FPGA---Aurora

本文介绍了Aurora_IP在FPGA之间的通讯作用,对比了8b/10b编码与64b/66b编码在数据位宽和带宽效率上的差异。8b/10b编码浪费20%带宽,适合小数据量传输,而64b/66b更适用于大数据量。文中提供了Aurora_IP的相关Verilog代码示例,包括AURORA_RST、AURORA_AXI模块的实现。
摘要由CSDN通过智能技术生成

1. Aurora_ip介绍(以8b/10b为例)

1.功能:两个fpga之间进行通讯的工具
2.区别:	8b/10b,axi_stream的数据位宽是32bit(我设置的)
		64b/66b,axi_stream的数据位宽是64bit(我设置的)
	为什么64b的比8b的好呢?
			因为8b的浪费了20%的带宽(也就是速度慢了)
	一般来说小数据量用8b就可以了,大数据量就得用64b了,具体还是要看项目的要求

ip核的设置

aurora_ip核
另外界面就不放了,那俩保持默认,或者你想初学时想要时钟少一点就看看第三个界面的设置吧,我懒得搞了

话不多说,直接放程序(初学者,我就不放过fifo的了,这个不过fifo的程序接收数据的时候跳了一下,别直接用哦,好好研究一下吧

 AURORA_TOP.V
module Aurora_TOP #(
	parameter DATA_LEN		= 32					,//这俩我是为了可以随时更改aurora的模式(8b或者64b的)
	parameter KEEP_LEN		= 4						
) (
	input						usr_rst				,//系统复位信号
	input						usr_clk				,//系统时钟,这里使用是为了产生aurora需要的两个复位信号,和init_clk直接连到一起的
	
	input						i_gt_clk_p			,//gt差分时钟,125mhz的
	input						i_gt_clk_n			,
	input						i_init_clk			,//初始化时钟,50mhz的

	output						o_aurora_txp		,//看名字
	output						o_aurora_txn		,

	input						i_aurora_rxp		,//看名字
	input						i_aurora_rxn			
);

	wire						s_reset				;
	wire						s_gt_reset			;

	wire						s_user_clk			;

	wire		[DATA_LEN-1:0]	s_axi_tx_tdata		;
	wire		[KEEP_LEN-1:0]	s_axi_tx_tkeep		;
	wire						s_axi_tx_tlast		;
	wire						s_axi_tx_tvalid		;
	wire						s_axi_tx_tready		;

	wire		[DATA_LEN-1:0]	s_axi_rx_tdata		;
	wire		[KEEP_LEN-1:0]	s_axi_rx_tkeep		;
	wire						s_axi_rx_tlast		;
	wire						s_axi_rx_tvalid		;

	wire						s_channel_up		;
	wire						s_lane_up			;

	wire						s_hard_err			;
	wire						s_soft_err			;
	wire						s_frame_err			;
//产生aurora需要的复位信号
	AURORA_RST u_Aurora_rst(
		.usr_clk				( usr_clk			),
		.usr_rst				( usr_rst			),

		.o_reset				( s_reset			),
		.o_gt_reset				( s_gt_reset		)
	);
//很简单的一个axi的程序
	AURORA_AXI u_Aurora_axi(
		.usr_clk				( s_user_clk		),
		.usr_rst				( usr_rst			),

		.i_channel_up			( s_channel_up		),

		.o_axi_tx_tdata			( s_axi_tx_tdata	),
		.o_axi_tx_tkeep			( s_axi_tx_tkeep	),
		.o_axi_tx_tlast			( s_axi_tx_tlast	),
		.o_axi_tx_tvalid		( s_axi_tx_tvalid	),
		.i_axi_tx_tready		( s_axi_tx_tready	),

		.i_axi_rx_tdata			( s_axi_rx_tdata	),
		.i_axi_rx_tkeep			( s_axi_rx_tkeep	),
		.i_axi_rx_tlast			( s_axi_rx_tlast	),
		.i_axi_rx_tvalid		( s_axi_rx_tvalid	)
	);

