基于Aurora核的数位转换及数据传输实现

零、系统概述

这个程序实现了如下功能:
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个时钟后接收到了完整的数据。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值