FPGA設計千兆以太網(wǎng)MAC(1)——通過MDIO接口配置與檢測PHY芯片
掃描二維碼
隨時隨地手機看文章
一、前言
本文設計思想采用明德?lián)P至簡設計法。以太網(wǎng)這一高效實用的數(shù)據(jù)傳輸方式應用于各個領域,如網(wǎng)絡交換設備,高速網(wǎng)絡相機等。雖然各FPGA廠商都提供MAC IP核,但大多收費,有時無法破解。不同廠家之間無法移植,而且為了通用性考慮犧牲了效率,因此自己動手寫一個以太網(wǎng)MAC是個不錯的選擇。
本博文討論通過MDIO接口管理PHY芯片來驗證其正確工作,為在此基礎上設計MAC邏輯開個頭。PHY芯片采用RTL8211EGVB,選用GMII接口與MAC連接。下面我們來開始第一步,在此之前明確設計目的:檢測PHY芯片是否完成自動協(xié)商 鏈路速率是否達到1000M。所以要從datasheet中了解到芯片引腳 寄存器地址 接口時序。
二、設計分析
管理幀格式如下:
讀寫操作時序:
MDC為MAC驅(qū)動時鐘信號,MDIO是串行數(shù)據(jù)總線,需要連接上拉電阻保證idle狀態(tài)下高電平。其中前導碼包含32個比特“1”,PHY地址根據(jù)芯片引腳連接而定,此處為01.turn around域是為了防止讀操作時數(shù)據(jù)沖突,在讀操作過程中MAC和PHY均在第1比特處進入高阻態(tài),PHY在第2比特處驅(qū)動MDIO接口為低電平以占據(jù)總線控制權(quán)。注意兩點:第一如果時鐘信號在讀寫操作后停止,時鐘必須保證至少7個時鐘周期持續(xù)翻轉(zhuǎn)且MDIO高電平從而保證之前的操作完成。故在設計中可以等待一段時間后再拉低時鐘使能信號。第二兩個操作之間至少一個idle比特。
正確驅(qū)動接口時序需要關注AC characterisics.

