首页 > 其他分享 >Verilog图片仿真

Verilog图片仿真

时间:2024-07-04 16:58:41浏览次数:3  
标签:仿真 reg BMP Verilog rst integer rBmpData iIndex 图片

        今天给大家分享自己使用的一段仿真代码,是我调整好的,拿去就可以直接使用!!!

        我们做fpga有时候会接触一些图像相关的算法,我们不能每一次都是编译成功下载验证看效果吧,我也是找了好久,终于找到一个没啥毛病的,我对于这个模块还是做了一些调整,满足我们接受像素是从左上角开始,一行一行的输出,中间 Floyd模块就是我自己的算法模块,通过这个模块获得图片的数据,然后再由算出的结果形成新的图片。

`timescale 1ns / 1ns
//使用BMP图片格式仿真VIP视频图像处理算法
module Cam_Vip();
 
integer iBmpFileId;                 //输入BMP图片
integer oBmpFileId_1;                 //输出BMP图片 1
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_1 [0:2000000]; //用于寄存视频图像处理之后 的BMP图片 数据 

reg [7:0]   rBmpWord;                //输出BMP图片时用于寄存数据(以word为单位,即4byte)
//reg [7:0]   rBmpWord_2;                //输出BMP图片时用于寄存数据(以word为单位,即4byte)

//reg [7:0]   rBmpWord_8;
reg [7:0]   pixel_data;              //输出视频流时的像素数据

reg clk;
reg rst_n;

reg [7:0] vip_pixel_data_1 [0:921600];   	//640x480x3
//---------------------------------------------
initial begin
    iBmpFileId      = $fopen("D:/Xilinx/Project/PL133K/V1/PL133K_V1/PL133K_V1.srcs/sources_1/5.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);
	
    //延迟13ms,等待第一帧VIP处理结束
     #9000000       
    //输出第一张
	oBmpFileId_1 = $fopen("D:/Xilinx/Project/PL133K/V1/PL133K_V1/PL133K_V1.srcs/sources_1/5_out31.bmp","wb+");
	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 + 1) begin
		rBmpWord = Vip_BmpData_1[iIndex];
		$fwrite(oBmpFileId_1,"%c",rBmpWord);
	end
    $fclose(oBmpFileId_1);

end
//--------------------------------------------- 

//初始化时钟和复位信号
initial begin
    clk     = 1;
    rst_n   = 0;
    #110
    rst_n   = 1;
end 

//产生100MHz时钟
always #5 clk = ~clk;
//---------------------------------------------		
//在时钟驱动下,从数组中读出像素数据,用于在Modelsim中查看BMP中的数据 
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
//---------------------------------------------
//产生摄像头时序 
//---------------------------------------------
//---------------------------------------------
//例化图片参数
//---------------------------------------------
parameter [10:0] IMG_HDISP = 11'd640;
parameter [10:0] IMG_VDISP = 11'd480;
//---------------------------------------------
wire		cmos_vsync ;
reg			cmos_href;
reg	[23:0]	cmos_data;	
reg [31:0]  cmos_index;



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;

//---------------------------------------------
//水平计数器  计数至 655
	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
//---------------------------------------------
//竖直计数器 计数 至 482
	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;

//---------------------------------------------
//行有效
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
//-------------------------------------
//从数组中以视频格式输出像素数据
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   <=  (iBmpHight - 1 - y_pos) * 1920  + (iBmpWidth-1-x_pos)*3 + 54;         //  3*(y*640 + x) + 54
       cmos_data    <=  {rBmpData[cmos_index], rBmpData[cmos_index+1] , rBmpData[cmos_index+2]};
   end
end
//-------------------------------------
//摄像头模拟输出接口
//-------------------------------------
wire       per_frame_clk   ;
wire        per_frame_rst  ;
wire 		per_frame_vsync;   	
wire 		per_frame_href ;
wire [7:0]	per_img_red		 ;	   	
wire [7:0]	per_img_green	 ;   	            
wire [7:0]	per_img_blue	 ;   

assign  per_frame_clk   =   clk              ;
assign  per_frame_rst  =   ~rst_n            ;
assign  per_frame_vsync	=	cmos_vsync      ;   
assign  per_frame_href	=	cmos_href;	
assign  per_img_red		=	cmos_data[ 7: 0];	   
assign  per_img_green	=	cmos_data[15: 8];   	       
assign  per_img_blue	=	cmos_data[23:16];   
//-------------------------------------
//模拟摄像头(测试平台)取数据interface 
//-------------------------------------
wire        PIC1_vip_out_frame_vsync;
wire        PIC1_vip_out_frame_href ;
wire        [7:0]      PIC1_vip_out_img_R;
wire        [7:0]      PIC1_vip_out_img_G;
wire        [7:0]      PIC1_vip_out_img_B;
//-------------------------------------


wire					floyd_out;

floyd2 u_floyd2(
    .tft_CLK    ( per_frame_clk    ),
    .rst        ( per_frame_rst    ),
    .tft_VS_in  ( ~per_frame_vsync  ),
    .gray_in    ( (per_img_red + 2*per_img_green + per_img_blue ) >> 2  ),
    .tft_DE_in  ( per_frame_href  ),
    .floyd_out  ( floyd_out  ),
    .tft_VS_out ( PIC1_vip_out_frame_vsync ),
    .tft_DE_out  ( PIC1_vip_out_frame_href  )
);





//-----------------------------------------

reg [31:0]  PIC1_vip_cnt;
reg         PIC1_vip_vsync_r;    //寄存VIP输出的场同步 
reg         PIC1_vip_out_en;     //寄存VIP处理图像的使能信号,仅维持一帧的时间

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

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

always@(posedge clk or negedge rst_n)begin
   if(!rst_n) begin
        PIC1_vip_cnt <=  iBmpSize-3-54;
   end
   else if(PIC1_vip_out_en) begin
        if(PIC1_vip_out_frame_href) begin
            PIC1_vip_cnt <=  PIC1_vip_cnt - 3;
            vip_pixel_data_1[PIC1_vip_cnt+0] <= floyd_out ? 8'hff : 8'h00; //PIC1_vip_out_img_B;//PIC1_vip_out_img_B;
            vip_pixel_data_1[PIC1_vip_cnt+1] <= floyd_out ? 8'hff : 8'h00; //PIC1_vip_out_img_G;//PIC1_vip_out_img_G;
            vip_pixel_data_1[PIC1_vip_cnt+2] <= floyd_out ? 8'hff : 8'h00; //PIC1_vip_out_img_R;//PIC1_vip_out_img_R;
        end
   end
end
endmodule 

标签:仿真,reg,BMP,Verilog,rst,integer,rBmpData,iIndex,图片
From: https://blog.csdn.net/LQIWAN/article/details/140179864

相关文章

  • 安卓手机微信H5无法长按保存图片修复
     <imageid="saveImg":src="imgSrc"></image>主要是因为空格的处理:this.img.replace(/(\r\n)|(\n)|(\r)/g,"")网络上的其他方式都尝试了 却忽略了最简单的问题;computed:{ imgSrc(){ if(/android/i.test(navigator.userAgent)){//判断是不......
  • 基于全数字实时仿真的嵌入式DevOps解决方案
    ​为丰富浙江省信息技术应用创新(以下简称“信创”)产业生态,在全社会各领域形成示范效应,浙江省经信厅联合省密码管理局开展2023年浙江省深化信创典型案例评选工作。经过征集申报、专家评选、名单公示等程序,确定36个应用示范案例和24个典型解决方案。【典型解决方案】基于全数......
  • 推荐一款免费好用的图片/照片卡通化、漫画工具
    现在经常能在朋友圈看到朋友、同事的卡通化、漫画照片,会不会觉得很奇怪,他们这些卡通化得照片都是怎么生产的?总不会是找人手绘的吧。如果这样的话,那得付出好多好多money啊。今天来推荐一款免费好用的图片/照片卡通化、漫画工具:《证件照图片助手》,它不仅可以在手机上使用,也可以......
  • 【雷达】单基地雷达仿真,含距离-多普勒地图Matlab实现
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......
  • 基于STM32单片机的智能垃圾桶控制系统 语音识别 LD3322 垃圾分类 红外感应 超声波满溢
        随着社会科学技术的飞速发展,人们的生活质量和速度也在不断提高。大多数传统的家用垃圾桶已经过时且缺乏新颖性,并且缺乏人性化设计。使用起来既不方便也不卫生,并且所有的生活垃圾和废物垃圾都被均匀地装载,没有经过仔细的分类。随之而来的是,清洁工的任务量正以几何速......
  • 基于STM32单片机的智能垃圾桶控制系统 语音识别LD3322 垃圾分类 火灾检测 金属检测 成
        随着社会科学技术的飞速发展,人们的生活质量和速度也在不断提高。大多数传统的家用垃圾桶已经过时且缺乏新颖性,并且缺乏人性化设计。使用起来既不方便也不卫生,并且所有的生活垃圾和废物垃圾都被均匀地装载,没有经过仔细的分类。随之而来的是,清洁工的任务量正以几何速......
  • 前端与AI融合:打造图片识别应用
    前言在当今的技术环境中,人工智能(AI)与前端开发的融合越来越普遍。其中一个显著的应用是在图像识别中,AI算法可以检测和标记图像中的对象,增强用户体验,并在网站或应用程序上实现创新功能。下面将给出完成图片识别功能简易代码示例与讲解:先决条件:在继续之前,请确保您对HTML、C......
  • 【Python】基于动态规划和K聚类的彩色图片压缩算法
    引言当想要压缩一张彩色图像时,彩色图像通常由数百万个颜色值组成,每个颜色值都由红、绿、蓝三个分量组成。因此,如果我们直接对图像的每个像素进行编码,会导致非常大的数据量。为了减少数据量,我们可以尝试减少颜色的数量,从而降低存储需求。1.主要原理(一)颜色聚类(ColorClusterin......
  • java高仿真数据生成器-需要的拿去
    java高仿真数据生成器源码-需要的拿去nit-random-tools介绍:高仿真数据生成器逆天开源java证号码,姓名,职业,日期,手机号生成器功能列表编号功能描述class1号生成器NitIdcardGenerator2姓名生成器NitChineseNameGenerator3职业生成器NitJobGenerator4日期生成器N......
  • 基于GWO灰狼优化的LDPC码NMS译码算法最优归一化参数计算和误码率matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下(完整代码运行后无水印):     2.算法涉及理论知识概要       LDPC码是一种线性错误修正码,以其接近香农极限的优良性能而被广泛应用于现代通信系统中。NMS译码是一种基于最小平方误差准则的软判决译码方法,其目标是找到一......