版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_46621272/article/details/126441071
Syetem Verilog 用BMP图片文件产生视频流 testbench 激励代码
//bmp_to_videoStream.sv
//用BMP图片文件产生视频流
//本模块不能被综合,只能用来当仿真
module bmp_to_videoStream #
(
parameter iMODE = "BMP", //"BMP" 用BMP文件的图像数据产生视频流
// parameter iMODE = "NUM", //用水平垂直扫描的数字产生视频流,在定位BUG时,需要一些有规律的数字去定位
parameter iBMP_FILE_PATH = "", //缺省的 bmp 文件路径
parameter iBMP_FILE_NAME = "vin.bmp" //缺省的 bmp 文件名
)
(
input clk,
input rst_n,
output logic[2:0][7:0] vout_dat, //输出视频数据
output logic vout_valid, //输出视频数据有效
input vout_ready, //输出准备好
input frame_sync_n, //输入视频帧同步复位,低有效
output [15:0] vout_xres, //输出视频水平分辨率
output [15:0] vout_yres //输出视频垂直分辨率
);
logic [0:53][7:0] bmp_header; //BMP 图像文件头
logic [31:0] offsetBits; //BMP 图像数据位置
logic [31:0] width; //BMP 图像宽度
logic [31:0] height; //BMP 图像高度
logic [31:0] sizeImage; //BMP 图像大小(字节)
logic [31:0] sizePixel; //BMP 像素数量(像素个数)
logic [31:0] sizeBmpFile; //BMP 图像文件大小(字节)
logic [31:0] BufferLineWidth; //BMP 每行大小,单位字节,每行大小需要4字节对齐
logic pixel_valid;
logic [0:2][7:0] pixel_dat;
logic [15:0] sx;
logic [15:0] sy;
logic [2:0][7:0] num_dat;
logic [7:0] cnt = '1;
integer bmp_rp;
initial
begin
$display("iBMP_FILE_NAME = %s%s\n",iBMP_FILE_PATH,iBMP_FILE_NAME);
bmp_rp = $fopen({iBMP_FILE_PATH,iBMP_FILE_NAME},"rb");
$fread(bmp_header,bmp_rp); //读图片文件头信息
if(bmp_header[0] != 8'h42 || bmp_header[1] != 8'h4d || bmp_rp == 0) begin
$display("bmp file format error!!!!!!!!!!!!!!!!\n");
$fclose(bmp_rp);
$stop;
end
else begin
sizeBmpFile = {bmp_header[05],bmp_header[04],bmp_header[03],bmp_header[02]};
offsetBits = {bmp_header[13],bmp_header[12],bmp_header[11],bmp_header[10]};
width = {bmp_header[21],bmp_header[20],bmp_header[19],bmp_header[18]};
height = {bmp_header[25],bmp_header[24],bmp_header[23],bmp_header[22]};
sizeImage = {bmp_header[37],bmp_header[36],bmp_header[35],bmp_header[34]};
sizePixel = width * height;
BufferLineWidth = (width*3+3) & 32'hffff_fffc; //BMP 文件,每行需要4字节对齐
$display("vin BMP File Size = 0x%h",sizeBmpFile);
$display("vin Image data offset = 0x%h",offsetBits);
$display("vin Image width = 0x%h",width);
$display("vin Image heigh = 0x%h",height);
$display("vin Image size = 0x%h",sizeImage);
$display("vin Image pixel number = 0x%h",sizePixel);
$display("vin Image BufferLineWidth = 0x%h\n",BufferLineWidth);
$fseek(bmp_rp,offsetBits,0); //将读文件指针移到图片数据去
end
end
assign vout_valid = pixel_valid;
assign vout_xres = width;
assign vout_yres = height;
if(iMODE == "NUM")begin
assign vout_dat = num_dat; //用水平垂直扫描的数字产生视频流,在定位BUG时,需要一些有规律的数字去定位
end
if(iMODE == "BMP")begin
assign vout_dat[0] = pixel_dat[0];
assign vout_dat[1] = pixel_dat[1];
assign vout_dat[2] = pixel_dat[2];
end
always_ff@(posedge clk)
begin
if(rst_n == 0)
cnt <= '1;
else if(frame_sync_n == 0)
cnt <= 0;
else if( cnt != '1 )
cnt <= cnt + 1;
end
always_ff@(posedge clk)begin
if(rst_n == 0 || frame_sync_n == 0 || cnt != '1)begin
sx <= 0;
sy <= 0;
end
else if(vout_ready == 1)begin
if(sy < height)begin
num_dat <= {sy[11:0],sx[11:0]}; //iMODE = "NUM" 时,num_dat 代替图片数据输出
if(sx < width - 1)begin
sx <= sx + 1;
end
else if(sy < height)begin
sx <= 0;
sy <= sy + 1;
end
end
end
end
always_ff@(posedge clk)
begin
if(rst_n == 0 || frame_sync_n == 0 || cnt != '1)begin
pixel_valid <= 0;
pixel_dat <= 0;
end
else if(vout_ready == 1)begin
if(sy < height)begin
pixel_valid <= 1;
if(sx == 0)begin //判断行首
$fseek(bmp_rp,offsetBits+(BufferLineWidth*sy),0); //将读文件指针移到图片数据的当前行首
$fread(pixel_dat,bmp_rp);
end
else begin
$fread(pixel_dat,bmp_rp);
end
end
else begin
pixel_valid <= 0;
end
end
end // always_ff
endmodule