今天给大家分享自己使用的一段仿真代码,是我调整好的,拿去就可以直接使用!!!
我们做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