10G_ethernet学习记录(1):10G Ethernet PCS/PMA ip的使用
参考资料:pg068:10G Ethernet PCS/PMA v6.0
开发平台:vivado2020.2
开发板卡:axck060(黑金板卡)
FPGA芯片:xcku060ffva_1156_2_i
修改日志:
2024/11/30:仿真调通,添加仿真波形
0,基础知识:
了解XGMII,XAUI
XGMII:
XGMII接口共74根连线,单端信号,采用HSTL/SSTL_2逻辑,端口电压1.5V/2.5V,由于SSTL_2的端口电压高,功耗大,现在已很少使用。HSTL即High Speed Transceiver Logic,高速发送逻辑的意思。SSTL,即Stub Series Terminated Logic,短路终止逻辑,主要用于高速内存接口,SSTL目前存在两种标准,SSTL_3是3.3V标准;SSTL_2是2.5V标准。
主要包括三个部分。一是从MAC层到物理层的发送数据接口,二是从MAC层到物理层的接收数据接口,三是MAC层和物理层之间数据管理的MDIO/MDC接口
74根线(参考千兆以太网的rxc,rxd[7:0],):RXD:32,RXC:4,RXLR:1;TXD:32,TXC:4,TXLR:1
XAUI:10 Gigabit attachment unit interface 10G附属单元接口
由于受电气特性的影响,XGMII接口的PCB走线最大传输距离仅有7cm,并且XGMII接口的连线数量太多,给实际应用带来不便,因此,在实际应用中,XGMII接口通常被XAUI接口代替,XAUI即10 Gigabit attachment unit interface,10G附属单元接口,XAUI在XGMII的基础上实现了XGMII接口的物理距离扩展,将PCB走线的传输距离增加到50cm,使背板走线成为可能。
源端XGMII把收发32位宽度数据流分为4个独立的lane通道,每个lane通道对应一个字节,经XGXS(XGMII Extender Sublayer)完成8B/10B编码后,将4个lane分别对应XAUI的4个独立通道,XAUI端口速率为:2.5Gbps * 1.25 * 4=12.5Gbps。
在发送端的XGXS模块中,将TXD[31:0]/ RXD[31:0],TXC[3:0]/ RXC[3:0], TXC/ RXC转换成串行数据从TX Lane[3:0]/ RX Lane[3:0]中发出去,在接收端的XGXS模块中,串行数据被转换成并行,并且进行时钟恢复和补偿,完成时钟去抖,经过5B/4B解码后,重新聚合成XGMII。
XAUI接口采用差分线,收发各四对,CML逻辑,AC耦合方式,耦合电容在10nF~100nF之间。
XAUI接口可以直接接光模块,如XENPAK/X2等。也可以转换成一路10G信号XFI,接XFP/SFP+等。
1,手册阅读
我们使用的是PCS/PMA部分,基于Ultrascale系列。pg068包含7系列与Ultrascale。所以有些信号在不同的系列有不同的选择。比如user_clk,7系列中是core_clk,Ultrascale中是txuserclk_2。根据自己的需求进行区分。
1.1 框架
xilinx提供两种:10GBASE-R(免费不要钱),10GBASE-KR(需要购买,背板)。我们选择使用10GBASE-R来实现10G以太网的PCS/PMA。
- XGMII: 链接10千兆以太网MAC层(user_rtl)与PCS/PMA层(ip);
- Transmit path,:包含 scrambler, 64b/66b encoder and Gearbox;(10G以太网是基于64/66编码来进行的);
- Receive path: 包含 block synchronization, descrambler, decoder and BER (Bit Error Rate) monito ;(64//66对齐功能)
10G Ethernet PCS/PMA (ip)与user_logic(MAC)相连接,我们的目的是做MAC层。PCS/PMA交给IP核。
1.2 port_interface
1.2.1 xgmii port
XGMII接口是FPGA内部的,不是与外部的PHY相连接(不用考虑走线之类的)。这个接口回用于IP核与用户编写的MAC层之间的连接。
rxd:64bit,参考时钟为156.25Mhz
rxd32bit,参考时钟为312.5Mhz
在FPGA中,要考虑时序问题,xilinx推荐的方式是大位宽,低时钟。所以使用rxd:64bit。
1.2.2 optical module
另外,该IP还提供了光模块接口。(不用自己编写o_sfp_disable了(。-ω-))
在官方example的tb文件中,signal_detect = 1'b1 , tx_fault = 1'b0;(这两个要给对,不然会pcs_rx_lock一直为未知状态,我在这里仿真卡了两天,重构之后按照example_prj才发祥这里给错了!!!!!)
开发板板卡的原理图中:
mode0连接高电平,loss连接高电平。signal_detect = ~(mode0 || loss) = 0。
1.2.3 MDIO接口(等待施工)
管理接口,未使用,先放着
1.2.4 CLOCK and RESET port
在生成ip核时,勾选Include Shared Logic in example design。 可以更好地了解ip的时钟和复位逻辑。
详细会在后续的example_prj学习中了解。
有些时钟是7serial,有些时ultrascale系列。
1.2.5 10GBASE-KR Training Interface
KR版本,不是我们学习的目标。
1.2.6 DRP interface port
drp控制接口,没用过。
1.2.7 Miscellaneous Ports(仿真相关)
这里面主要是sim_speedup_control用于加快仿真速度。
注意,这个信号与srio中的仿真加速不一样。srio中直接使能就行。
在官方提供的tb文件中 ,
sim_speedup_control 先拉低,等待全局复位信号拉低之后,reset拉低之后。才拉高。
我们还可以看到,在仿真加速中,对这个接口的描述。当我们想要implementation时(上板),只要不先拉低,再拉高。这个端口就不会作用。相应的,这个端口的作用条件就是先拉低,再拉高。
1.2.8 configuration port
10G Ethernet PCS/PMA ip的配置端口是用了一个[535:0] configuration_vector大位宽矢量来控制的。
需要根据要求去查找对应控制目标。
我现在只使用了PMA Loopback Enable,PCS Loopback Enable。以及125us timer Control
Status Vector反应当前的状态
我们需要 PMA/PMD RX Link Status ,PCS RX Link Status 来判断接收端是否建立链接。
1.3 designing with the core
1.3.0 data_interface
rxc = 0 ,表示数据位
rxc = 1 , 表示控制位,常用有开始FB,结束FD,错误FE,默认07。
64bit接口下,有两种开始帧(开始位置不一致,与64/66编码中一致)
1.S开始在8‘b0000_1000。
2,还有一种S在8‘b1000_0000。字节对齐发送。
1.3.1 clocking
数据位宽:64bit ;ultrascale系列时钟架构:
- 首先通过一个IBUFDS_GTE3将refclk_n,refclk_p转换为单端w_refclk信号。
- 因为10G ethernet的速度为10.3125,超过了cpll所能提供的速率,需要使用qpll,
- qpll产生的qpll_clk,qpll_refclk输入进GTE3中产生对应rxoutclk,txoutclk.
- rxoutclk,txoutclk使用bufg产生userclk,userclk2。
XGMII接口的发送信号与txuserclk2是同步的!!!
1.3.2 reset
1.3.3 mult core (后续施工)
1.3.4 loopback (后续施工)
2,IP操作
2.1 生成10G Ethernet PCS/PMA ip核
配置如下:BASE-R是免费的。64bit大位宽。
勾选 include shared logic in example design
生成example_prj
2.2 example_pri学习
生成的prj中包含如下模块:
1,gt_common_block:用于处理 gth模块;
用于产生qpllclk与qpllrefclk
module ten_gig_eth_pcs_pma_0_gt_common # (
parameter WRAPPER_SIM_GTRESET_SPEEDUP = "false" ) //Does not affect hardware
(
input refclk,
input qpllreset,
output qpll0lock,
output qpll0outclk,
output qpll0outrefclk
);
gt_common_block仿真波形
2,pcs_pma共享时钟,复位模块;
仿真波形:
3,tb文件:官方编写的仿真顶层,包含一些仿真行为。施工中
3,编写工程
3.1 工程搭建
整体工程如下:
vivado中架构:
基本单元都是从example中参照过来的。
其中
configuration_vector[535:0]
status_vector[447:0]
这两个模块,example中有详细的划分,结合手册选择自己所需要的。
assign configuration_vector[0] = pma_loopback;
assign configuration_vector[14:1] = 0;
assign configuration_vector[15] = pma_reset;
assign configuration_vector[16] = global_tx_disable;
assign configuration_vector[79:17] = 0;
assign configuration_vector[83:80] = 0;
assign configuration_vector[109:84] = 0;
assign configuration_vector[110] = pcs_loopback;
assign configuration_vector[111] = pcs_reset;
assign configuration_vector[169:112] = test_patt_a_b;
assign configuration_vector[175:170] = 0;
assign configuration_vector[233:176] = test_patt_a_b;
assign configuration_vector[239:234] = 0;
assign configuration_vector[240] = data_patt_sel;
assign configuration_vector[241] = test_patt_sel;
assign configuration_vector[242] = rx_test_patt_en;
assign configuration_vector[243] = tx_test_patt_en;
assign configuration_vector[244] = prbs31_tx_en;
assign configuration_vector[245] = prbs31_rx_en;
assign configuration_vector[269:246] = 0;
assign configuration_vector[271:270] = 0;
assign configuration_vector[383:272] = 0;
assign configuration_vector[399:384] = 16'h4C4B;
assign configuration_vector[511:400] = 0;
assign configuration_vector[512] = set_pma_link_status;
assign configuration_vector[515:513] = 0;
assign configuration_vector[516] = set_pcs_link_status;
assign configuration_vector[517] = 0;
assign configuration_vector[518] = clear_pcs_status2;
assign configuration_vector[519] = clear_test_patt_err_count;
assign configuration_vector[535:520] = 0;
assign pma_link_status = status_vector[18];
assign rx_sig_det = status_vector[48];
assign pcs_rx_link_status = status_vector[226];
assign pcs_rx_locked = status_vector[256];
assign pcs_hiber = status_vector[257];
assign teng_pcs_rx_link_status = status_vector[268];
assign pcs_err_block_count = status_vector[279:272];
assign pcs_ber_count = status_vector[285:280];
assign pcs_rx_hiber_lh = status_vector[286];
assign pcs_rx_locked_ll = status_vector[287];
assign pcs_test_patt_err_count = status_vector[303:288];
3.2 仿真
在经过几天的调试之后,将仿真调通,更新仿真波形(2024/11/30)
编写了一个数据生成模块,按照64bit的形式编写,每1000个周期trigger一次,发送一段固定的数据,并进行loopback,查看发送与接受的xgmii_data,xgmii_control是否一致。
module _10g_data_gen_test
(
input i_xgmii_clk ,
input i_xgmii_rst ,
input [ 63:0] i_xgnii_rxd ,
input [ 7:0] i_xgmii_rxc ,
output [ 63:0] o_xgmii_txd ,
output [ 7:0] o_xgmii_txc
);
localparam P_TRAGER_GAP = 1000 ;
localparam P_SEND_LEN = 10 ;
reg [ 63:0] r_o_xgmii_txd ;
reg [ 7:0] r_o_xgmii_txc ;
reg [ 15:0] r_cnt ;
reg r_triger ;
reg [ 15:0] r_triger_cnt ;
reg r_run ;
assign o_xgmii_txd = r_o_xgmii_txd ;
assign o_xgmii_txc = r_o_xgmii_txc ;
always @(posedge i_xgmii_clk) begin
if (i_xgmii_rst) begin
r_triger_cnt <= 'd0;
end
else if(r_triger_cnt == P_TRAGER_GAP - 1) begin
r_triger_cnt <= 'd0;
end
else if(!r_run) begin
r_triger_cnt <= r_triger_cnt + 1;
end
else begin
r_triger_cnt <= 'd0;
end
end
always @(posedge i_xgmii_clk) begin
if (i_xgmii_rst) begin
r_run <= 'd0;
end
else if(r_cnt == P_SEND_LEN - 1) begin
r_run <= 'd0;
end
else if(r_triger) begin
r_run <= 'd1;
end
else begin
r_run <= r_run;
end
end
always @(posedge i_xgmii_clk) begin
if (i_xgmii_rst) begin
r_triger <= 'd0;
end
else if(r_triger_cnt == P_TRAGER_GAP - 1) begin
r_triger <= 'd1;
end
else begin
r_triger <= 'd0;
end
end
always@(posedge i_xgmii_clk,posedge i_xgmii_rst)
begin
if(i_xgmii_rst)
r_cnt <= 'd0;
else if(r_cnt == P_SEND_LEN - 1)
r_cnt <= 'd0;
else if(r_run || r_cnt)
r_cnt <= r_cnt + 1;
else
r_cnt <= r_cnt;
end
always@(posedge i_xgmii_clk,posedge i_xgmii_rst)
begin
if(i_xgmii_rst)
r_o_xgmii_txd <= 64'h07070707_07070707;
else if(!r_run)
r_o_xgmii_txd <= 64'h07070707_07070707;
else case(r_cnt)
0 :r_o_xgmii_txd <= 64'hFB555555_55555555;
1 :r_o_xgmii_txd <= 64'hD5000102_03040506;
2 :r_o_xgmii_txd <= 64'h0708090a_0b0c0d0e;
3 :r_o_xgmii_txd <= 64'h0f101112_13141516;
4 :r_o_xgmii_txd <= 64'h1718191a_1b1c1d1e;
5 :r_o_xgmii_txd <= 64'h1f202122_23242526;
6 :r_o_xgmii_txd <= 64'h2728292a_2b2c2d2e;
7 :r_o_xgmii_txd <= 64'h2f303132_33343536;
8 :r_o_xgmii_txd <= 64'h3738393a_3b3c3d3e;
9 :r_o_xgmii_txd <= 64'h3f404142_434445FD;
default :r_o_xgmii_txd <= 'd0;
endcase
end
always@(posedge i_xgmii_clk,posedge i_xgmii_rst)
begin
if(i_xgmii_rst)
r_o_xgmii_txc <= 8'b1111_1111;
else if(r_run && r_cnt == 0)
r_o_xgmii_txc <= 8'b1000_0000;
else if(r_run && r_cnt == 9)
r_o_xgmii_txc <= 8'b0000_0001;
else if(r_run)
r_o_xgmii_txc <= 8'b0000_0000;
else
r_o_xgmii_txc <= 8'b1111_1111;
end
endmodule
另外,高速接口基本都有endian的变换,我们常用的是大端,gt常用的为小端。注意查看exp仿真。我编写了两个转换函数,是可以综合的,如下:
function [63:0] transfer_data;
input [ 63:0] i_ori_data ;
begin
transfer_data[7 :0 ] = i_ori_data[63:56];
transfer_data[15:8 ] = i_ori_data[55:48];
transfer_data[23:16] = i_ori_data[47:40];
transfer_data[31:24] = i_ori_data[39:32];
transfer_data[39:32] = i_ori_data[31:24];
transfer_data[47:40] = i_ori_data[23:16];
transfer_data[55:48] = i_ori_data[15:8 ];
transfer_data[63:56] = i_ori_data[7 :0 ];
end
endfunction
function [7:0] transfer_rxc;
input [ 7:0] i_ori_char ;
begin
transfer_rxc[0] = i_ori_char[7];
transfer_rxc[1] = i_ori_char[6];
transfer_rxc[2] = i_ori_char[5];
transfer_rxc[3] = i_ori_char[4];
transfer_rxc[4] = i_ori_char[3];
transfer_rxc[5] = i_ori_char[2];
transfer_rxc[6] = i_ori_char[1];
transfer_rxc[7] = i_ori_char[0];
end
endfunction
传输波形:
接受波形 :
我进行了endian变换,用于后续的mac处理。
3.3上板
等待网卡中,上板之后更新。。。