//初学时无关的输入都设置为0(我也是初学者,还不是很懂那些输入信号)
	aurora_8b10b_0 u_aurora_8b10b_0 (

		.reset					( s_reset			),
		.gt_reset				( s_gt_reset		),

		.gt_refclk1_p			( i_gt_clk_p		),
		.gt_refclk1_n			( i_gt_clk_n		),
		.init_clk_in			( i_init_clk		),
		.drpclk_in				( i_init_clk		),

		//speed = 3.125,lane_width = 4 --> data_width = 32
		//because 8b/10b,so data_width = 32*(10/8) = 40
		//so o_user_clk = 3.125g/40 = 78.125mhz,输出的user时钟,给子模块当时时钟用的

		.user_clk_out			( s_user_clk		),

		.channel_up				( s_channel_up		),//o
		.lane_up				( s_lane_up			),//o

		.s_axi_tx_tdata			( s_axi_tx_tdata	),//i
		.s_axi_tx_tkeep			( s_axi_tx_tkeep	),//i
		.s_axi_tx_tlast			( s_axi_tx_tlast	),//i
		.s_axi_tx_tvalid		( s_axi_tx_tvalid	),//i
		.s_axi_tx_tready		( s_axi_tx_tready	),//o

		.m_axi_rx_tdata			( s_axi_rx_tdata	),//o
		.m_axi_rx_tkeep			( s_axi_rx_tkeep	),//o
		.m_axi_rx_tlast			( s_axi_rx_tlast	),//o
		.m_axi_rx_tvalid		( s_axi_rx_tvalid	),//o
 
		.hard_err				( s_hard_err		),//o
		.soft_err				( s_soft_err		),//o
		.frame_err				( s_frame_err		),//o

		.rxp					( i_aurora_rxp		),//i
		.rxn					( i_aurora_rxn		),//i

		.txp					( o_aurora_txp		),//o
		.txn					( o_aurora_txn		),//o

		.sync_clk_out			( ),
		.gt_reset_out			( ),
		.gt_refclk1_out			( ),

		.loopback				( 3'b000),
		.drpaddr_in				( 'd0	),
		.drpen_in				( 'd0	),
		.drpdi_in				( 'd0	),
		.drprdy_out				( ),
		.drpdo_out				( ),
		.drpwe_in				( 'd0	),

		.power_down				( 1'b0	),
		.tx_lock				( ),
		.tx_resetdone_out		( ),
		.rx_resetdone_out		( ),
		.link_reset_out			( ),
		.pll_not_locked_out		( ),
		.sys_reset_out			( ),

		.gt0_qplllock_out		( ),
		.gt0_qpllrefclklost_out	( ),
		.gt_qpllclk_quad2_out	( ),
		.gt_qpllrefclk_quad2_out( )
	);

endmodule
 AURORA_RST.V(这个是借鉴哪个博主的,忘了)
module AURORA_RST (
	input						usr_clk				,
	input						usr_rst				,

	output						o_reset				,
	output						o_gt_reset			
	
);
	parameter GT_RESET_START	= 128				;//说了她最少得拉低128个时钟
	parameter GT_RESET_END		= 256				;//另一个复位只要比上面长就行,256=128*2,就是凭心里咋舒服咋来
	parameter RESET_MAX			= GT_RESET_END + GT_RESET_START;

	reg							r_reset				;
	reg							r_gt_reset			;

	reg					[10:0]	r_start_cnt			;
	wire						s_start				;

	reg					[10:0]	r_cnt				;

	assign s_start = (r_start_cnt < RESET_MAX - 1 && r_start_cnt > 'd0);

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_start_cnt <= 'd0;
		end else begin
			if(r_start_cnt == RESET_MAX - 1) begin
				r_start_cnt <= r_start_cnt;
			end else begin
				r_start_cnt <= r_start_cnt + 1'b1;
			end
		end
	end

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_cnt <= 'd0;
		end else if(s_start) begin
			if(r_cnt == RESET_MAX - 1) begin
				r_cnt <= 'd0;
			end else begin
				r_cnt <= r_cnt + 1'b1;
			end
		end else ;
	end

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_gt_reset <= 1'b0;
		end else begin
			if(r_cnt == GT_RESET_START - 1) begin
				r_gt_reset <= 1'b1;
			end else if (r_cnt == GT_RESET_END - 1 || r_cnt == 0 ) begin
				r_gt_reset <= 1'b0;
			end 
		end
	end

	assign o_gt_reset = r_gt_reset;

	always @ (posedge usr_clk) begin
		if (s_start) begin
			r_reset <= 1'b1;
		end else begin
			r_reset <= 1'b0;
		end
	end

	assign o_reset = r_reset;

endmodule
 AURORA_AXI.V,这个就不多介绍了,很简单的(当时学的时候主要是初始化有点烦)
module AURORA_AXI #(
	parameter DATA_LEN			= 32				,
	parameter KEEP_LEN			= 4				
) (
	input						usr_clk				,
	input						usr_rst				,

	input						i_channel_up		,

	output		[DATA_LEN-1:0]	o_axi_tx_tdata		,
	output		[KEEP_LEN-1:0]	o_axi_tx_tkeep		,
	output						o_axi_tx_tlast		,
	output						o_axi_tx_tvalid		,
	input						i_axi_tx_tready		,

	input		[DATA_LEN-1:0]	i_axi_rx_tdata		,
	input		[KEEP_LEN-1:0]	i_axi_rx_tkeep		,
	input						i_axi_rx_tlast		,
	input						i_axi_rx_tvalid		
);

	localparam NUM				= 63				;

	localparam C_TXIDLE			= 4'h0				;
	localparam C_TXDATA			= 4'h1				;
	localparam C_TXEND			= 4'hf				;

	localparam C_RXIDLE			= 4'h0				;
	localparam C_RXDATA			= 4'h1				;
	localparam C_RXEND			= 4'hf				;

	reg					[ 3:0]	r_t_now				;
	reg					[ 3:0]	r_t_next			;

	reg					[ 3:0]	r_r_now				;
	reg					[ 3:0]	r_r_next			;

	reg			[DATA_LEN-1:0]	r_axi_tx_tdata		;
	reg			[DATA_LEN-1:0]	r_axi_rx_tdata		;

	reg					[10:0]	r_tx_cnt			;
	reg							r_axi_tx_tlast		;
	reg							r_axi_tx_tvalid		;


	assign o_axi_tx_tkeep = 4'hf;

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_t_now <= C_TXIDLE;
		end else begin
			r_t_now <= r_t_next;
		end
	end

	always @ (*) begin
		r_t_next = C_TXIDLE;
		case (r_t_now)
			C_TXIDLE	:	begin
								if(i_channel_up) begin
									r_t_next = C_TXDATA;
								end else begin
									r_t_next = C_TXIDLE;
								end
							end

			C_TXDATA	:	begin
								if(o_axi_tx_tlast && o_axi_tx_tvalid && i_axi_tx_tready) begin
									r_t_next = C_TXEND;
								end else begin
									r_t_next = C_TXDATA;
								end
							end

			C_TXEND		:	begin
									r_t_next = C_TXIDLE;
							end

			default		:	r_t_next = C_TXIDLE;
		endcase
	end

	always @(posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_axi_tx_tlast <= 1'b0;
		end else begin
			if(i_axi_tx_tready && o_axi_tx_tvalid) begin
				if(r_tx_cnt == 'd63) begin
					r_axi_tx_tlast <= 1'b1;
				end else begin
					r_axi_tx_tlast <= 1'b0;
				end
			end else ;
		end
	end

	assign o_axi_tx_tlast = r_axi_tx_tlast;

	always @(posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_axi_tx_tvalid <= 1'b0;
		end else begin
			if(i_axi_tx_tready) begin
				if(r_t_next == C_TXDATA) begin
					r_axi_tx_tvalid <= 1'b1;
				end else begin
					r_axi_tx_tvalid <= 1'b0;
				end
			end else ;
		end
	end

	assign o_axi_tx_tvalid = r_axi_tx_tvalid;

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_tx_cnt <= 'd0;
		end else begin
			if(r_t_next == C_TXDATA && i_axi_tx_tready) begin
				r_tx_cnt <= r_tx_cnt + 'd1;
			end else if(r_t_next == C_TXEND) begin
				r_tx_cnt <= 'd0;
			end 
		end
	end

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_axi_tx_tdata <= 'dz;
		end else begin
			if(r_t_next == C_TXDATA && i_axi_tx_tready) begin
				r_axi_tx_tdata <= r_axi_tx_tdata + 'd1;
			end else if(r_t_next == C_TXIDLE) begin
				r_axi_tx_tdata <= 'd0;
			end 
		end
	end

	assign o_axi_tx_tdata = r_axi_tx_tdata;

	always @ (posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_r_now <= C_RXIDLE;
		end else begin
			r_r_now <= r_r_next;
		end
	end

	always @ (*) begin
		r_r_next = C_RXIDLE;
		case (r_r_now)
			C_RXIDLE	:	begin
								if(i_axi_rx_tvalid) begin
									r_r_next = C_RXDATA;
								end else begin
									r_r_next = C_RXIDLE;
								end
							end

			C_RXDATA	:	begin
								if(i_axi_rx_tlast) begin
									r_r_next = C_RXEND;
								end else begin
									r_r_next = C_RXDATA;
								end
							end

			C_RXEND		:	begin
								r_r_next = C_RXIDLE;
							end

			default		:	r_r_next = C_RXIDLE;	
		endcase
	end

	always @(posedge usr_clk or posedge usr_rst) begin
		if(usr_rst) begin
			r_axi_rx_tdata <= 'dz;
		end else begin
			if(i_axi_rx_tvalid) begin
				r_axi_rx_tdata <= i_axi_rx_tdata;
			end else begin
				r_axi_rx_tdata <= 'dz;
			end
		end
	end


endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值