FPGA------------ SRIO通信(1)发送

一、系统结构

        分为四个模块。外部控制单元,SWR_fifo,AXI_fifo,SRIO IP核。之间的主要连线关系如图所示。



二、外部控制单元。

        此单元用来产生需要发送的数据data以及写使能信号wen。主要产生的过程比较简单。这里发送720*576byte的数据,由于SRIO是64bit的数据  因此,将数据进行组合发送,共发送64bit的数据个数为 720*576/8 = 51480

always @(posedge sys_clk)
    begin
	if (~sys_rstn) 
	    begin
		k7_srio_dma_wren <= 1'b0;
		cnt_data	 <= 16'd0;
	    end 
	else 
	    begin
		if ((cnt_40ms >= 24'd1) && (cnt_40ms <= 24'd51840)) 
		    begin		// 720x576=414720 byte
			k7_srio_dma_wren	<= 1'b1;
			cnt_data		<= cnt_data + 1; //发送的数据++
		    end 
		else 
		    begin
			k7_srio_dma_wren <= 1'b0;
			cnt_data	 <= 16'd0;
		    end
	    end
	end

assign	 k7_srio_dma_data = {4{cnt_data[7:0], cnt_data[15:8]}}; //64bit   SRIO要发送的数据

三、SWR_fifo

        用于缓存输入的数据,在状态机进入SWRITE之后,读取出数据。

