图像处理7:测试文件

`timescale 1ns / 1ps

module Image_Processing_tb;
 
	integer iBmpFileId;                 //输入BMP图片
	integer oBmpFileId;                 //输出BMP图片
	integer oTxtFileId;                 //输入TXT文本
			
	integer iIndex = 0;                 //输出BMP数据索引
	integer pixel_index = 0;            //输出像素数据索引 
			
	integer iCode;      
			
	integer iBmpWidth;                  //输入BMP 宽度
	integer iBmpHight;                  //输入BMP 高度
	integer iBmpSize;                   //输入BMP 字节数
	integer iDataStartIndex;            //输入BMP 像素数据偏移量
		
	reg [ 7:0] rBmpData [0:2000000];    //用于寄存输入BMP图片中的字节数据(包括54字节的文件头)
	reg [ 7:0] Vip_BmpData [0:2000000]; //用于寄存视频图像处理之后 的BMP图片 数据 
	reg [7:0] rBmpWord;                //输出BMP图片时用于寄存数据(以word为单位,即4byte)
	
	reg [ 7:0] pixel_data;              //输出视频流时的像素数据
	
	reg clk;
	reg rst_n;
	
	reg [ 7:0] vip_pixel_data [0:230400];   //320x240x3

	
	//产生50MHz时钟
	initial clk = 0;
	always #10 clk = ~clk;

	
	//复位信号
	initial begin
		rst_n   = 0;
		#100;
		rst_n   = 1;
	end 
	
	
	
	//--------------------------------------------------//
	//------------读取外部的图片文件夹位置--------------//
	//--------------------------------------------------//
	initial begin
		//分别打开 输入/输出BMP图片,以及输出的Txt文本
		
		// 导入图片部分,需要更改
		iBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi.bmp","rb");
		
		// 输出的图片
		oBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi_test.bmp","wb+");

		oTxtFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi_3.txt","w+");
		
		// =======2种方法=======
		// 使用绝对路径:oBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\pic.bmp","wb+");
		// 将图片加入工程:iBmpFileId = $fopen("che_BMP.bmp","rb");
		
		
		//将输入BMP图片加载到数组中
		iCode = $fread(rBmpData,iBmpFileId);
	
		//根据BMP图片文件头的格式,分别计算出图片的 宽度 /高度 /像素数据偏移量 /图片字节数
		iBmpWidth       = {rBmpData[21],rBmpData[20],rBmpData[19],rBmpData[18]};
		iBmpHight       = {rBmpData[25],rBmpData[24],rBmpData[23],rBmpData[22]};
		iBmpSize        = {rBmpData[ 5],rBmpData[ 4],rBmpData[ 3],rBmpData[ 2]};
		iDataStartIndex = {rBmpData[13],rBmpData[12],rBmpData[11],rBmpData[10]};
		
		//关闭输入BMP图片
		$fclose(iBmpFileId);
		
		//将数组中的数据写到输出Txt文本中
		$fwrite(oTxtFileId,"%p",rBmpData);
		//关闭Txt文本
		$fclose(oTxtFileId);
			
		
		//延迟2ms,等待第一帧VIP处理结束
		#2000000    
		//加载图像处理后,BMP图片的文件头和像素数据
		for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
			if(iIndex < 54)
					Vip_BmpData[iIndex] = rBmpData[iIndex];
			else
					Vip_BmpData[iIndex] = vip_pixel_data[iIndex-54];
		end
		
		//将数组中的数据写到输出BMP图片中    
		for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
			rBmpWord = Vip_BmpData[iIndex];
			$fwrite(oBmpFileId,"%c",rBmpWord);
		end
		//关闭输出BMP图片
		$fclose(oBmpFileId); 
	end
	
	
	
	//=====================================================================================================
	//--------------------------------------------------//
	//-------------------图像处理外部IP-----------------//
	//--------------------------------------------------//
	
	//模拟的摄像头输出数据和时钟
	wire		cmos_vsync;
	reg			cmos_href;
	wire        cmos_clken;
	reg	[23:0]	cmos_data;
	
	//  2  图像处理部分,需要更改
	wire 		per_frame_vsync	=	cmos_vsync;
	wire 		per_frame_href	=	cmos_href;
	wire 		per_frame_clken	=	cmos_clken;
	wire [7:0]	per_img_red		=	cmos_data[23:16];
	wire [7:0]	per_img_green	=	cmos_data[15: 8];
	wire [7:0]	per_img_blue	=	cmos_data[ 7: 0];
	
	wire		post_frame_vsync;
	wire		post_frame_href;
	wire		post_frame_clken;
	wire [7:0]	post_img_Y;
	wire [7:0]	post_img_Cb;
	wire [7:0]	post_img_Cr;

// 图像处理算法顶层模块
	Image_Processing Image_Processing_inst(
		.clk				(clk),
		.rst_n				(rst_n),
	
		.per_frame_vsync	(per_frame_vsync),
		.per_frame_href		(per_frame_href),
		.per_frame_clken	(per_frame_clken),
		.per_img_red		(per_img_red),
		.per_img_green		(per_img_green),
		.per_img_blue		(per_img_blue),
		
		.post_frame_vsync 	(post_frame_vsync),
		.post_frame_href	(post_frame_href),
		.post_frame_clken 	(post_frame_clken),
		.post_img_Y		    (post_img_Y),
        .post_img_Cb        (post_img_Cb),
        .post_img_Cr        (post_img_Cr)
        /* .post_img_Bit		(post_img_Bit) */
);



	//--------------------------------------------------//
	//--------------------图像输出部分------------------//
	//--------------------------------------------------//
	
	wire 			vip_out_frame_vsync;   
	wire 			vip_out_frame_href ;   
	wire 			vip_out_frame_clken;    
	wire [7:0]		vip_out_img_R;   
	wire [7:0]		vip_out_img_G;   
	wire [7:0]		vip_out_img_B;  
	
	//  3  输出图像数据,需要更改的地方
	assign vip_out_frame_vsync = post_frame_vsync;   
	assign vip_out_frame_href  = post_frame_href ;   
	assign vip_out_frame_clken = post_frame_clken;    
	/* assign vip_out_img_R       = {8{post_img_Bit}};   
	assign vip_out_img_G       = {8{post_img_Bit}};   
	assign vip_out_img_B       = {8{post_img_Bit}};  */
	/* assign vip_out_img_R       = post_img_Y;   
	assign vip_out_img_G       = post_img_Y;   
	assign vip_out_img_B       = post_img_Y; */
	assign vip_out_img_R       = post_img_Y;   
	assign vip_out_img_G       = post_img_Cb;   
	assign vip_out_img_B       = post_img_Cr;

//=====================================================================================================


	//--------------------------------------------------//
	//----------------产生摄像头的输出时序--------------//
	//--------------------------------------------------//
	reg [31:0]  cmos_index;
	
	parameter [10:0] IMG_HDISP = 11'd320;
	parameter [10:0] IMG_VDISP = 11'd240;
	
	localparam H_SYNC = 11'd5;		
	localparam H_BACK = 11'd5;		
	localparam H_DISP = IMG_HDISP;	
	localparam H_FRONT = 11'd5;		
	localparam H_TOTAL = H_SYNC + H_BACK + H_DISP + H_FRONT;	
	
	localparam V_SYNC = 11'd1;		
	localparam V_BACK = 11'd0;		
	localparam V_DISP = IMG_VDISP;	
	localparam V_FRONT = 11'd1;		
	localparam V_TOTAL = V_SYNC + V_BACK + V_DISP + V_FRONT;
	
	//水平计数器
	reg	[10:0]	hcnt;
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			hcnt <= 11'd0;
		else
			hcnt <= (hcnt < H_TOTAL - 1'b1) ? hcnt + 1'b1 : 11'd0;
	end
	
	//竖直计数器
	reg	[10:0]	vcnt;
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			vcnt <= 11'd0;		
		else begin
			if(hcnt == H_TOTAL - 1'b1)
				vcnt <= (vcnt < V_TOTAL - 1'b1) ? vcnt + 1'b1 : 11'd0;
			else
				vcnt <= vcnt;
		end
	end
	
	//场同步
	reg	cmos_vsync_r;
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			cmos_vsync_r <= 1'b0;			//H: Vaild, L: inVaild
		else begin
			if(vcnt <= V_SYNC - 1'b1)
				cmos_vsync_r <= 1'b0; 	//H: Vaild, L: inVaild
			else
				cmos_vsync_r <= 1'b1; 	//H: Vaild, L: inVaild
		end
	end
	
	assign	cmos_vsync	= cmos_vsync_r;
	
	//Image data href vaild  signal
	wire	frame_valid_ahead =  ( vcnt >= V_SYNC + V_BACK  && vcnt < V_SYNC + V_BACK + V_DISP
										&& hcnt >= H_SYNC + H_BACK  && hcnt < H_SYNC + H_BACK + H_DISP ) 
							? 1'b1 : 1'b0;
			
	reg			cmos_href_r;      
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			cmos_href_r <= 0;
		else begin
			if(frame_valid_ahead)
				cmos_href_r <= 1;
			else
				cmos_href_r <= 0;
		end
	end
	
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n)
			cmos_href <= 0;
		else
			cmos_href <= cmos_href_r;
	end
	
	assign cmos_clken = cmos_href;
	
	//从数组中以视频格式输出像素数据
	wire [10:0] x_pos;
	wire [10:0] y_pos;
	
	assign x_pos = frame_valid_ahead ? (hcnt - (H_SYNC + H_BACK )) : 0;
	assign y_pos = frame_valid_ahead ? (vcnt - (V_SYNC + V_BACK )) : 0;
	
	
	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_data    <=  {rBmpData[cmos_index], rBmpData[cmos_index+1] , rBmpData[cmos_index+2]};
		end
	end

	//在时钟驱动下,从数组中读出像素数据
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n) begin
			pixel_data  <=  8'd0;
			pixel_index <=  0;
		end
		else begin
			pixel_data  <=  rBmpData[pixel_index];
			pixel_index <=  pixel_index+1;
		end
	end
	
	

	//-------------------------------------------//
	//----------图像处理之后的像素数据-----------//
	//-------------------------------------------//
	
	reg [31:0] vip_cnt;
	
	reg         vip_vsync_r;    //寄存VIP输出的场同步 
	reg         vip_out_en;     //寄存VIP处理图像的使能信号,仅维持一帧的时间

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n) 
			vip_vsync_r   <=  1'b0;
		else 
			vip_vsync_r   <=  per_frame_vsync;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n) 
			vip_out_en    <=  1'b1;
		else if(vip_vsync_r & (!per_frame_vsync))  //第一帧结束之后,使能拉低
			vip_out_en    <=  1'b0;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n) begin
			vip_cnt <=  32'd0;
		end
		else if(vip_out_en) begin
			if(vip_out_frame_href & vip_out_frame_clken) begin
					vip_cnt <=  vip_cnt + 3;
					vip_pixel_data[vip_cnt+0] <= vip_out_img_R;
					vip_pixel_data[vip_cnt+1] <= vip_out_img_G;
					vip_pixel_data[vip_cnt+2] <= vip_out_img_B;
			end
		end
	end
	
	
endmodule 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值