很明顯MAC驅(qū)動總線時,在MDC下降沿更新數(shù)據(jù)。而PHY驅(qū)動總線時,MDC上升沿后更新數(shù)據(jù)。根據(jù)datasheet中的timing參數(shù)設定MDC時鐘周期是800ns,MAC接收PHY數(shù)據(jù)時下降沿采樣。
接下來關注要訪問的內(nèi)部寄存器地址,首先讀取PHY寄存器數(shù)據(jù)以檢測其工作狀態(tài),若發(fā)現(xiàn)異常再考慮寫入數(shù)據(jù)。這里讀取基本模式狀態(tài)寄存器0X01的bit5,若為1說明自動協(xié)商完成。第二個寄存器是PHY特定狀態(tài)寄存器0X11中的[15:14]和13,分別是當前速率和全/半雙工通信模式。若檢測到自動協(xié)商完成,且工作在1000M全雙工模式下,說明工作正確。
三、硬件架構(gòu)與狀態(tài)機設計
所有準備工作完成,現(xiàn)在開始設計。按照“自頂向下”設計原則,規(guī)劃好整體結(jié)構(gòu)和模塊間接口,再設計內(nèi)部狀態(tài)機一步步實現(xiàn)邏輯功能。
Mdio_ctrl模塊負責完成PHY芯片的配置與檢測邏輯,Mdio接口模塊完成讀寫操作時序。此處僅通過讀操作簡單檢測PHY狀態(tài),暫不進行配置,故兩模塊工作狀態(tài)跳轉(zhuǎn)如圖所示:
剩下的工作就是把兩個狀態(tài)機實現(xiàn)出來,非常簡單。有需要的朋友可以參考一下,關于芯片的具體參數(shù)詳見:Realtek RTL8211E(G)-VB(VL)-CG Datasheet 1.8.上代碼!
四、代碼編寫
MDIO控制模塊:
MDIO時序接口模塊:
頂層封裝:
五、功能仿真
之后編寫testbench進行行為仿真:
1 `timescale 1 ns/1 ps 2 3 `define BIT_CNT uut.mdio_interface.bit_cnt 4 5 module phy_manage_tb(); 6 7 //時鐘和復位 8 reg clk ; 9 reg rst_n; 10 11 //uut的輸入信號 12 reg mdio_en; 13 14 //uut的輸出信號 15 wire link_up; 16 wire chk_done; 17 wire mdc; 18 wire mdio; 19 wire [16-1:0] back_data1,back_data2; 20 21 //時鐘周期,單位為ns,可在此修改時鐘周期。 22 parameter CYCLE = 10; 23 24 //復位時間,此時表示復位3個時鐘周期的時間。 25 parameter RST_TIME = 2 ; 26 27 defparam uut.mdio_ctrl.MS_CYC = 100; 28 29 //待測試的模塊例化 30 phy_manage uut( 31 .clk (clk) , 32 .rst_n (rst_n) , 33 34 .mdio_en (mdio_en) , 35 .link_up (link_up) , 36 .chk_done (chk_done) , 37 38 .mdc (mdc) , 39 .mdio (mdio) 40 ); 41 42 43 //生成本地時鐘50M 44 initial begin 45 clk = 1; 46 forever 47 #(CYCLE/2) 48 clk=~clk; 49 end 50 51 //產(chǎn)生復位信號 52 initial begin 53 rst_n = 1; 54 #1; 55 rst_n = 0; 56 #(CYCLE*RST_TIME); 57 rst_n = 1; 58 end 59 60 //輸入信號din0賦值方式 61 initial begin 62 #1; 63 //賦初值 64 mdio_en = 0; 65 #(10*CYCLE); 66 mdio_en = 1; 67 #(1*CYCLE); 68 mdio_en = 0; 69 //開始賦值 70 #100_000; 71 $stop; 72 end 73 74 //模擬PHY響應 75 76 //data 77 assign back_data1 = {16'b0000_0000_0010_0000}; 78 assign back_data2 = {16'b1010_0000_0000_0000}; 79 80 integer i = 0,j = 0; 81 initial begin 82 forever begin 83 wait(uut.mdio_interface.state_c == 1 && `BIT_CNT == 47 ); 84 @(posedge mdc); 85 force mdio = 0; 86 @(posedge mdc); 87 j = j+1; 88 if(j == 1) 89 force mdio = back_data1[16-1-i+1]; 90 else 91 force mdio = back_data2[16-1-i+1]; 92 93 wait(uut.mdio_interface.state_c == 0); 94 @(posedge mdc); 95 release mdio; 96 end 97 end 98 99 initial begin100 forever begin101 @(posedge mdc);102 if(uut.mdio_interface.state_c == 2)begin103 #10;104 i = i+1;105 end106 else 107 i = 0;108 end109 end110 111 112 endmodule phy_manage_tb
testbench中利用force強迫更新mdio雙向端口方式模擬PHY芯片響應。仿真波形上半部分為MDIO控制模塊信號,下半部分則是MDIO時序接口模塊信號。可見當讀取寄存器數(shù)值滿足PHY工作需求時,link_up信號拉高,證明此時MAC可以傳輸數(shù)據(jù)給PHY。
六、板級調(diào)試
完整的設計,板級調(diào)試是必不可少的。真正地將接口調(diào)通,PHY芯片正確響應才能說明達到設計目的。頂層封裝測試工程,內(nèi)部例化:差分時鐘緩沖原語、PLL、PHY管理頂層封裝以及VIO ILA調(diào)試IP。我們來看下原理圖頂層:
測試工程頂層:
mdio_test
時鐘引腳約束文件:
clk_pin
有一點相信調(diào)試過以太網(wǎng)的人大多都跳過一個坑:沒有驅(qū)動PHY的復位輸入信號。本人也在此處栽過跟頭,這里直接連續(xù)賦值拉高PHY芯片復位信號。關于板級調(diào)試還有個小技巧,根據(jù)高亞軍老師的書籍得知,將set up debug生成的ILA探針相關約束命令單獨放入一個約束文件便于調(diào)試IP的管理和修改,debug約束文件就不貼出來了。
查看debug波形,MDIO時序接口模塊在釋放MDIO串行總線時,由于存在上拉電阻為高電平,下一個MDC時鐘上升沿時刻,PHY拉低MDIO信號響應并得到總線控制權(quán),開始輸出數(shù)據(jù)。
得到讀取的兩個寄存器數(shù)據(jù),根據(jù)數(shù)值分析滿足:PHY自動協(xié)商完成,且工作在全雙工1000Mbps速率下。
最終RJ45接口綠色指示燈常亮,表明自動協(xié)商完成,網(wǎng)絡連接正確。到此簡易的PHY芯片檢測管理模塊設計完成。