fwft_fifo_w64	swr_fifo
(
	.rst					(inner_log_rst	),
	.wr_clk					(user_dma_clk	),
	.wr_en					(user_dma_en	),
	.din					(user_dma_data	),
			
	.prog_full_thresh		        (9'd470		),
	.prog_full				(user_dma_full	),
	.full					(		),
			
	.rd_clk					(log_clk	),
	.rd_en					(dma_read_en	),  //swr fifo读使能
	.dout					(dma_data_out	),  //swr fifo读数据
	.empty					(user_dma_emtpy),
	.prog_empty_thresh	                (9'd29		),	
	.prog_empty				(dma_fifo_empty),
	.rd_data_count			        (		)	
);

四、AXI_fifo

        SWR_fifo输出的数据dma_data_out在传输过程中赋值给ireq_tdata。ireq_tvalid, ireq_tdata, ireq_tlast再组合成64bit的数据axi_fifo_din输入fifo

assign	axi_fifo_din	= {ireq_tvalid, ireq_tdata, ireq_tlast}; //axi fifo输入数据  ireq_tdata位主要部分 是将要发送的数据
// ================================== 发送数据的fifo  FIFO Depth: 512 ============================//
fwft_fifo_w66		axi_fifo    //66bit in  66 bit out 
(
	.clk				(log_clk	),
	.rst				(inner_log_rst	),
	.wr_en				(axi_fifo_wren	), //ireq_tvalid  发送数据过程中 持续拉高
	.din				(axi_fifo_din	), //将swr的fifo输出数据 经过数据组装之后  写入axi fifo
	.full				(		),
	.prog_full			(axi_fifo_full	),
	.prog_full_thresh		(9'd470		),
	.rd_en				(axi_fifo_rden	), //val_ireq_tready  SRIO IP核传来
	.dout				(axi_fifo_dout	), //传给SRIO IP核
	.empty				(axi_fifo_empty )
);

        AXI fifo的读使能信号由SRIO模块传来。

扫描二维码关注公众号,回复: 3224732 查看本文章
assign	axi_fifo_rden = ~axi_fifo_empty && val_ireq_tready; 	  //axi fifo读使能

五、SRIO IP核模块

output			val_ireq_tvalid,	// AXI fifo使能信号
input			val_ireq_tready,	// IP核valid信号
output			val_ireq_tlast,		// Indicates the last beat of a packet
output		[63:0]	val_ireq_tdata,		// 数据
output		[7:0]	val_ireq_tkeep,		// 0xff
output		[31:0]	val_ireq_tuser,		// src_id, dest_id

        和IP核相关的主要由以上几个信号

六、状态机控制

IREQ_SWRITE_PRE: //每一帧数据的第一个状态,主要用于地址的重载  第一包数据用于重新加载地址  后续的地址+=256 无需进入这个状态
begin
	cstate		<= IREQ_SWRITE_HDR;
	first_dma_flag	<= 1'b0;
end


IREQ_SWRITE_HDR:// send swrite HELLO head 
begin
	cstate			<= IREQ_SWRITE;
	
	ireq_tvalid		<= 1'b1; //axi fifo的读使能拉高  往fifo写入数据
	ireq_tlast		<= 1'b0;
	
	//hello format的头部
	ireq_tdata	<=       {  8'h00,					// R
				    SWRITE,					// FTYPE
				    4'b0000,					// R
				    1'b0,					// R
				    2'b00,					// prio
				    1'b0,					// crf
				    8'h00,					// R
				    1'b0,					// R
				    1'b0,					// R
				    2'b00, dma_wr_addr	                        // addr
				};
	
	dma_read_en <= 1'b1; //swr_fifo的读使能拉高
end 


IREQ_SWRITE:	// send DMA data
begin
	if ( !srio_initialized_r2 ) begin
		cstate		<= IREQ_INIT;
	end else if ( dword_cnt == ( DMA_THRESHOLD - 1 )) begin //读取完毕32个64bit的数据之后
		cstate		<= IREQ_SWRITE_WAIT; 
		ireq_tlast	<= 1'b1;
	end else begin
		cstate		<= IREQ_SWRITE;
	end
	
	ireq_tdata		<= dma_data_out; //swr_fifo输出的数据  读取将要发送的数据
	
	if ( dword_cnt == ( DMA_THRESHOLD - 1 )) //dword_cnt读出的数据  DMA_THRESHOLD=32 一包256字节  由于从fifo读出的是64bit的数据 所以这里的个数是256/8
		begin
			dma_read_en		<= 1'b0; //发送完一包数据  256个
		end 
	else 
		begin
			dma_read_en		<= 1'b1;
		end
end


IREQ_SWRITE_WAIT:	// wait one package SWRITE data send done
	begin
		if( !srio_initialized_r2 )
			begin
				cstate		<= IREQ_INIT;
			end
		else if ( swrite_cnt == single_dma_size_r2 ) //发送完毕720*576/8个数据之后
			begin
				cstate			<= IREQ_SWRITE_DONE;
				dma_wr_done_r	<= 1'b1;
				first_dma_flag	<= 1'b1;
			end
		else
			begin
				cstate			<= IREQ_IDLE; //开始准备发送下一包数据  从头开始进入状态机
			end
		
		ireq_tvalid		<= 1'b0; //axi fifo的读使能拉低 停止向axi fifo写数据
		ireq_tlast		<= 1'b0;
	end


IREQ_SWRITE_DONE:	// DMA SWRITE done
	begin
		cstate			<= IREQ_IDLE;						
		dma_wr_done_r	<= 1'b0;
	end


default:
begin
	cstate			<= IREQ_INIT;
	
	ireq_tvalid		<= 1'b0;
	ireq_tlast		<= 1'b0;
end

IREQ_SWRITE_PRE:状态机主要包括以下几个状态:每一帧数据的第一个状态,主要用于地址的重载  第一包数据用于重新加载地址  后续的地址+=256 无需进入这个状态

IREQ_SWRITE_HDR:发送第一个hello format格式包

IREQ_SWRITE:控制读取swr_fifo的个数。当读取了32个64bit的数据之后,拉低swr_fifo读使能。可以构成一个256Byte的包,可以发送出去,

IREQ_SWRITE_WAIT:等待发送完毕swrite_cnt个数据。注意,每次进入的是IREQ_IDLE状态  从最开始的状态机开始准备。知道发送的个数等于需要发送的个数,跳入下一个完成状态

IREQ_SWRITE_DONE:SRIO发送完成


//------------------------------------------------------------------------------------------
// dword_cnt Counter  用于SWRITE模式计数  从swr fifo中读取的数
//------------------------------------------------------------------------------------------
always @( posedge log_clk, posedge inner_log_rst ) begin
	if ( inner_log_rst ) begin
		dword_cnt		<= 6'd0;
	end else begin
		if ( cstate == IREQ_SWRITE ) begin
			dword_cnt	<= dword_cnt + 1'b1;
		end else if ( ireq_tlast ) begin
			dword_cnt	<= 6'd0;
		end
	end
end

//-------------------------------------------------------------------------------------------
// DMA Write Address  每次地址递增256
//-------------------------------------------------------------------------------------------
always @( posedge log_clk, posedge inner_log_rst ) begin
	if ( inner_log_rst ) begin
		dma_wr_addr <= 32'd0;
	end else begin
		if ( cstate == IREQ_SWRITE_PRE ) begin		 // 初始帧,载入地址		
			dma_wr_addr <= dma_addr_init_value;
		end else if ( cstate == IREQ_SWRITE_HDR ) begin // Update DMA Write Address				
			dma_wr_addr <= dma_wr_addr + 256;
		end
	end
end


//-------------------------------------------------------------------------------------------
// 			SWRITE Counter  用于记录总共发送的数据
//-------------------------------------------------------------------------------------------
always @( posedge log_clk, posedge inner_log_rst ) begin
	if ( inner_log_rst ) begin
		swrite_cnt		<= 24'd0;
	end else begin
		if ((cstate == IREQ_SWRITE_DONE) || (cstate == IREQ_INIT)) begin
			swrite_cnt	<= 24'd0;
		end else if (cstate == IREQ_SWRITE_HDR) begin
			swrite_cnt	<= swrite_cnt + 1'b1;
		end
	end
end



猜你喜欢

转载自blog.csdn.net/yunge812/article/details/80931097