零、系统概述
这个程序实现了如下功能:
1、三组4位数据 合并成 一组12位数据输出;
2、四组12位数据 转为 三组16位数据输出;
3、16位数据 拆分为 两组8位数据输出;
4、8位数据经过Aurora核的处理通过高速串行总线发送给第二个Aurora核。
功能1、2、3均在Aurora_TX模块的FRAME_GEN中实现,其余部分为:
TX-only Simplex Aurora Core为实现发送功能的Aurora核
RX-only Simplex Aurora Core为实现接收功能的Aurora核
FRAME_RECE为处理接收数据的模块
系统总框图
↓↓↓↓↓
TRA_TOP模块总框图
↓↓↓↓↓
一、Tra4To12实现模块
1、功能一框图
2、功能实现原理
这个模块实现了三个时钟采集三组数据,在第四个时钟并行输出三组数据的功能。
当valid_in信号拉高时、第一个时钟上升沿时,in_data的4位数据被存入寄存器中。经过三个时钟上升沿后,寄存器存入三组共12位数输出到out_data,并且valid_out被拉高,表示输出数据有效。
当valid_out置低时,out_data为0,方便调试不成功时排查错误。
3、功能一代码
`timescale 1ns/1ps
module tra4to12(
input [3:0] in_data ,
input clk ,
input rst_n ,
input valid_in ,
output [11:0] out_data ,
output reg valid_out
);
reg [1:0] cycle_status;
reg [11:0] out_data_cache;
parameter cycle0 =0;
parameter cycle1 =1;
parameter cycle2 =2;
always@(posedge clk or posedge rst_n)
begin
if(!valid_in) valid_out<=0;
else
begin
if(!rst_n)
begin
out_data_cache[11:0]<=12'b0;
valid_out<=0;
cycle_status<=cycle0;
end
else
begin
case(cycle_status)
cycle0:
begin
out_data_cache[11:8]<=in_data;
cycle_status<=cycle1;
valid_out<=0;
end
cycle1:
begin
out_data_cache[7:4]<=in_data;
cycle_status<=cycle2;
valid_out<=0;
end
cycle2:
begin
out_data_cache[3:0]<=in_data;
cycle_status<=cycle0;
valid_out<=1;
end
endcase
end
end
end
assign out_data=valid_out?out_data_cache:12'b0;
endmodule
二、Tra12To16实现模块
1、功能二框图
2、功能二实现原理
这个模块实现了不同位数的数据互相转换的功能。
在cycle_status的每一状态,判断valid_in是否拉高,拉高则读取in_data存入out_data_cache;置低则维持状态。
在cycle_status的cycle1、cycle2、cycle3分别输出高16位、中16位、低16位。
当valid_out置低时,out_data为0,方便调试不成功时排查错误。
3、功能二代码
`timescale 1ns/1ps
module tra12to16(
input [11:0] in_data ,
input clk ,
input rst_n ,
input valid_in ,
output reg [15:0] out_data ,
output reg valid_out
);
reg [1:0] cycle_status;
reg [1:0] cycle_status_next;
reg [47:0] out_data_cache;
parameter cycle0 =0;
parameter cycle1 =1;
parameter cycle2 =2;
parameter cycle3 =3;
always@(posedge clk or posedge rst_n)
begin
if(!rst_n)
begin
out_data_cache[47:0]<= 48'h000000;
valid_out<=0;
cycle_status<=cycle0;
out_data<=0;
end
else
begin
case(cycle_status)
cycle0:
begin
if(valid_in)
begin
out_data_cache[47:36]<=in_data;
cycle_status<=cycle1;
valid_out<=0;
end
else
begin
cycle_status<=cycle0;
valid_out<=0;
end
end
cycle1:
begin
if(valid_in)
begin
out_data_cache[35:24]<=in_data;
cycle_status<=cycle2;
valid_out<=1;
end
else
begin
cycle_status<=cycle1;
valid_out<=0;
end
end
cycle2:
begin
if(valid_in)
begin
out_data_cache[23:12]<=in_data;
cycle_status<=cycle3;
valid_out<=1;
end
else
begin
cycle_status<=cycle2;
valid_out<=0;
end
end
cycle3:
begin
if(valid_in)
begin
out_data_cache[11:0]<=in_data;
cycle_status<=cycle0;
valid_out<=1;
end
else
begin
cycle_status<=cycle3;
valid_out<=0;
end
end
endcase
end
end
always@(valid_out)
begin
if(!valid_out) out_data<=16'h0;
else
case(cycle_status)
cycle2:out_data<=out_data_cache[47:32];
cycle3:out_data<=out_data_cache[31:16];
cycle0:out_data<=out_data_cache[15:0];
endcase
end
endmodule
三、Tra16To8实现模块
1、功能三框图
2、功能三实现原理
这个模块实现了将一组数据拆分成两组数据分时输出的功能,可用作串行转并行模块。
当valid_in信号拉高时、第一个时钟上升沿时,in_data的高8位送到输出端口out_data,低8位存入out_data_cache寄存器;下一个时钟判断有数据进入,则表示数据输入过快,产生了冲突,拉高fault错误标志位,若无数据进入则输出out_data_cache寄存器的输出。
3、功能三代码
`timescale 1ns/1ps
module tra16to8(
input [15:0] in_data ,
input clk ,
input rst_n ,
input valid_in ,
output reg [7:0] out_data ,
output reg valid_out ,
output reg fault
);
parameter cycle0 =0;
parameter cycle1 =1;
reg [7:0] out_data_cache;
reg [1:0] cycle_status;
always@(posedge clk or posedge rst_n)
begin
if(!rst_n)
begin
out_data_cache[7:0]<=8'b0;
valid_out<=0;
cycle_status<=cycle0;
out_data<=0;
fault<=0;
end
else
begin
case(cycle_status)
cycle0:
begin
if(valid_in)
begin
{out_data,out_data_cache}<=in_data;
cycle_status<=cycle1;
valid_out<=1;
end
else
begin
cycle_status<=cycle0;
valid_out<=0;
end
end
cycle1:
begin
if(valid_in)
begin
fault<=1;
valid_out<=0;
end
else
begin
out_data<=out_data_cache;
cycle_status<=cycle0;
valid_out<=1;
fault<=0;
end
end
endcase
end
end
endmodule
四、TRA_TOP数位转换顶层模块
1、框图2、代码
module tra_top(
input sys_clk ,
input rst_n ,
input [3:0] in_data ,
input valid_in ,
output [7:0] out_data ,
output fault ,
output valid_out
);
wire [11:0] out_data_6;
wire [15:0] out_data_8;
tra4to12 u_tra4to12(
.in_data (in_data) ,
.clk (sys_clk) ,
.rst_n (rst_n) ,
.valid_in (valid_in) ,
.out_data (out_data_6) ,
.valid_out (valid_out_6)
);
tra12to16 u_tra12to16(
.in_data (out_data_6) ,
.clk (sys_clk) ,
.rst_n (rst_n) ,
.valid_in (valid_out_6) ,
.out_data (out_data_8) ,
.valid_out (valid_out_8)
);
tra16to8 u_tra16to8(
.in_data (out_data_8) ,
.clk (sys_clk) ,
.rst_n (rst_n) ,
.valid_in (valid_out_8) ,
.out_data (out_data) ,
.valid_out (valid_out) ,
.fault (fault)
);
endmodule
五、Tra_top的Test_bench代码
1、代码
`timescale 1ns/1ps
module tra_top_tb(
output wire [7:0] out_data,
output wire [0:0] fault,
output wire [0:0] valid_out
);
reg [0:0] sys_clk;
reg [0:0] rst_n;
reg [3:0] in_data;
reg [0:0] valid_in;
tra_top u_tra_top(
.sys_clk (sys_clk) ,
.rst_n (rst_n) ,
.in_data (in_data) ,
.valid_in (valid_in) ,
.out_data (out_data) ,
.fault (fault) ,
.valid_out (valid_out)
);
initial
begin
sys_clk =0;
valid_in =1;
in_data =4'h0;
rst_n =1;
#200 rst_n=0;
#200 rst_n=1;
#5000 $stop;
end
always #10 sys_clk=!sys_clk;
always #20 in_data=in_data+4'b1;
endmodule
2、测试文件原理
输入数据为递增数,valid_in一直为高,表示输入数据一直有效。
3、测试波形
3.1 Tra4To12局部波形分析
in_data在640000ps、660000ps、680000ps输入4‘h0、4‘h1、4‘h2三组数,out_data_12在680000ps时刻输出12’h012。分析波形图可知out_data_12在740000ps、800000ps、860000ps,输出12’h345、12’h678、12’h9ab。并且数据输出有效时valid_out_12为高,其余时间为低。
3.2 Tra12To16局部波形分析
valid_out_12在680000ps、740000ps、800000ps、860000ps分别输入12’h012、12’h345、12’h678、12’h9ab。valid_out_16在760000ps、820000ps、880000ps分别输出16’h0123、16’h4567、16’h89ab。
并且数据输出有效时valid_out_12为高,其余时间为低。
3、Tra16to8局部波形分析
valid_out_16在760000ps输出16’h0123,out_data在780000ps、800000ps分别输出8’h01、8’h23
4、延时分析
数位转换模块,在640000ps输入4’h0,在780000ps输出8’h01,延时140000ps,共7个时钟周期;在860000ps输入4’hb,在920000ps输出8’hab,延时60000ps,共三个时钟周期。
六、Aurora官方示例的原理
PG046 Aurora 8B/10B手册中提到Aurora核有如下应用:
Applications
Aurora 8B/10B cores can be used in a wide variety of applications because of their low resource cost, scalable throughput, and flexible data interface. Examples of core applications include:
• Chip-to-chip links: Replacing parallel connections between chips with high-speed serial connections can significantly reduce the number of traces and layers required on a PCB. The core provides the logic needed to use GTP, GTX, and GTH transceivers, with minimal FPGA resource cost.
• Board-to-board and backplane links: The core uses standard 8B/10B encoding, making it compatible with many existing hardware standards for cables and backplanes. Aurora 8B/10B cores can be scaled, both in line rate and channel width, to allow inexpensive legacy hardware to be used in new, high-performance systems.
• Simplex connections (unidirectional): The Aurora protocol provides alternate ways to perform unidirectional channel initialization making possible the use of the GTP, GTX, and GTH transceivers in the absence of a back channel and to reduce costs due to unused full-duplex resources.
简单翻译就是Aurora核可连接以多个不同型号的FPGA芯片、可以通过backplane连接不用的电路板、可以简单的进行单向数据传输。
Aurora IP核配有Xlinx官方示例,下图为官方示例Test_Bench的框图
Test_bench中中DUT1和DUT2的FRAME_GEN模块即上图的traffic.frame_gen_i,通过如下代码生成伪随机数。
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hABCD; //random seed value
end
else if(!TX_DST_RDY_N && !idle_r)
begin
data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},
data_lfsr_r[0:14]};
end
然后经traffic.frame_chk_axi_to_ll_pdu_i做接口转换后,aurora_module_i模块通过差分对TXN、TXP(上图未标注出)发送出去。
同时aurora_module_i模块的RXN、RXP可同时接受数据,经traffic.frame_chk_axi_to_ll_pdu_i模块做格式转换后,传输到traffic.frame_check_i进行校验。校验代码如下
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hD5E6; //random seed value
end
else if(CHANNEL_UP)
begin
if(data_valid_c)
data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},
data_lfsr_r[0:14]};
end
else
begin
data_lfsr_r <= `DLY 16'hD5E6; //random seed value
end
其中D5E6是发送数据ABCD经过如下公式计算后得到的数。
{!{data_lfsr_r[3]data_lfsr_r[12]data_lfsr_r[14]^data_lfsr_r[15]}, data_lfsr_r[0:14]};
其中接受有效标志位CHANNEL_UP为通道建立标志位,只有该标志位拉高时,传输的数据才有效。
七、修改、精简Aurora示例
因为上述示例已实现两个Aurora核的数据传输功能,所以对其进行加加减减即可使用。
1、将两个可同时收发的核,修改为一个收、一个发。
在aurora_8b10b_0_tb.v文件中,修改模块的例化名,删除接收模块的RXP、RXN接口、删除发送模块的TXP、TXN接口;删除发送模块的traffic.frame_chk_axi_to_ll_pdu_i、traffic.frame_check_i模块和相关错误计数端口;删除接收模块的traffic.frame_gen_i、traffic.frame_chk_axi_to_ll_pdu_i模块。
2、修改发送模块的aurora_8b10b_0_frame_gen.v文件
在该文件中添加如下代码,例化tra_top模块并添加初始化语句。
tra_top u_tra_top(
.sys_clk (USER_CLK) ,
.rst_n (!RESET) ,
.in_data (in_data) ,
.valid_in (valid_in) ,
.out_data (tra_out_data) ,
.fault () ,
.valid_out (tra_valid_out)
);
reg [3:0] in_data;
reg [0:0] valid_in;
wire [7:0] tra_out_data;
wire [0:0] valid_out;
always@(posedge USER_CLK)
begin
if(RESET)
begin
in_data <=4'h0;
valid_in <=1'h1;
in_data <=4'h0;
end
else
in_data <=in_data+4'b1;
end
将tra_top模块输出的tra_out_data、tra_valid_out连接到data_lfsr_r数据输出端
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY {tra_valid_out,7'b0,tra_out_data}; //random seed value
end
else if(!TX_DST_RDY_N && !idle_r)
begin
data_lfsr_r <= `DLY {tra_valid_out,7'b0,tra_out_data};
end
发送数据共16位,最高位为数据有效位,低8位为数据位。
八、仿真波形
TX_D前后产生了8012、0012、8034、8056、0056、8078、809a、009a、80bc、80de、00de,接收端在9个时钟后接收到了完整的数据。