Git地址:
https://gitee.com/whik/bmp_gen_c_and_verilog/tree/master/verilog
BMP文件格式详解参考:
Verilog实现生成BMP,注意宽度必须进行4字节对齐,使用0来补充,否则部分宽度图片生成乱码。可使用PhotoShop生成宽度10,长度5的图片验证,数据存储为BMP文件最后一行为图片第一行的像素数据。先选择图像->模式->8位/通道
,再保存为BMP,Windows,24Bit。
Verilog实现生成BMP
module main;
/* rgb_565 to rgb_888 */
function [23:0] rgb_888 (
input [15:0] rgb_565
);
begin
rgb_888[23:16] = rgb_565[15:11] / 31.0 * 255.0;//r
rgb_888[15:8] = rgb_565[10:5] / 63.0 * 255.0; //g
rgb_888[7:0] = rgb_565[4:0] / 31.0 * 255.0; //b
end
endfunction
/* small to big: 0x12345678 -> 0x78563412 */
function [31:0] to_small_endian(
input [31:0] big_endian
);
begin
to_small_endian[31:24] = big_endian[7:0];
to_small_endian[23:16] = big_endian[15:8];
to_small_endian[15:8] = big_endian[23:16];
to_small_endian[7:0] = big_endian[31:24];
end
endfunction
/* num to char: 5->"5" */
function [7:0] num_to_ascii(
input [3:0] num
);
num_to_ascii[7:0] = num + "0";
endfunction
/* num to filename string: 7890->"7890.bmp" */
function [8*8-1:0] num_to_filename(
input [13:0] num
);
begin
num_to_filename[8*8-1 : 8*8-8] = num_to_ascii(num / 1000); //1
num_to_filename[7*8-1 : 7*8-8] = num_to_ascii(num / 100 % 10); //2
num_to_filename[6*8-1 : 6*8-8] = num_to_ascii(num / 10 % 10); //3
num_to_filename[5*8-1 : 5*8-8] = num_to_ascii(num % 10); //4
num_to_filename[4*8-1 : 0 ] = ".bmp";
end
endfunction
function [31:0] width_4byte_align(
input [31:0] width
);
width_4byte_align = ((width * 24) / 8 + 3) / 4 * 4;
endfunction
//close bmp file
task bmp_file_close(
input integer fd
);
begin
$fclose(fd);
$display("file is close!");
end
endtask
//bmp write rgb data 565 format
task bmp_file_write(
input integer fd,
input [15:0] rgb_data_565
);
reg [23:0] rgb_data_888;
begin
rgb_data_888 = rgb_888(rgb_data_565);
// B G R
$fwrite(fd, "%c%c%c", rgb_data_888[7:0], rgb_data_888[15:8], rgb_data_888[23:16]);
end
endtask
//write num zero
task bmp_file_write_zero(
input integer fd,
input integer zero_num
);
integer idx;
begin
if(zero_num > 0)
begin
for(idx = 0; idx < zero_num; idx = idx + 1)
$fwrite(fd, "%c", 0);
end
end
endtask
task bmp_file_new(
input [13:0] filenum
,input [31:0] width
,input [31:0] height
,output reg [31:0] width_real
,output integer fd
);
/* file header(14 Byte) and map info(40 Byte) */
reg [7:0] bmp_head_map [53:0];
reg [31:0] bfSize; /* = w*h*3*/
reg [31:0] width_small;
reg [31:0] height_small;
reg [8*8-1:0] filename;
reg [23:0] rgb_data_888;
integer idx;
begin
//width 4 byte align
width_real = width_4byte_align(width);
$display("width: %03d, width_real: %03d", width, width_real);
//width and height to small endian
width_small = to_small_endian(width);
height_small = to_small_endian(height);
bfSize = to_small_endian(width_real * height + 54 + 2);
filename = num_to_filename(filenum);
bmp_head_map[0 ] = 'h42;
bmp_head_map[1 ] = 'h4d;
//bfSize
bmp_head_map[2 ] = bfSize[31:24];
bmp_head_map[3 ] = bfSize[23:16];
bmp_head_map[4 ] = bfSize[15:8] ;
bmp_head_map[5 ] = bfSize[7:0] ;
bmp_head_map[6 ] = 'h0;
bmp_head_map[7 ] = 'h0;
bmp_head_map[8 ] = 'h0;
bmp_head_map[9 ] = 'h0;
bmp_head_map[10] = 'h36;
bmp_head_map[11] = 'h0;
bmp_head_map[12] = 'h0;
bmp_head_map[13] = 'h0;
bmp_head_map[14] = 'h28;
bmp_head_map[15] = 'h0;
bmp_head_map[16] = 'h0;
bmp_head_map[17] = 'h0;
//width
bmp_head_map[18] = width_small[31:24];
bmp_head_map[19] = width_small[23:16];
bmp_head_map[20] = width_small[15:8] ;
bmp_head_map[21] = width_small[7:0] ;
//height
bmp_head_map[22] = height_small[31:24];
bmp_head_map[23] = height_small[23:16];
bmp_head_map[24] = height_small[15:8] ;
bmp_head_map[25] = height_small[7:0] ;
bmp_head_map[26] = 'h01;
bmp_head_map[27] = 'h0;
//24Bit RGB_888
bmp_head_map[28] = 'h18;
bmp_head_map[29] = 'h0;
bmp_head_map[30] = 'h0;
bmp_head_map[31] = 'h0;
bmp_head_map[32] = 'h0;
bmp_head_map[33] = 'h0;
bmp_head_map[34] = 'h0;
bmp_head_map[35] = 'h0;
bmp_head_map[36] = 'h0;
bmp_head_map[37] = 'h0;
bmp_head_map[38] = 'h0;
bmp_head_map[39] = 'h0;
bmp_head_map[40] = 'h0;
bmp_head_map[41] = 'h0;
bmp_head_map[42] = 'h0;
bmp_head_map[43] = 'h0;
bmp_head_map[44] = 'h0;
bmp_head_map[45] = 'h0;
bmp_head_map[46] = 'h0;
bmp_head_map[47] = 'h0;
bmp_head_map[48] = 'h0;
bmp_head_map[49] = 'h0;
bmp_head_map[50] = 'h0;
bmp_head_map[51] = 'h0;
bmp_head_map[52] = 'h0;
bmp_head_map[53] = 'h0;
fd = $fopen(filename,"wb+");
if(fd != 0)
begin
$display("filename: %08s, width: %04d, height: %04d", filename, width, height);
for(idx = 0; idx <= 53; idx = idx + 1)
$fwrite(fd, "%c", bmp_head_map[idx]);
end
else
$display("file create failed: %d", fd);
end
endtask
integer fd = 0, i = 0, j = 0;
reg [31:0] width_real = 0;
reg [31:0] w = 0, h = 0;
initial
begin
w = 301;
h = 401;
bmp_file_new(w, w, h, width_real, fd);
for(i = 0; i < h; i = i + 1)
begin
for(j = 0; j < w; j = j + 1)
bmp_file_write(fd, 16'b01000_000111_01111); /* BGR */
bmp_file_write_zero(fd, width_real - w * 3);
end
bmp_file_write_zero(fd, 2);
bmp_file_close(fd);
// $finish;
end
endmodule
生成的图片:
Git地址:
https://gitee.com/whik/bmp_gen_c_and_verilog/tree/master/verilog