1. 概述
基于RGMII時序廣泛應用于以太網通信中,基于Xilinx的三速以太網時序分析,不同的Xilinx系列方法不一樣。當使用2路以上以太網通信,KU系列FPGA的MAC核需要進行修改,以支持2路以太網和滿足時序要求。以下筆者對修改的部分進行說明,希望對廣大開發者有所幫助,如果有不對的地方歡迎指針。
2. 代碼修改
主要針對以上三個文件修改,詳細的可以打開我們的配套工程閱讀代碼,下圖是第一個以太網的三個文件
tri_mode_ethernet_mac_1_rgmii_v2_0_if.v文件關鍵部分修改如下:
發送部分odelay3的代碼修改,原來默認的代碼對于rgmii_tx發送時序調整是通過級聯一個idelay3模塊來實現,這里注釋掉級聯的idelay3模塊,默認為" TIME"模式最大是1ns延遲調整,修改odelay3模塊的delay模式為"COUNT模式",這樣每調整1個tap代表了0.005ns,最大可以調整512個tap,這樣我們可以實現最大2ns以上的延遲調整
//InstantiatetheOutputDelayprimitive(delayoutputby2ns).Inorderto //achieve2ns,anODELAYiscascadedwithanIDELAYfromthebitslice //immediatelybelowit. ODELAYE3#( .DELAY_VALUE(300), .DELAY_FORMAT("COUNT"),//UnitsoftheDELAY_VALUE(COUNT,TIME) .DELAY_TYPE("FIXED"), //.CASCADE("MASTER"), .REFCLK_FREQUENCY(333.333), .SIM_DEVICE("ULTRASCALE") ) delay_rgmii_tx_clk( .ODATAIN(rgmii_txc_odelay), .DATAOUT(rgmii_txc_obuf), .CLK(1'b0), .CE(1'b0), .INC(1'b0), .CNTVALUEIN(9'h0), .CNTVALUEOUT(), .LOAD(1'b0), .RST(1'b0), .CASC_IN(1'b0), .CASC_RETURN(1'b0), .CASC_OUT(), .EN_VTC(1'b1) ); /* IDELAYE3#( .DELAY_VALUE(320), .DELAY_TYPE("FIXED"), .CASCADE("SLAVE_END"), .REFCLK_FREQUENCY(333.333), .SIM_DEVICE("ULTRASCALE_PLUS") ) delay_rgmii_tx_clk_casc( .IDATAIN(1'b0), .DATAOUT(delay_rgmii_tx_clk_casc_return), .DATAIN(1'b0), .CLK(1'b0), .CE(1'b0), .INC(1'b0), .CNTVALUEIN(9'h0), .CNTVALUEOUT(), .LOAD(1'b0), .RST(1'b0), .CASC_IN(delay_rgmii_tx_clk_casc_out), .CASC_RETURN(1'b0), .CASC_OUT(), .EN_VTC(1'b1) ); */ //--------------------------------------------------------------------------- //RGMIITransmitterLogic: //driveTXsignalsthroughIOBsontoRGMIIinterface //--------------------------------------------------------------------------- //Encodergmiictlsignal assignrgmii_tx_ctl_int=tx_en_from_mac^tx_er_from_mac; //InstantiateDoubleDataRateOutputcomponents.Then //putdataandcontrolsignalsthroughODELAYcomponentsto //providesimiliarnetdelaystothoseseenontheclksignal. assigngmii_txd_falling=txd_from_mac[7:4]; genvari; generatefor(i=0;i<4;?i=i+1) ?????begin?:?txdata_out_bus ???????ODDRE1?#( ????????? ??????????.SRVAL?????????(1'b0) ???????) ???????rgmii_txd_out?( ??????????.Q?????????????(rgmii_txd_odelay[i]), ??????????.C?????????????(tx_clk), ??????????.D1????????????(txd_from_mac[i]), ??????????.D2????????????(gmii_txd_falling[i]), ??????????.SR????????????(tx_reset) ???????); ? ??????ODELAYE3?#( ??????????.DELAY_VALUE??????(0), ??????????.DELAY_TYPE???????("FIXED"), ??????????.REFCLK_FREQUENCY?(333.333), ??????.SIM_DEVICE???????("ULTRASCALE") ??????? ???????) ???????delay_rgmii_txd?( ??????????.ODATAIN???????(rgmii_txd_odelay[i]), ??????????.DATAOUT???????(rgmii_txd_obuf[i]), ??????????.CLK???????????(1'b0), ??????????.CE????????????(1'b0), ??????????.INC???????????(1'b0), ??????????.CNTVALUEIN????(9'h0), ??????????.CNTVALUEOUT???(), ??????????.LOAD??????????(1'b0), ??????????.RST???????????(1'b0), ??????????.CASC_IN???????(1'b0), ??????????.CASC_RETURN???(1'b0), ??????????.CASC_OUT??????(), ??????????.EN_VTC????????(1'b1) ???????); ? ?????end ???endgenerate
同理,接收部分idelay3的代碼修改,原來默認為" TIME"模式最大是1ns延遲調整,修改idelay3模塊的delay模式為"COUNT模式",這樣每調整1個tap代表了0.005ns,最大可以調整512個tap,這樣我們可以實現最大2ns以上的延遲調整
IDELAYE3 #( .DELAY_FORMAT ("COUNT"), // Units of the DELAY_VALUE (COUNT, TIME) .DELAY_TYPE ("FIXED"), .REFCLK_FREQUENCY (333.333), .DELAY_VALUE (330), // Input delay value setting .SIM_DEVICE ("ULTRASCALE") ) delay_rgmii_rx_ctl ( .IDATAIN (rgmii_rx_ctl_ibuf), .DATAOUT (rgmii_rx_ctl_delay), .DATAIN (1'b0), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (1'b0), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); genvar j; generate for (j=0; j<4; j=j+1) ? ? begin : rxdata_bus ? ? ? IDELAYE3 #( ? ? ? .DELAY_FORMAT ? ? ("COUNT"), ? ? // Units of the DELAY_VALUE (COUNT, TIME) ? ? ? ? ? ? ? ? ?.DELAY_TYPE ? ? ? ("FIXED"), ? ? ? ? ?.REFCLK_FREQUENCY (333.333), ? ? ? ? ?.DELAY_VALUE ? ? ?(330), ? ? ? ? ? // Input delay value setting ? ? ? ? ?.SIM_DEVICE ? ?("ULTRASCALE") ? ? ? ) ? ? ? delay_rgmii_rxd ( ? ? ? ? ?.IDATAIN ? ? ? (rgmii_rxd_ibuf[j]), ? ? ? ? ?.DATAOUT ? ? ? (rgmii_rxd_delay[j]), ? ? ? ? ?.DATAIN ? ? ? ?(1'b0), ? ? ? ? ?.CLK ? ? ? ? ? (1'b0), ? ? ? ? ?.CE ? ? ? ? ? ?(1'b0), ? ? ? ? ?.INC ? ? ? ? ? (1'b0), ? ? ? ? ?.CNTVALUEIN ? ?(9'h0), ? ? ? ? ?.CNTVALUEOUT ? (), ? ? ? ? ?.LOAD ? ? ? ? ?(1'b0), ? ? ? ? ?.RST ? ? ? ? ? (1'b0), ? ? ? ? ?.CASC_IN ? ? ? (1'b0), ? ? ? ? ?.CASC_RETURN ? (1'b0), ? ? ? ? ?.CASC_OUT ? ? ?(), ? ? ? ? ?.EN_VTC ? ? ? ?(1'b1) ? ? ? ); ? ? end ? endgenerate
下圖是第二個以太網的三個文件,由于需要貢獻一部分FPGA的delay_ctr資源,他們的代碼稍微有點差異。
修改方法和第一個以太網修改方法一樣
ODELAYE3 #( .DELAY_VALUE (300), .DELAY_FORMAT ("COUNT"), // Units of the DELAY_VALUE (COUNT, TIME) .DELAY_TYPE ("FIXED"), //.CASCADE ("MASTER"), .REFCLK_FREQUENCY (333.333), .SIM_DEVICE ("ULTRASCALE") ) delay_rgmii_tx_clk ( .ODATAIN (rgmii_txc_odelay), .DATAOUT (rgmii_txc_obuf), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (1'b0), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); /* IDELAYE3 #( .DELAY_VALUE (320), .DELAY_TYPE ("FIXED"), .CASCADE ("SLAVE_END"), .REFCLK_FREQUENCY (333.333), .SIM_DEVICE ("ULTRASCALE_PLUS") ) delay_rgmii_tx_clk_casc ( .IDATAIN (1'b0), .DATAOUT (delay_rgmii_tx_clk_casc_return), .DATAIN (1'b0), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (delay_rgmii_tx_clk_casc_out), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); */ //--------------------------------------------------------------------------- // RGMII Transmitter Logic : // drive TX signals through IOBs onto RGMII interface //--------------------------------------------------------------------------- // Encode rgmii ctl signal assign rgmii_tx_ctl_int = tx_en_from_mac ^ tx_er_from_mac; // Instantiate Double Data Rate Output components. Then // put data and control signals through ODELAY components to // provide similiar net delays to those seen on the clk signal. assign gmii_txd_falling = txd_from_mac[7:4]; genvar i; generate for (i=0; i<4; i=i+1) ? ? begin : txdata_out_bus ? ? ? ODDRE1 #( ? ? ? ? ?.SRVAL ? ? ? ? (1'b0) ? ? ? ) ? ? ? rgmii_txd_out ( ? ? ? ? ?.Q ? ? ? ? ? ? (rgmii_txd_odelay), ? ? ? ? ?.C ? ? ? ? ? ? (tx_clk), ? ? ? ? ?.D1 ? ? ? ? ? ?(txd_from_mac), ? ? ? ? ?.D2 ? ? ? ? ? ?(gmii_txd_falling), ? ? ? ? ?.SR ? ? ? ? ? ?(tx_reset) ? ? ? ); ? ? ?ODELAYE3 #( ? ? ? ? ?.DELAY_VALUE ? ? ?(0), ? ? ? ? ?.DELAY_TYPE ? ? ? ("FIXED"), ? ? ? ? ?.REFCLK_FREQUENCY (333.333), ? ? ?.SIM_DEVICE ? ? ? ("ULTRASCALE") ? ? ? ) ? ? ? delay_rgmii_txd ( ? ? ? ? ?.ODATAIN ? ? ? (rgmii_txd_odelay), ? ? ? ? ?.DATAOUT ? ? ? (rgmii_txd_obuf), ? ? ? ? ?.CLK ? ? ? ? ? (1'b0), ? ? ? ? ?.CE ? ? ? ? ? ?(1'b0), ? ? ? ? ?.INC ? ? ? ? ? (1'b0), ? ? ? ? ?.CNTVALUEIN ? ?(9'h0), ? ? ? ? ?.CNTVALUEOUT ? (), ? ? ? ? ?.LOAD ? ? ? ? ?(1'b0), ? ? ? ? ?.RST ? ? ? ? ? (1'b0), ? ? ? ? ?.CASC_IN ? ? ? (1'b0), ? ? ? ? ?.CASC_RETURN ? (1'b0), ? ? ? ? ?.CASC_OUT ? ? ?(), ? ? ? ? ?.EN_VTC ? ? ? ?(1'b1) ? ? ? ); ? ? end ? endgenerate
接收部分
IDELAYE3 #( .DELAY_FORMAT ("COUNT"), .DELAY_TYPE ("FIXED"), .REFCLK_FREQUENCY (333.333), .DELAY_VALUE (250), // Input delay value setting .SIM_DEVICE ("ULTRASCALE") ) delay_rgmii_rx_ctl ( .IDATAIN (rgmii_rx_ctl_ibuf), .DATAOUT (rgmii_rx_ctl_delay), .DATAIN (1'b0), .CLK (1'b0), .CE (1'b0), .INC (1'b0), .CNTVALUEIN (9'h0), .CNTVALUEOUT (), .LOAD (1'b0), .RST (1'b0), .CASC_IN (1'b0), .CASC_RETURN (1'b0), .CASC_OUT (), .EN_VTC (1'b1) ); genvar j; generate for (j=0; j<4; j=j+1) ? ? begin : rxdata_bus ? ? ? IDELAYE3 #( ? ? ? ? ?.DELAY_FORMAT ? ? ("COUNT"), ? ? ? ? ?.DELAY_TYPE ? ? ? ("FIXED"), ? ? ? ? ?.REFCLK_FREQUENCY (333.333), ? ? ? ? ?.DELAY_VALUE ? ? ?(250), ? ? ? ? ? // Input delay value setting ? ? ? ? ? ? ? ? ? ? ? ?.SIM_DEVICE ? ?("ULTRASCALE") ? ? ? ) ? ? ? delay_rgmii_rxd ( ? ? ? ? ?.IDATAIN ? ? ? (rgmii_rxd_ibuf[j]), ? ? ? ? ?.DATAOUT ? ? ? (rgmii_rxd_delay[j]), ? ? ? ? ?.DATAIN ? ? ? ?(1'b0), ? ? ? ? ?.CLK ? ? ? ? ? (1'b0), ? ? ? ? ?.CE ? ? ? ? ? ?(1'b0), ? ? ? ? ?.INC ? ? ? ? ? (1'b0), ? ? ? ? ?.CNTVALUEIN ? ?(9'h0), ? ? ? ? ?.CNTVALUEOUT ? (), ? ? ? ? ?.LOAD ? ? ? ? ?(1'b0), ? ? ? ? ?.RST ? ? ? ? ? (1'b0), ? ? ? ? ?.CASC_IN ? ? ? (1'b0), ? ? ? ? ?.CASC_RETURN ? (1'b0), ? ? ? ? ?.CASC_OUT ? ? ?(), ? ? ? ? ?.EN_VTC ? ? ? ?(1'b1) ? ? ? ); ? ? end ? endgenerate
以上也能看出第二個以太網和第一個以太網的時序調整有所差異。
3. 約束文件修改
由于我們在tri_mode_ethernet_mac_1_rgmii_v2_0_if.v中完成了時序的調整,因此需要注釋以下約束
時序約束部分修改和硬件上PHY的delay延遲設置有關系,米聯客的FPGA的PHY以太網芯片rx 有2ns延遲,tx沒有2ns延遲。因此rgmii_rx數據是源同步中心對齊方式分析,而rgmii_tx數據是源源步邊沿對齊方式分析,米聯客使用的是RTL8211FD芯片,關鍵的時序參數如下:
因此給出如下時序約束:
############################################################ # RX Clock period Constraints (per instance) # ############################################################ # Receiver clock period constraints: please do not relax set rx_clk [get_clocks -of [get_ports rgmii_rxc]] ############################################################ # Obtain input clocks from top level XDC # ############################################################ set ip_gtx_clk [get_clocks -of_objects [get_ports gtx_clk]] # #### ####### ########## ############# ################# #BLOCK CONSTRAINTS ############################################################ # For Setup and Hold time analysis on RGMII inputs # ############################################################ # define a virtual clock to simplify the timing constraints create_clock -name [current_instance .]_rgmii_rx_clk -period 8 set rgmii_rx_clk [current_instance .]_rgmii_rx_clk # Identify RGMII Rx Pads only. # This prevents setup/hold analysis being performed on false inputs, # eg, the configuration_vector inputs. set_input_delay -clock [get_clocks $rgmii_rx_clk] -max -1.5 [get_ports {rgmii_rxd rgmii_rx_ctl}] set_input_delay -clock [get_clocks $rgmii_rx_clk] -min -2.5 [get_ports {rgmii_rxd rgmii_rx_ctl}] set_input_delay -clock [get_clocks $rgmii_rx_clk] -clock_fall -max -1.5 -add_delay[get_ports {rgmii_rxd rgmii_rx_ctl}] set_input_delay -clock [get_clocks $rgmii_rx_clk] -clock_fall -min -2.5 -add_delay[get_ports {rgmii_rxd rgmii_rx_ctl}] set_false_path -rise_from [get_clocks $rgmii_rx_clk] -fall_to $rx_clk -setup set_false_path -fall_from [get_clocks $rgmii_rx_clk] -rise_to $rx_clk -setup set_false_path -rise_from [get_clocks $rgmii_rx_clk] -rise_to $rx_clk -hold set_false_path -fall_from [get_clocks $rgmii_rx_clk] -fall_to $rx_clk -hold set_multicycle_path -from [get_clocks $rgmii_rx_clk] -to $rx_clk -setup 0 set_multicycle_path -from [get_clocks $rgmii_rx_clk] -to $rx_clk -hold -1 ############################################################ # For Setup and Hold time analysis on RGMII outputs # ############################################################ create_generated_clock -name [current_instance .]_rgmii_tx_clk -divide_by 1 -source[get_pins {tri_mode_ethernet_mac_i/rgmii_interface/rgmii_txc_ddr/C}] [get_ports rgmii_txc] set rgmii_tx_clk [current_instance .]_rgmii_tx_clk set_output_delay -0.5 -max -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd rgmii_tx_ctl}] set_output_delay -1.2 -min -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd rgmii_tx_ctl}] set_output_delay -0.5 -max -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd rgmii_tx_ctl}] -clock_fall -add_delay set_output_delay -1.2 -min -clock [get_clocks $rgmii_tx_clk] [get_ports {rgmii_txd rgmii_tx_ctl}] -clock_fall -add_delay set_false_path -rise_from $ip_gtx_clk -fall_to [get_clocks $rgmii_tx_clk] -setup set_false_path -fall_from $ip_gtx_clk -rise_to [get_clocks $rgmii_tx_clk] -setup set_false_path -rise_from $ip_gtx_clk -rise_to [get_clocks $rgmii_tx_clk] -hold set_false_path -fall_from $ip_gtx_clk -fall_to [get_clocks $rgmii_tx_clk] -hold set_multicycle_path -from $ip_gtx_clk -to [get_clocks $rgmii_tx_clk] 0 -setup set_multicycle_path -from $ip_gtx_clk -to [get_clocks $rgmii_tx_clk] -1 -hold
這里時序分析是比較難理解的部分,尤其是根據datasheet分析時序要求,更多的關于時序相關的內容,請看米聯客時序課程相關內容。
審核編輯:湯梓紅
-
FPGA
+關注
關注
1629文章
21729瀏覽量
603011 -
以太網
+關注
關注
40文章
5419瀏覽量
171603 -
Xilinx
+關注
關注
71文章
2167瀏覽量
121305 -
時序約束
+關注
關注
1文章
115瀏覽量
13416
發布評論請先 登錄
相關推薦
評論