`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/08/01 20:54:28
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`define INPUT_FILE "../../../../test_img/in/" //input image
`define IMG_WIDTH 1024 //Image width
`define IMG_HEIGHT 600 //Image height
`define H_BLANK 400 //横向消影区,仿真可*设定
`define V_BLANK 30 //纵向消影区,仿真可*设定
`define OUTPUT_FILE "../../../../test_img/out/" //result image frame1
`define LEN_HEADER 54 // 0x33
`define IMG_ALL (`IMG_HEIGHT*`IMG_WIDTH*3)
`define IMG_SIZE (`IMG_HEIGHT*`IMG_WIDTH)
`define IMG_BMP_SIZE (`IMG_ALL + `LEN_HEADER)
`define NULL 0
`define DATA_WIDTH 8
`define SEEK_SET 0
`define SEEK_CUR 1
`define SEEK_END 2
module tb;
parameter TIME = 2;
integer fdI;
integer fdO;
integer ret, i, j, idx, file_end_offset, zero_len;
reg [`DATA_WIDTH-1:0] bmp_head_r[0:`LEN_HEADER-1];//Image 1 Header
reg [`DATA_WIDTH-1:0] imgR_r[0:`IMG_SIZE-1]; //Image-- R Channel
reg [`DATA_WIDTH-1:0] imgG_r[0:`IMG_SIZE-1]; //Image-- G Channel
reg [`DATA_WIDTH-1:0] imgB_r[0:`IMG_SIZE-1]; //Image-- B Channel
wire [31:0] bmp_size, bmp_width, bmp_height;
reg init_r;
reg clk = 1'b0;
reg rst;
reg [31:0] h_cnt_r, v_cnt_r;
reg [31:0] data_cnt_r;
reg [31:0] addr_r;
wire valid_i;
wire [`DATA_WIDTH*3-1:0] img_data_i;
wire valid_o;
wire [`DATA_WIDTH*3-1:0] img_data_o;
reg [31:0] out_data_cnt_r;
reg valid_o_r;
wire [`DATA_WIDTH-1:0] R_o_w, G_o_w, B_o_w;
always
begin
#(TIME/2) clk = ~clk;
end
initial begin
rst = 1'b1;
zero_len = 'b0;
#(TIME*10);
rst = 1'b0;
wait(init_r);
$display("> Initial Done");
wait(out_data_cnt_r == (`IMG_SIZE-1));//检测一幅图像完成�
#(TIME*2);
//文件末尾补0
$fseek(fdO, 0, `SEEK_END);
zero_len = $ftell(fdO);
zero_len = 4- zero_len[1:0];
for(i=0;i < zero_len;i=i+1)
$fwrite(fdO, "%c", 0);
$fclose(fdO);
$display("> Simulate Done");
$stop;
end
///读取BMP文件
assign bmp_size = {bmp_head_r[5], bmp_head_r[4], bmp_head_r[3], bmp_head_r[2]};
assign bmp_width = {bmp_head_r[21], bmp_head_r[20], bmp_head_r[19], bmp_head_r[18]};
assign bmp_height = {bmp_head_r[25], bmp_head_r[24], bmp_head_r[23], bmp_head_r[22]};
initial begin
init_r = 1'b0;
for (i = 0; i < `IMG_SIZE; i=i+1)begin
imgB_r[i] = 0;
imgG_r[i] = 0;
imgR_r[i] = 0;
end
fdI = $fopen(`INPUT_FILE,"rb");
if (fdI == `NULL) begin
$display("> OPEN FAIL: The file not exist !!!");
end else begin
$display("> OPEN file SUCCESS !");
//读取bmp文件头
ret = $fread(bmp_head_r, fdI, 0, `LEN_HEADER);
//读取图像RGB分量值�
//BMP倒序存储数据时,从下到上,从左到右
for(i=`IMG_HEIGHT - 1;i >= 0;i=i-1)
for(j=0;j <`IMG_WIDTH;j=j+1) begin
idx = i*`IMG_WIDTH + j;
imgB_r[idx] = $fgetc(fdI);//b
imgG_r[idx] = $fgetc(fdI);//g
imgR_r[idx] = $fgetc(fdI);//r
end
$display("> Read b,g,r Successful !");
end
fdO = $fopen(`OUTPUT_FILE,"wb");
//写入文件头 �
for(i=0;i < `LEN_HEADER;i=i+1) begin
$fwrite(fdO, "%c", bmp_head_r[i]);
end
//移动到图片数据最后一行起始位置
file_end_offset = `IMG_ALL + `LEN_HEADER - `IMG_WIDTH*3;
$fseek(fdO, file_end_offset, `SEEK_SET);
init_r = 1'b1;
end
img_rgb_ycbcr img_rgb_ycbcr(
.clk (clk ),
.rst (rst ),
.img_data_i (img_data_i ),
.valid_i (valid_i ),
.img_data_o (img_data_o ),
.valid_o (valid_o )
);
always @(posedge clk or posedge rst) begin
if (rst) begin
{h_cnt_r, v_cnt_r} <= 'b0;
addr_r <= 'b0;
data_cnt_r <= 'b0;
end else begin
h_cnt_r <= (h_cnt_r == `IMG_WIDTH + `H_BLANK - 1) ? 'b0 : h_cnt_r + 1'b1;
v_cnt_r <= (h_cnt_r == `IMG_WIDTH + `H_BLANK - 1) ? ((v_cnt_r == `IMG_HEIGHT + `V_BLANK - 1) ? 'b0 : v_cnt_r + 1'b1) : v_cnt_r;
addr_r <= (addr_r == `IMG_SIZE - 1) ? 'b0 : valid_i ? (addr_r + 'd1) : addr_r;
data_cnt_r <= valid_i ? ((data_cnt_r == `IMG_WIDTH - 1) ? 'b0 : data_cnt_r + 1) : data_cnt_r;
end
end
assign valid_i = (h_cnt_r < `IMG_WIDTH)&&(v_cnt_r < `IMG_HEIGHT) ? 1'b1 : 1'b0;
assign img_data_i = {imgR_r[addr_r], imgG_r[addr_r], imgB_r[addr_r]};
///写入BMP文件
assign {R_o_w, G_o_w, B_o_w} = img_data_o;
always @(posedge clk or posedge rst) begin
if (rst) begin
out_data_cnt_r <= 'b0;
valid_o_r <= 'b0;
end else begin
valid_o_r <= valid_o;
if(valid_o) begin
$fwrite(fdO, "%c", B_o_w);
$fwrite(fdO, "%c", G_o_w);
$fwrite(fdO, "%c", R_o_w);
out_data_cnt_r <= out_data_cnt_r + 1'b1;
end else if(valid_o_r) begin//行结束�
file_end_offset = file_end_offset - `IMG_WIDTH*3;
$fseek(fdO, file_end_offset, `SEEK_SET);
end
end
end
endmodule