diff --git a/Color/ColorBlender.v b/Color/ColorBlender.v index 27b591a..695ad39 100644 --- a/Color/ColorBlender.v +++ b/Color/ColorBlender.v @@ -2,9 +2,9 @@ // 三通道图像合成一个RGB图像 module ColorBlender #( - parameter reg [ 4:0] IN_DEPTH = 12, // 输入图像的色深 - parameter reg [ 4:0] OUT_DEPTH = 8, // 输出图像的色深 - parameter reg [ 8:0] BUFF_SIZE = 32 + parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深 + parameter reg [4:0] OUT_DEPTH = 8, // 输出图像的色深 + parameter reg [8:0] BUFF_SIZE = 32 ) ( input wire clk, input wire reset, @@ -18,13 +18,13 @@ module ColorBlender #( input wire in_ready, input wire in_receive, output reg out_en, - output reg [3 * OUT_DEPTH - 1:0] out_data, + output reg [OUT_DEPTH - 1:0] out_data[3], // 颜色校正 input wire [15:0] gain_red, input wire [15:0] gain_green, input wire [15:0] gain_blue, - input wire color_correction + input wire enable ); localparam reg [2:0] READ_DATA = 0; localparam reg [2:0] CALC_DATA = 1; @@ -62,7 +62,9 @@ module ColorBlender #( data_cal[1] <= 0; data_cal[2] <= 0; - out_data <= 0; + out_data[0] <= 0; + out_data[1] <= 0; + out_data[2] <= 0; out_en <= 0; end else begin case (state) @@ -75,12 +77,11 @@ module ColorBlender #( end CALC_DATA: begin - if (color_correction) begin - data_cal[0] <= (data_cal[0] * {{(BUFF_SIZE - 16){1'b0}}, gain_red}) >> 16; - data_cal[1] <= (data_cal[1] * {{(BUFF_SIZE - 16){1'b0}}, gain_green}) >> 16; - data_cal[2] <= (data_cal[2] * {{(BUFF_SIZE - 16){1'b0}}, gain_blue}) >> 16; - end - else begin + if (enable) begin + data_cal[0] <= (data_cal[0] * {{(BUFF_SIZE - 16) {1'b0}}, gain_red}) >> 16; + data_cal[1] <= (data_cal[1] * {{(BUFF_SIZE - 16) {1'b0}}, gain_green}) >> 16; + data_cal[2] <= (data_cal[2] * {{(BUFF_SIZE - 16) {1'b0}}, gain_blue}) >> 16; + end else begin data_cal[0] <= data_cal[0] >> 8; data_cal[1] <= data_cal[1] >> 8; data_cal[2] <= data_cal[2] >> 8; @@ -88,17 +89,17 @@ module ColorBlender #( end SATI_DATA: begin - data_cal[0] <= |data_cal[0][BUFF_SIZE -1 :OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[0]; - data_cal[1] <= |data_cal[0][BUFF_SIZE -1 :OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[1]; - data_cal[2] <= |data_cal[0][BUFF_SIZE -1 :OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[2]; + data_cal[0] <= |data_cal[0][BUFF_SIZE-1 : OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[0]; + data_cal[1] <= |data_cal[0][BUFF_SIZE-1 : OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[1]; + data_cal[2] <= |data_cal[0][BUFF_SIZE-1 : OUT_DEPTH] ? {BUFF_SIZE{1'b1}} : data_cal[2]; end SEND_DATA: begin if (in_ready && !in_receive) begin out_en <= 1; - out_data <= { - data_cal[0][OUT_DEPTH-1:0], data_cal[1][OUT_DEPTH-1:0], data_cal[2][OUT_DEPTH-1:0] - }; + out_data[0] <= data_cal[0][OUT_DEPTH-1:0]; + out_data[1] <= data_cal[1][OUT_DEPTH-1:0]; + out_data[2] <= data_cal[2][OUT_DEPTH-1:0]; end else out_en <= 0; end diff --git a/Color/GammaCorrection.v b/Color/GammaCorrection.v index e1dd429..8dbe6c2 100644 --- a/Color/GammaCorrection.v +++ b/Color/GammaCorrection.v @@ -7,16 +7,17 @@ module GammaCorrection #( input wire reset, input wire in_en, - input wire [COLOR_DEPTH - 1 : 0] in_data [3], + input wire [COLOR_DEPTH - 1 : 0] in_data[3], output wire out_ready, output wire out_receive, output reg out_en, - output reg [COLOR_DEPTH - 1 : 0] out_data [3], + output reg [COLOR_DEPTH - 1 : 0] out_data[3], input wire in_ready, input wire in_receive, - input wire [8:0] gamma + input wire enable, + input wire [9:0] gamma_inverse ); reg [2:0] state, nextState; localparam reg [2:0] READ_DATA = 0; @@ -39,13 +40,48 @@ module GammaCorrection #( endcase end + assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0; + assign out_receive = (in_en && state == READ_DATA) ? 1 : 0; + always @(posedge clk or posedge reset) begin if (reset) begin out_en <= 0; - out_data <= 0; - end - else begin - + out_data[0] <= 0; + out_data[1] <= 0; + out_data[2] <= 0; + + data_cal[0] <= 0; + data_cal[1] <= 0; + data_cal[2] <= 0; + end else begin + case (state) + READ_DATA: begin + if (in_en) begin + data_cal[0] <= {8'b0, in_data[0]}; + data_cal[1] <= {8'b0, in_data[1]}; + data_cal[2] <= {8'b0, in_data[2]}; + end + end + + CALC_DATA: begin + if (enable) begin + data_cal[0] <= data_cal[0] ** gamma_inverse; + data_cal[1] <= data_cal[1] ** gamma_inverse; + data_cal[2] <= data_cal[2] ** gamma_inverse; + end + end + + SEND_DATA: begin + if (in_ready) begin + out_en <= 1; + out_data[0] <= data_cal[0][COLOR_DEPTH-1 : 0]; + out_data[1] <= data_cal[1][COLOR_DEPTH-1 : 0]; + out_data[2] <= data_cal[2][COLOR_DEPTH-1 : 0]; + end else out_en <= 0; + end + + default: ; + endcase end end diff --git a/Color/GammaCorrection2.v b/Color/GammaCorrection2.v new file mode 100644 index 0000000..c4e6163 --- /dev/null +++ b/Color/GammaCorrection2.v @@ -0,0 +1,85 @@ +`timescale 1ns / 1ps + +module GammaCorrection2 #( + parameter reg [4:0] COLOR_DEPTH = 8 +) ( + input wire clk, + input wire reset, + + input wire in_en, + input wire [COLOR_DEPTH - 1 : 0] in_data[3], + output wire out_ready, + output wire out_receive, + + output reg out_en, + output reg [COLOR_DEPTH - 1 : 0] out_data[3], + input wire in_ready, + input wire in_receive, + + input wire [7:0] gamma_table[256], + input wire enable +); + reg [2:0] state, nextState; + localparam reg [2:0] READ_DATA = 0; + localparam reg [2:0] SEND_DATA = 2; + + reg [7:0] data_cache[3]; + + always @(posedge clk or posedge reset) begin + if (reset) state <= READ_DATA; + else state <= nextState; + end + + always @(*) begin + case (state) + READ_DATA: nextState = in_en ? SEND_DATA : READ_DATA; + SEND_DATA: nextState = in_receive ? READ_DATA : SEND_DATA; + default: nextState = READ_DATA; + endcase + end + + assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0; + assign out_receive = (in_en && state == READ_DATA) ? 1 : 0; + + always @(posedge clk or posedge reset) begin + if (reset) begin + out_en <= 0; + out_data[0] <= 0; + out_data[1] <= 0; + out_data[2] <= 0; + + data_cache[0] <= 0; + data_cache[1] <= 0; + data_cache[2] <= 0; + end else begin + case (state) + READ_DATA: begin + if (in_en) begin + data_cache[0] <= in_data[0]; + data_cache[1] <= in_data[1]; + data_cache[2] <= in_data[2]; + end + end + + SEND_DATA: begin + if (in_ready) begin + out_en <= 1; + if (enable) begin + out_data[0] <= gamma_table[data_cache[0]]; + out_data[1] <= gamma_table[data_cache[1]]; + out_data[2] <= gamma_table[data_cache[2]]; + end else begin + out_data[0] <= data_cache[0]; + out_data[1] <= data_cache[1]; + out_data[2] <= data_cache[2]; + end + end else out_en <= 0; + end + + default: ; + endcase + end + end + + +endmodule diff --git a/isp.v b/isp.v index ab901d4..bf2183f 100644 --- a/isp.v +++ b/isp.v @@ -28,7 +28,12 @@ module isp #( input wire [15:0] gain_red, input wire [15:0] gain_green, input wire [15:0] gain_blue, - input wire color_correction // 是否启用颜色校正 + input wire blender_enable, // 是否启用颜色校正 + + // Gamma矫正,低八位为小数位 + // input wire [7:0] gamma_inverse, + input wire [7:0] gamma_table [256], + input wire gamma_enable ); localparam reg [15:0] BAYER_WIDTH = IN_WIDTH - 2; localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 2; @@ -36,9 +41,13 @@ module isp #( wire blender_en, blender_ready, blender_receive; wire [15:0] blender_r, blender_g, blender_b; + // Gamma矫正 + wire gamma_en, gamma_ready, gamma_receive; + wire [COLOR_DEPTH - 1 : 0] gamma_data[3]; + // 任意比例缩放图像 wire crop_en, crop_ready, crop_receive; // scaler 请求数据 - reg [3 * COLOR_DEPTH - 1:0] crop_data; + reg [COLOR_DEPTH - 1:0] crop_data[3]; // 写入RAM // wire RAM_in_en; @@ -51,7 +60,7 @@ module isp #( .IM_WIDTH (IN_WIDTH), .IM_HEIGHT(IN_HEIGHT), .RAW_TYPE (RAW_TYPE) - ) CFA ( + ) inst_demosaic ( .clk(clk), .reset(reset), .in_en(in_en), @@ -70,7 +79,7 @@ module isp #( ColorBlender #( .IN_DEPTH (12), .OUT_DEPTH(8) - ) blender ( + ) inst_blender ( .clk (clk), .reset(reset), @@ -79,15 +88,57 @@ module isp #( .out_ready(blender_ready), .out_receive(blender_receive), + .in_ready(gamma_ready), + .in_receive(gamma_receive), + .out_en(gamma_en), + .out_data(gamma_data), + + .gain_red(gain_red), + .gain_green(gain_green), + .gain_blue(gain_blue), + .enable(blender_enable) + ); + + // 计算型Gamma校正 + // GammaCorrection #( + // .COLOR_DEPTH(COLOR_DEPTH) + // ) inst_gamma ( + // .clk (clk), + // .reset(reset), + + // .in_en(gamma_en), + // .in_data(gamma_data), + // .out_ready(gamma_ready), + // .out_receive(gamma_receive), + + // .in_ready(crop_ready), + // .in_receive(crop_receive), + // .out_en(crop_en), + // .out_data(crop_data), + + // .gamma_inverse(gamma_inverse), + // .enable(gamma_enable) + // ); + + // 查找表型Gamma校正 + GammaCorrection2 #( + .COLOR_DEPTH(COLOR_DEPTH) + ) inst_gamma ( + .clk (clk), + .reset(reset), + + .in_en(gamma_en), + .in_data(gamma_data), + .out_ready(gamma_ready), + .out_receive(gamma_receive), + .in_ready(crop_ready), .in_receive(crop_receive), .out_en(crop_en), .out_data(crop_data), - .gain_red(gain_red), - .gain_green(gain_green), - .gain_blue(gain_blue), - .color_correction(color_correction) + .gamma_table(gamma_table), + .enable(gamma_enable) ); Crop #( @@ -96,14 +147,14 @@ module isp #( .OUT_WIDTH(OUT_WIDTH), .OUT_HEIGHT(OUT_HEIGHT), .COLOR_DEPTH(COLOR_DEPTH) - ) crop_process ( + ) inst_crop ( .clk (clk), .reset(reset), .in_en(crop_en), .out_ready(crop_ready), .out_receive(crop_receive), - .in_data(crop_data), + .in_data({crop_data[2], crop_data[1], crop_data[0]}), .out_en(out_en), .in_ready(in_ready), diff --git a/sim/sc_main.cpp b/sim/sc_main.cpp index f3a3609..ac763a5 100644 --- a/sim/sc_main.cpp +++ b/sim/sc_main.cpp @@ -207,11 +207,15 @@ int sc_main(int argc, char* argv[]) { sc_signal out_receive; sc_signal out_data; - sc_signal color_correction; + sc_signal blender_enable; sc_signal gain_red; sc_signal gain_green; sc_signal gain_blue; + sc_signal gamma_enable; + sc_signal gamma_inverse; + sc_signal gamma_table[256]; + sc_signal flag_done; // Construct the Verilated model, from inside Visp.h @@ -236,12 +240,22 @@ int sc_main(int argc, char* argv[]) { isp->gain_red(gain_red); isp->gain_green(gain_green); isp->gain_blue(gain_blue); - isp->color_correction(color_correction); + isp->blender_enable(blender_enable); - color_correction.write(true); // enable color correction - gain_red.write((uint32_t)(color_gain.red * std::pow(2, 8))); - gain_green.write((uint32_t)(color_gain.green * std::pow(2, 8))); - gain_blue.write((uint32_t)(color_gain.blue * std::pow(2, 8))); + isp->gamma_enable(gamma_enable); + // isp->gamma_inverse(gamma_inverse); + + blender_enable = true; // enable color correction + gain_red = (uint32_t)(color_gain.red * std::pow(2, 8)); + gain_green = (uint32_t)(color_gain.green * std::pow(2, 8)); + gain_blue = (uint32_t)(color_gain.blue * std::pow(2, 8)); + + gamma_enable = true; + gamma_inverse = (uint32_t)((1.0 / gamma_value) * std::pow(2, 8)); + for (int i = 0; i < 256; i++) { + isp->gamma_table[i](gamma_table[i]); + gamma_table[i] = (uint32_t)(255 * pow(i / 255.0, 1.0 / gamma_value)); + } // Construct testbench module TB_ISP tb_isp("tb_isp");