FPGA实现千兆/百兆自适应以太网UDP传输
0、前言
筆者最近在項目中需要使用到ZYNQ中PL端做以太網(wǎng)UDP傳輸并且需要支持100M/1000M自適應(yīng)切換。使用的PHY型號為RTL8211。以下分享的主要為利用已有的1000M協(xié)議棧修改為100M并且實現(xiàn)二者自適應(yīng)切換,IP核主要實現(xiàn)以下功能
1、實現(xiàn)100M/1000M自適應(yīng)
2、回環(huán)測試
PS:完整的IP核文件下載地址:https://download.csdn.net/download/qq_24025329/87019436
1、軟硬件環(huán)境和前置條件
筆者采用的接口是RGMII接口,即100M模式下單邊沿采樣,時鐘頻率為25M。在1000M模式下使用雙邊沿采樣,時鐘頻率為125M。所以在千兆模式下需要使用原語對數(shù)據(jù)采樣,這里就不過多贅述了,這里默認已經(jīng)擁有了可以實現(xiàn)1000M通訊的協(xié)議棧了。
2、實現(xiàn)步驟
第一步:千兆-百兆接收數(shù)據(jù)轉(zhuǎn)換模塊
這里筆者偷了個懶,既然已經(jīng)有了千兆模式下讀取的數(shù)據(jù),那么我們只需要根據(jù)千兆與百兆之間的采樣模式進行轉(zhuǎn)換就可以讀出來正確的數(shù)據(jù)了。具體思想如下
1、千兆為雙邊沿采樣,百兆為單邊沿采樣。所以在千兆模式RGMII轉(zhuǎn)換為GMII接口下跑百兆的速度讀出來的8bit數(shù)據(jù)中高四位=低四位的。所以我們將讀出來的數(shù)據(jù)只保留四位即可。下圖為千兆模式下的采樣
?2、時鐘采用PHY提供的時鐘,即百兆模式下25M千兆模式下為125M即可。具體實現(xiàn)代碼如下
`timescale 1ns / 1ps module eth_speed(input Rst_n, //系統(tǒng)復(fù)位//以太網(wǎng)GMII接口input gmii_rx_clk , //GMII接收時鐘input gmii_rx_dv , //GMII接收數(shù)據(jù)有效信號input [7:0] gmii_rxd , //GMII接收數(shù)據(jù)//速度轉(zhuǎn)換后以太網(wǎng)GMII接口output gmii_rx_clk_s , //GMII接收時鐘output gmii_rx_dv_s , //GMII接收數(shù)據(jù)有效信號output reg[7:0] gmii_rxd_s //GMII接收數(shù)據(jù)); //==========參數(shù)定義=============// parameter SPEED = 1000;//1000Mbps//==========寄存器定義===========// reg out_clk; //輸出時鐘 reg count_s; //二分?jǐn)?shù)據(jù)計數(shù) reg data0_en; reg data1_en; //數(shù)據(jù)有效位//==========組合邏輯運算=============// assign gmii_rx_clk_s = out_clk;//輸出時鐘二分頻 assign gmii_rx_dv_s = data0_en && data1_en;//接收數(shù)據(jù)有效//==========時序邏輯============// //輸入時鐘二分頻 always @(posedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)out_clk <= 1'd0; elseout_clk <= ~out_clk;//二分?jǐn)?shù)據(jù)計數(shù) //第一個數(shù)據(jù)來臨后的第一個下降沿=1 // always @(negedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)count_s <= 1'd0; else if(!gmii_rx_dv)//數(shù)據(jù)無效 清零count_s <= 1'd0; elsecount_s = ~count_s;//反轉(zhuǎn)//采集數(shù)據(jù)1 下降沿采集數(shù)據(jù) always @(negedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)gmii_rxd_s[3:0] <= 4'd0; else if(gmii_rx_dv && (!count_s))//接收數(shù)據(jù)有效并且二分頻時鐘位低電平gmii_rxd_s[3:0] <= gmii_rxd[3:0];//采集數(shù)據(jù)2 下降沿采集數(shù)據(jù) always @(negedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)gmii_rxd_s[7:4] <= 4'd0; else if(gmii_rx_dv && (count_s))//接收數(shù)據(jù)有效并且二分頻時鐘位低電平gmii_rxd_s[7:4] <= gmii_rxd[3:0];//采集數(shù)據(jù)1有效位 always @(posedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)data0_en <= 1'd0; else if(!count_s) //第一個數(shù)據(jù)采樣的周期if(gmii_rx_dv) //有效data0_en <= 1'd1;elsedata0_en <= 1'd0; elsedata0_en <= data0_en;//采集數(shù)據(jù)2有效位 always @(posedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)data1_en <= 1'd0; else if(count_s) //第二個數(shù)據(jù)采樣的周期if(gmii_rx_dv) //有效data1_en <= 1'd1;elsedata1_en <= 1'd0; elsedata1_en <= data1_en;endmodule第二步:千兆-百兆接收數(shù)據(jù)轉(zhuǎn)換模塊
發(fā)送方面就不能偷懶了,只能自己寫了一個百兆模式下的發(fā)送,代碼如下
`timescale 1ns / 1psmodule eth_speed_tx(input Rst_n,input gmii_rx_clk, //來自PHY的時鐘//獲得數(shù)據(jù)接口input [7:0] data_in, //GMII數(shù)據(jù)input data_en, //GMII使能output data_clk, //GMII時鐘,用于獲取發(fā)送數(shù)據(jù),是RGMII的1/2//RGMII接口output rgmii_txc, //RGMII的時鐘output reg[3:0]rgmii_txd, //RGMII發(fā)送的數(shù)據(jù)output rgmii_tx_ctl //RGMII發(fā)送控制 );//========寄存器定義===========// reg rgmii_txc_2_s;//發(fā)送時鐘的二分頻 并滯后90° reg en_delay;//輸入使能延遲//==========邏輯==============// assign data_clk = rgmii_txc_2_s; assign rgmii_tx_ctl = data_en|en_delay; assign rgmii_txc = gmii_rx_clk;//==========時序邏輯==========// //時鐘二分頻 用于獲得數(shù)據(jù) 并滯后90° always@(negedge rgmii_txc or negedge Rst_n) if(!Rst_n)rgmii_txc_2_s <= 1'd0; elsergmii_txc_2_s <= ~rgmii_txc_2_s;//發(fā)送數(shù)據(jù)賦值 always @(negedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)rgmii_txd <= 4'd0; else if(data_en && rgmii_txc_2_s)//要發(fā)送第一個4bit數(shù)據(jù) 低位rgmii_txd <= data_in[3:0]; else if(data_en && (!rgmii_txc_2_s))//要發(fā)送第二個4bit數(shù)據(jù) 高位rgmii_txd <= data_in[7:4]; elsergmii_txd <= rgmii_txd;//使能延遲 always @(negedge gmii_rx_clk or negedge Rst_n) if(!Rst_n)en_delay <= 1'd0; else if(data_en && (!rgmii_txc_2_s))en_delay <= 1'd1; elseen_delay <= 1'd0;endmodule第三步:百兆千兆切換邏輯
百兆和千兆模式下切換本質(zhì)上就是切換RGMII的接口信號源,具體的邏輯較為簡單如圖所示
?其中SPEED為選擇開關(guān),該值可以是定義的參數(shù),也可以當(dāng)作接口有外部提供。
最后
該IP核是筆者在項目中解決自己的問題所編寫,水平有限如有疏漏敬請指正。
總結(jié)
以上是生活随笔為你收集整理的FPGA实现千兆/百兆自适应以太网UDP传输的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VUE 拦截浏览器后退弹窗,弹窗一闪立刻
- 下一篇: 大数据环境中资源优化配置策略研究(非原创