基于AXI-Stream接口的Modelsim图像处理仿真平台的搭建

该文详细介绍了在FPGA设计中使用AXI_Stream接口处理图像数据的过程,包括VALID和TLAST信号的正确使用,以及如何在一行结束后拉低VALID信号。文中还涉及到BMP图片的生成,通过灰度转换算法处理像素数据并存储到BMP文件中。
摘要由CSDN通过智能技术生成

AXI_Stream接口注意事项
这里需要注意到:
1**、在EOL(AXIS_TLAST)被(拉高)后,VALID是需要在下一个时刻置低的。
2、无论是EOL还是SOF,拉高时数据通道依然是有效的,如果需要对行计数时,需要对LAST信号进行延时,等待延时信号后对行清零。**在这里插入图片描述## AXI_Stream接口编写
#s_axis_tvaild控制

reg [5:0] rst_cnt;	
	
//赋初值再加一个初始延时
always @(posedge clk or negedge rst_n) begin
	if (~rst_n)
		rst_cnt <= 6'd0;
	else if (rst_cnt == 6'd30)
		rst_cnt <= rst_cnt;
	else
		rst_cnt <= rst_cnt + 1'b1;
end
		
//s_axis_tvalid信号在一行的结束拉低
always @(posedge clk or negedge rst_n) begin
	if(~rst_n)
		s_axis_tvalid <= 1'b0;
	else if(s_axis_tlast) 
		s_axis_tvalid <= 1'b0;
	else if(rst_cnt == 6'd30)
		s_axis_tvalid <= 1'b1;
	else
		s_axis_tvalid <= s_axis_tvalid;  
end	

s_axis_tlast在一行的最后一个数据拉高

reg [10:0] w_cnt;
always @(posedge clk or negedge rst_n) begin
	if(~rst_n)begin
		w_cnt <= 11'b0;
	end
	else if(s_axis_tvalid && s_axis_tready && w_cnt < iBmpWidth - 1 ) begin
		w_cnt <= w_cnt  + 1'b1;
	end
	else if(w_cnt ==  iBmpWidth-1) begin
		w_cnt <= 11'b0;
	end
	else begin
		w_cnt <= w_cnt;
	end
end

assign s_axis_tlast = (w_cnt ==  iBmpWidth - 1) ? 1'b1: 1'b0 ;

s_axis_tuser在第一行的第一列数据拉高

reg [10:0] h_cnt;

always @(posedge clk or negedge rst_n) begin
	if(~rst_n)begin
		h_cnt <= 1'b0;
	end
	else if(s_axis_tlast) begin
		h_cnt <= h_cnt  + 1'b1;
	end
	else if(h_cnt == iBmpHight - 1'd1) begin
		h_cnt <= 1'b0;
	end
	else begin
		h_cnt <= h_cnt;
	end
end
assign s_axis_tuser = (h_cnt == 0 && w_cnt == 0) ? 1'b1: 1'b0 ;

从数组中以视频格式输出像素数据

reg	[23:0]	cmos_data;	
reg [31:0]  cmos_index;

always@(posedge clk or negedge rst_n)begin
   if(!rst_n) begin
       cmos_index   <=  0;
       cmos_data    <=  24'd0;
   end
   else begin
       //cmos_index   <=  y_pos * 960  + x_pos*3 + 54;        //  3*(y*320 + x) + 54
       cmos_index   <=  h_cnt * 1920  + w_cnt * 3 + 54;         //  3*(y*640 + x) + 54
       cmos_data    <=  {rBmpData[cmos_index], rBmpData[cmos_index+1] , rBmpData[cmos_index+2]};
   end
end

wire [7:0]	img_red		=	cmos_data[ 7: 0];	   	
wire [7:0]	img_green	=	cmos_data[15: 8];   	            
wire [7:0]	img_blue	=	cmos_data[23:16]; 

assign s_axis_tdata = (s_axis_tvalid && s_axis_tready) ? {img_red, img_green, img_blue} : 24'd0;

以灰度转换为例

//--------------------
//VIP算法——彩色转灰度
wire 		per_frame_tvalid	;
wire 		per_frame_tready	;	
wire 		per_frame_tuser		;	
wire 		per_frame_tlast		;	
wire [23:0]	per_frame_tdata		;	

wire 		pose0_frame_tvalid	;
wire 		pose0_frame_tready	;	
wire 		pose0_frame_tuser	;	
wire 		pose0_frame_tlast	;
wire [23:0] pose0_frame_tdata	;		
	
wire [7:0]	post0_img_Y      	;   
wire [7:0]	post0_img_Cb     	;   
wire [7:0]	post0_img_Cr     	;  


assign per_frame_tvalid		= s_axis_tvalid	;	
assign per_frame_tuser		= s_axis_tuser	;
assign per_frame_tlast		= s_axis_tlast	;
assign per_frame_tdata 		= s_axis_tdata	;

//s_axis_tready信号由主机输出
assign s_axis_tready 		= per_frame_tready;
	

assign pose0_frame_tvalid	= m_axis_tvalid	;
assign pose0_frame_tuser	= m_axis_tuser	;
assign pose0_frame_tlast	= m_axis_tlast	;	
assign post0_img_Y 			= pose0_frame_tdata[23:16];
assign post0_img_Cb		 	= pose0_frame_tdata[15:8];
assign post0_img_Cr 		= pose0_frame_tdata[7:0];


rgb_ycbcr u_rgb_ycbcr(

	 //AXI4_Stream Slave接口0,来自摄像头,获取当前帧数据
	.clk    			(clk				),
	.rst_n 				(rst_n				),
	.s0_axis_tdata    	(per_frame_tdata 	),
	.s0_axis_tready   	(per_frame_tready	),		//输出
	.s0_axis_tvalid   	(per_frame_tvalid	),
	.s0_axis_tuser    	(per_frame_tuser 	),   	//tuser == start of frame(SOF) 
	.s0_axis_tlast    	(per_frame_tlast 	),   	//tlast == end of line(EOL)
    
    
    //AXIS4_Stream Master接口,输出到VDMA
//    input               m_axis_aclk    	,
//    input               m_axis_aresetn 	,
    .m_axis_tdata    	(pose0_frame_tdata	),
    .m_axis_tvalid   	(pose0_frame_tvalid	),
    .m_axis_tready   	(pose0_frame_tready	),
    .m_axis_tuser    	(pose0_frame_tuser	),
    .m_axis_tlast    	(pose0_frame_tlast	)
);
##   生成BMP图片

```c
//寄存图像处理之后的像素数据

//-------------------------------------
//第一张图

reg [31:0]  PIC1_vip_cnt;
reg         PIC1_vip_out_en;     	//寄存VIP处理图像的使能信号,仅维持一帧的时间
reg 		m_axis_tuser_r0;		//采集上升沿
reg 		m_axis_tuser_r1;
wire 		m_axis_tuser_p;

reg         PIC1_vip_vsync_r;    	//寄存VIP输出的场同步


always@(posedge clk or negedge rst_n)begin
   
	if(!rst_n) begin
		m_axis_tuser_r0 <= 1'd0;
        m_axis_tuser_r1 <= 1'd0;
	end
	else begin
		m_axis_tuser_r0 <= PIC1_vip_out_tuser	;
        m_axis_tuser_r1 <= m_axis_tuser_r0		;
	end
end

assign m_axis_tuser_p = (~m_axis_tuser_r1) && m_axis_tuser_r0;



always@(posedge clk or negedge rst_n)begin
   if(!rst_n) 
        PIC1_vip_vsync_r   <=  1'b0;
   else if (m_axis_tuser_p)
        PIC1_vip_vsync_r   <=  ~PIC1_vip_vsync_r;
end


always@(posedge clk or negedge rst_n)begin
   if(!rst_n) 
        PIC1_vip_out_en    <=  1'b1;
   else if(PIC1_vip_vsync_r & m_axis_tuser_p)  //第一帧结束之后,使能拉低
        PIC1_vip_out_en    <=  1'b0;
end


always@(posedge clk or negedge rst_n)begin
	if(!rst_n) begin
		PIC1_vip_cnt <=  32'd0;
	end
	else if (PIC1_vip_out_en) begin
		if(PIC1_vip_out_tvalid & PIC1_vip_out_tready) begin
			PIC1_vip_cnt <=  PIC1_vip_cnt + 3;
			vip_pixel_data_1[PIC1_vip_cnt+0] <= PIC1_vip_out_img_R;
			vip_pixel_data_1[PIC1_vip_cnt+1] <= PIC1_vip_out_img_G;
			vip_pixel_data_1[PIC1_vip_cnt+2] <= PIC1_vip_out_img_B;
		end
	end
end

	//输出第一张
	for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
		if(iIndex < 54)
            Vip_BmpData_1[iIndex] = rBmpData[iIndex];
        else
            Vip_BmpData_1[iIndex] = vip_pixel_data_1[iIndex-54];
	end
    //将数组中的数据写到输出BMP图片中    
	for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 4) begin
		rBmpWord = {Vip_BmpData_1[iIndex+3],Vip_BmpData_1[iIndex+2],Vip_BmpData_1[iIndex+1],Vip_BmpData_1[iIndex]};
		$fwrite(oBmpFileId_1,"%u",rBmpWord);
	end

效果展示

在这里插入图片描述

参考文献

https://hwbyyds.blog.csdn.net/article/details/124319453?spm=1001.2014.3001.5502
b站大磊FPGA图像处理,基于Modelsim的图像仿真处理平台搭建

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: axi-streamaxi-lite是两种不同的传输协议,它们在数据传输的方式和控制信号上有所不同。在将axi-stream转换为axi-lite时,需要进行一些改变和调整。 首先,axi-stream是一种流式传输协议,它主要用于高速数据传输,没有固定的地址和控制信号。而axi-lite是一种基于地址和控制信号的传输协议,适用于低速数据传输和对外部设备的读写控制。 要将axi-stream转换为axi-lite,需要定义一个寄存器(或寄存器组),用于接收从axi-stream传输过来的数据。通过定义该寄存器的地址和控制信号,可以对其进行读写操作,并将数据传输到外部设备。 其次,需要根据具体的应用场景,对数据的格式和处理进行调整。axi-stream一般通过数据流的方式传输,而axi-lite传输的数据需要按照特定的格式进行打包和解包。因此,在进行转换时,需要对数据进行格式转换和处理,以满足axi-lite的传输要求。 最后,需要修改相应的控制逻辑和状态机来适应axi-lite的读写操作。axi-stream主要通过数据流传输,而axi-lite需要定义读写控制信号和状态机来实现读写操作。因此,在进行转换时,需要对控制逻辑和状态机进行修改,以实现axi-lite的读写功能。 总结起来,将axi-stream转换为axi-lite需要进行以下几个步骤:定义一个寄存器用于接收数据、调整数据的格式和处理、修改控制逻辑和状态机来适应axi-lite的读写操作。通过这些步骤,我们可以完成axi-streamaxi-lite的转换。 ### 回答2: 要将Axi-Stream转换为Axi-Lite,需要进行一系列的处理和转换。 首先,需要了解Axi-StreamAxi-Lite之间的区别。Axi-Stream是一种高速数据传输协议,用于在数据流传输应用中实现高速数据传输。相比之下,Axi-Lite则是一种更简化、精简的协议,适用于低速、延迟敏感的访问要求。 要将Axi-Stream转换为Axi-Lite,需要将数据流转变为离散的数据包。可以通过添加一些额外的逻辑和寄存器来实现数据的提取和转换。 首先,需要添加一个接收缓冲区,用于接收Axi-Stream传输的数据。可以使用一个FIFO(First-In, First-Out)缓冲区来实现。将Axi-Stream输入端口连接到该缓冲区,并配置缓冲区的大小以适应数据传输的需求。 然后,可以使用状态机和控制逻辑从接收缓冲区中提取数据。根据Axi-Lite协议的要求,需要提取合适的数据字段,并将其放入适当的寄存器中。可以使用状态机来控制数据的提取和转换过程。 最后,在提取和转换数据后,可以使用Axi-Lite的地址端口和数据端口,将数据传输到Axi-Lite总线上。根据Axi-Lite协议的要求,需要设置地址、数据和控制信号,以完成对寄存器的读写操作。 总体而言,将Axi-Stream转换为Axi-Lite需要添加接收缓冲区、状态机和控制逻辑,并通过Axi-Lite协议完成数据的提取和转换。这样可以实现从高速数据传输到低速数据访问的转换。 ### 回答3: Axi-streamAxi-lite是两种不同的通信协议,将Axi-stream转换为Axi-lite可以通过添加适当的逻辑和转换器来实现。下面是一种将Axi-stream转换为Axi-lite的方法: 1. 首先,需要添加一个转换器模块,该模块将负责将Axi-stream信号转换为Axi-lite信号。该转换器模块可以使用FIFO(First-In-First-Out)缓冲区来处理数据流,并将其转换为连续的数据列。 2. 转换器模块接收来自Axi-stream的有效数据包,并根据Axi-lite协议的要求生成对应的Axi-lite数据包。转换过程包括将Axi-stream的数据包拆分为Axi-lite的数据包,并提取有效数据和其他控制信息。 3. 转换器模块还需要处理Axi-stream信号的流速。由于Axi-stream的数据是连续流动的,而Axi-lite的数据包需要在时钟边沿进行传输,因此需要添加适当的时序逻辑来处理数据流速的差异。 4. 转换器模块还应该能够处理Axi-lite协议中的写入和读取操作。写入操作将由Axi-stream转换成Axi-lite写入操作,读取操作将由Axi-stream转换成Axi-lite读取操作。 5. 最后,通过适当的连接操作将转换器模块与Axi-lite总线连接起来,以实现从Axi-streamAxi-lite的转换。 总结来说,将Axi-stream转换为Axi-lite需要添加一个转换器模块,该模块负责处理Axi-stream数据流的数据包和流速,并将其转换为符合Axi-lite协议的信号。这样可以实现从Axi-streamAxi-lite的数据通信转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值