一、概述
VC709板卡在Bank113上连接了4个SFP+光纤接口,可用于板间高速数据传递。使用Aurora IP,可以快速的构建数据收发链路,实现数据的系统间传递。
本文包含了Aurora IP的设置以及EXAMPLE_DESIGN的详细分析。
工具版本:Vivado2021.1
二、Aurora IP设置
页面1的设置如下图。
1)参考时钟的设置要匹配板上的实际情况,这里设置为200MHz,可参考前续文章《基于VC709构建FPGA开发学习平台(三)-GTH的参考时钟-CSDN博客》
2)一般第一次下载到板卡时,推荐打开VivadoLabTools选项,利用ILA和VIO等工具,对链路进行调试,调试完成后,再关闭即可。
3)GT的控制和状态端口可选择性的打开,一般只用到其中的loop_back端口设置自回环,以验证FPGA本身的问题。
页面2的设置如下图:
1)选择SFP+所在的GTH位置,对于VC709而言,SFP+接口位于BANK113,因此选择GTHQ3,通道1、2、3、4的顺序如图标注。
页面3的设置:
1)shared logic一般勾选“in the example design”,因为GT_REFCLK通常被一个BANK中的四个GT Channel复用,若被一个Channel包含到了Core中,会导致其它Channel无法使用。
确认后,生成Aurora IP 。
三、EXAMPLE_DESIGN结构分析:
EXAMPLE_DESIGN主要包含了4大部分:
1)与TX接口相连的FRAME_GEN模块,用于产生一定模式的发送数据;
2)与RX接口相连的FRAME_CHECK模块,用于对接收到的数据进行正确性验证;
3)ILA和VIO对工程的工作状态进行设置和监控;
4)Aurora IP本身。
四、FRAME_GEN数据产生模块:
FRAME_GEN模块用来按照既定的模式产生发送的数据,模块产生的数据类似于伪随机数的模式,利用移位+异或的方式产生数据。
1)模块在CHANNEL_UP为低时,一直处于复位状态:
aurora_64b66b_x1_frame_gen.v, line 151:
assign reset_i = RESET || (!CHANNEL_UP);
此时,pdu_lfsr_r寄存器被赋予了初始种子值16‘habcd,然后每次成功发送一次数据,就进行一次移位+异或操作,改变数据模式:
line 152~156:
//Generate random data using XNOR feedback LFSR
always @(posedge USER_CLK)
if(reset_i)
begin
pdu_lfsr_r <= `DLY 16'hABCD; //random seed value
end
else if(!TX_DST_RDY_N && !idle_r)
begin
pdu_lfsr_r <= `DLY {!{pdu_lfsr_r[3]^pdu_lfsr_r[12]^pdu_lfsr_r[14]^pdu_lfsr_r[15]},
pdu_lfsr_r[0:14]};
end
//Connect TX_D to the pdu_lfsr_r register
assign TX_D = {AURORA_LANES*4{pdu_lfsr_r}};
2)发送数据包
采用两个计数器:包计数器、包内数据计数器,对已发出的包和每个包内的数据进行计数,包计数的循环范围是0~15:
line 198~212:
//Use a counter to determine the size of the next frame to send
always @(posedge USER_CLK)
if(RESET_ii)
frame_size_r <= `DLY 4'h0;
else if(single_cycle_frame_r || eof_r)
frame_size_r <= `DLY frame_size_r + 1;
//Use a second counter to determine how many bytes of the frame have already been sent
always @(posedge USER_CLK)
if(RESET_ii)
bytes_sent_r <= `DLY 4'h0;
else if(sof_r)
bytes_sent_r <= `DLY 4'h1;
else if(!TX_DST_RDY_N && !idle_r)
bytes_sent_r <= `DLY bytes_sent_r + 1;
依据这两个计数器,每当包计数值frame_size_r == 0时,发送一个单周期包:
assign next_single_cycle_frame_c = (ifg_done_c && (frame_size_r == 0)) &&
(idle_r || single_cycle_frame_r || eof_r);
而在其它时刻发送的包长度取决于以下判断条件:
line 248:
assign next_data_cycle_c = (frame_size_r != bytes_sent_r) &&
(sof_r || data_cycle_r);
line 251:
assign next_eof_c = (frame_size_r == bytes_sent_r) &&
(sof_r || data_cycle_r);
综上,frame_gen模块产生的数据模式为:
frame #1 : 64‘hde56de56de56de56 (signle frame)
frame #2 : 64‘heaf3eaf3eaf3eaf3 → 64‘hf579f579f579f579 (sof_r产生结束)
frame #3 : 64‘h7abc7abc7abc7abc → 64‘hbd5ebd5ebd5ebd5e (data_cycle_r产生结束)
frame #4 : 64‘h5eaf5eaf5eaf5eaf → 64‘haf57af57af57af57 → 64‘h7abd7abd7abd7abd → 64‘hebd5ebd5ebd5ebd5 → 64‘h75ea75ea75ea75ea (data_cycle_r产生结束)
frame #5 : 64‘h3af53af53af53af5 → 64‘h9d7a9d7a9d7a9d7a → 64‘h4ebd4ebd4ebd4ebd → 64‘ha75ea75ea75ea75e → 64‘hd3afd3afd3afd3af → 64‘he9d7e9d7e9d7e9d7(data_cycle_r产生结束)
frame #6 : 64‘hf4ebf4ebf4ebf4eb → 64‘hfa75fa75fa75fa75 → 64‘hfd3afd3afd3afd3a → 64‘h7e9d7e9d7e9d7e9d → 64‘h3f4e3f4e3f4e3f4e → 64‘h1fa71fa71fa71fa7(data_cycle_r产生结束)
frame #7 .....
五、数据校验模块FRAME_CHECK:
采用同样的随机数生成方法,以de56为种子(匹配发送端的第一个数据),每接收到一个有效数据,就进行一次移位异或,由于采用的移位异或算法与发送端是一致的,因此二者生成的数据序列是一致的,从而实现正确性的对比。
line 149~155:
//Generate the PDU data using LFSR for data comparision
always @ (posedge USER_CLK)
if(reset_i)
pdu_lfsr_r <= `DLY 16'hD5E6;
else if(pdu_data_valid_c)
pdu_lfsr_r <= `DLY {!{pdu_lfsr_r[3]^pdu_lfsr_r[12]^pdu_lfsr_r[14]^pdu_lfsr_r[15]},
pdu_lfsr_r[0:14]};
产生序列的顺序为:de56 → eaf3 → f579 → 7abc ..... , 如果接收到的数据未发生过丢失,则刚好与发送端的数据一一匹配。若发生了数据丢失或误码,则DATA_ERR_COUNT+1:
line 305:
assign data_err_c[0] = ( pdu_data_valid_r && (RX_D_R[0:63] != pdu_cmp_data_r1[0:63]));
总结:
由于数据的产生和比较都是“内源”性的,无需用户参与,因此只要物理链路正常,CHANNEL_UP拉高后,两个模块即开始运行测试。CHANNEL_UP信号为低时,两个模块处于复位状态。
参考文献:
《PG074-Aurora 64B/66B v12.0 LogiCORE IP Product Guide》