fpga图像处理实战-RGB转YCBCR(YUV)算法

时间:2024-11-16 14:10:17
  • `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