diff --git a/Color/ColorBlender.sv b/Color/ColorBlender.sv index 695ad39..9492503 100644 --- a/Color/ColorBlender.sv +++ b/Color/ColorBlender.sv @@ -34,7 +34,7 @@ module ColorBlender #( reg [2:0] state, nextState; reg [BUFF_SIZE - 1:0] data_cal[3]; // 用于保存运算结果,防止溢出 - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) begin state <= READ_DATA; end else begin @@ -55,7 +55,7 @@ module ColorBlender #( 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 + always @(posedge clk) begin if (reset) begin // 初始化 data_cal[0] <= 0; diff --git a/Color/GammaCorrection2.sv b/Color/GammaCorrection2.sv index c4e6163..b83f289 100644 --- a/Color/GammaCorrection2.sv +++ b/Color/GammaCorrection2.sv @@ -25,7 +25,7 @@ module GammaCorrection2 #( reg [7:0] data_cache[3]; - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) state <= READ_DATA; else state <= nextState; end @@ -41,7 +41,7 @@ module GammaCorrection2 #( 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 + always @(posedge clk) begin if (reset) begin out_en <= 0; out_data[0] <= 0; diff --git a/Color/GreyWorld.sv b/Color/GreyWorld.sv new file mode 100644 index 0000000..2bf8951 --- /dev/null +++ b/Color/GreyWorld.sv @@ -0,0 +1,134 @@ + +`timescale 1ns / 1ps + +// 三通道图像合成一个RGB图像 +module GreyWorld #( + parameter reg [4:0] COLOR_DEPTH = 8, + parameter reg [31:0] IM_SIZE = 1920 * 1080 +) ( + input wire clk, + input wire reset, + + input wire in_en, + input wire [7:0] in_data[3], // 0:R 1:G 2:B + output wire out_ready, + output wire out_receive, + + // 输出相关 + input wire in_ready, + input wire in_receive, + output reg out_en, + output reg [COLOR_DEPTH - 1:0] out_data[3], + + // Gain: red = 0.803881, green = 0.885894, blue = 1.594308 + input wire enable, + input wire [8:0] flame_rate, + input wire [31:0] white_gain[3] +); + + reg [2:0] state, nextState; + localparam reg [2:0] READ_DATA = 0; + localparam reg [2:0] CALC_DATA = 1; + localparam reg [2:0] SEND_DATA = 2; + + reg [8:0] cnt_flame; + reg [31:0] red_total, green_total, blue_total, r_white_gain[3]; + reg [31:0] data_cal[3], data_cache[3]; + reg [31:0] cnt_pexels; + wire [31:0] average; + + always @(posedge clk) begin + if (reset) state <= READ_DATA; + else state <= nextState; + end + + always @(*) begin + case (state) + READ_DATA: nextState = in_en ? CALC_DATA : READ_DATA; + CALC_DATA: nextState = SEND_DATA; + SEND_DATA: nextState = in_receive ? READ_DATA : SEND_DATA; + default: nextState = READ_DATA; + endcase + end + + assign out_ready = (!in_en && !reset) ? 1 : 0; + assign out_receive = (in_en && !reset) ? 1 : 0; + + assign average = ((red_total + green_total + blue_total) << 8) / (3 * IM_SIZE); + + always @(posedge clk) begin + if (reset) begin + red_total <= 0; + green_total <= 0; + blue_total <= 0; + cnt_flame <= flame_rate; + cnt_pexels <= 0; + r_white_gain[0] <= white_gain[0]; + r_white_gain[1] <= white_gain[1]; + r_white_gain[2] <= white_gain[2]; + data_cache[0] <= 0; + data_cache[1] <= 0; + data_cache[2] <= 0; + + out_en <= 0; + out_data[0] <= 0; + out_data[1] <= 0; + out_data[2] <= 0; + end else begin + case (state) + READ_DATA: begin + if (in_en) begin + data_cache[0] <= {24'b0, in_data[0]}; + data_cache[1] <= {24'b0, in_data[1]}; + data_cache[2] <= {24'b0, in_data[2]}; + + if (cnt_flame == flame_rate) begin + red_total <= red_total + {24'b0, in_data[0]}; + green_total <= green_total + {24'b0, in_data[0]}; + blue_total <= blue_total + {24'b0, in_data[0]}; + end + + if (cnt_pexels < IM_SIZE) begin + cnt_pexels <= cnt_pexels + 1; + end else begin + cnt_pexels <= 0; + if (cnt_flame < flame_rate) cnt_flame <= cnt_flame + 1; + else cnt_flame <= 0; + end + end + end + + CALC_DATA: begin + if (cnt_pexels >= IM_SIZE && cnt_flame == flame_rate) begin + r_white_gain[0] <= (average * ( IM_SIZE << 8 )) / red_total; + r_white_gain[1] <= (average * ( IM_SIZE << 8)) / green_total; + r_white_gain[2] <= (average * ( IM_SIZE << 8)) / blue_total; + end + + data_cal[0] <= (data_cache[0] * r_white_gain[0]); + data_cal[1] <= (data_cache[1] * r_white_gain[1]); + data_cal[2] <= (data_cache[2] * r_white_gain[2]); + end + + SEND_DATA: begin + if (in_ready) begin + out_en <= 1; + if (enable) begin + out_data[0] <= (|data_cal[0][31:16]) ? 255 : (data_cal[0] > 0 ? data_cal[0][15:8] : 0); + out_data[1] <= (|data_cal[1][31:16]) ? 255 : (data_cal[1] > 0 ? data_cal[1][15:8] : 0); + out_data[2] <= (|data_cal[2][31:16]) ? 255 : (data_cal[2] > 0 ? data_cal[2][15:8] : 0); + end else begin + out_data[0] <= data_cache[0][7:0]; + out_data[1] <= data_cache[1][7:0]; + out_data[2] <= data_cache[2][7:0]; + end + end else out_en <= 0; + end + default: ; + endcase + end + end + + + +endmodule diff --git a/Color/SaturationCorrection.sv b/Color/SaturationCorrection.sv index 78f6722..c1c0831 100644 --- a/Color/SaturationCorrection.sv +++ b/Color/SaturationCorrection.sv @@ -27,7 +27,7 @@ module SaturationCorrection #( reg signed [31:0] data_cal[3], data_cache[3]; wire signed [31:0] max, min, delta, value, light, saturation, alpha; - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) state <= READ_DATA; else state <= nextState; end @@ -60,7 +60,7 @@ module SaturationCorrection #( ? (65536 / saturation) - 256 : (65536 / (256 - saturation_inc)) - 256) : (saturation_inc); - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) begin out_en <= 0; out_data[0] <= 0; @@ -101,9 +101,9 @@ module SaturationCorrection #( if (in_ready) begin out_en <= 1; if (enable && delta != 0) begin - out_data[0] <= (data_cal[0] <= 65535) ? (data_cal[0] > 0 ? data_cal[0][15:8] : 0) : 255; - out_data[1] <= (data_cal[1] <= 65535) ? (data_cal[1] > 1 ? data_cal[1][15:8] : 1) : 255; - out_data[2] <= (data_cal[2] <= 65535) ? (data_cal[2] > 2 ? data_cal[2][15:8] : 2) : 255; + out_data[0] <= (|data_cal[0][31:16]) ? 255 : (data_cal[0] > 0 ? data_cal[0][15:8] : 0); + out_data[1] <= (|data_cal[1][31:16]) ? 255 : (data_cal[1] > 0 ? data_cal[1][15:8] : 0); + out_data[2] <= (|data_cal[2][31:16]) ? 255 : (data_cal[2] > 0 ? data_cal[2][15:8] : 0); end else begin out_data[0] <= data_cache[0][7:0]; out_data[1] <= data_cache[1][7:0]; diff --git a/Color/WhiteBalance.sv b/Color/WhiteBalance.sv index 5505f5e..8e3eeda 100644 --- a/Color/WhiteBalance.sv +++ b/Color/WhiteBalance.sv @@ -2,9 +2,11 @@ // 三通道图像合成一个RGB图像 module WhiteBalance #( - 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, + parameter reg [31:0] RAM_BEGIN_ADDR = 0, + parameter reg [31:0] IM_SIZE = 1920 * 1080 ) ( input wire clk, input wire reset, @@ -17,22 +19,116 @@ module WhiteBalance #( // 输出相关 input wire in_ready, input wire in_receive, - output reg out_en, - output reg [OUT_DEPTH - 1:0] out_data[3], + output wire out_en, + output wire [OUT_DEPTH - 1:0] out_data[3], input wire enable, - input wire [8:0] flame_rate + input wire [8:0] flame_rate, + input wire [31:0] white_gain[3] ); - assign out_ready = (!reset) ? 1 : 0; - assign out_receive = (in_en && !reset) ? 1 : 0; + wire ram_read_en, ram_write_en, ram_read_ready, ram_write_ready; + wire [31:0] ram_read_data, ram_read_addr, ram_write_data, ram_write_addr; + + reg [8:0] cnt_flame; + reg [31:0] cnt_in_pic, cnt_out_pic, cnt_pixels; + reg [31:0] red_total, green_total, blue_total; + reg [31:0] r_white_gain[3]; + + wire is_finish_cal; + always @(*) begin + if (cnt_in_pic >= IM_SIZE) is_finish_cal = 1; + else if (cnt_out_pic >= IM_SIZE) is_finish_cal = 0; + else is_finish_cal = is_finish_cal; + end + + assign ram_read_addr = cnt_out_pic; + assign ram_write_addr = cnt_in_pic; + assign cnt_pixels = (is_finish_cal) + ? IM_SIZE - cnt_out_pic + cnt_in_pic + : cnt_in_pic - cnt_out_pic; + + assign out_ready = (!in_en && !reset && cnt_pixels < IM_SIZE) ? 1 : 0; + assign out_receive = (in_en && !reset && cnt_in_pic < IM_SIZE) ? 1 : 0; DiffWidthSyncFIFO #( + .DATA_WIDTH (8), + .DATA_DEPTH (12), + .READ_DEPTH (4), + .WRITE_DEPTH(3) + ) in_fifo ( + .clk(clk), + .reset(reset), + .read_ready(ram_write_ready), + .read_en(ram_write_en), + .read_data(ram_write_data), + .write_ready(in_ready), + .write_en(in_en), + .write_data(in_data) + ); - ) + DiffWidthSyncFIFO #( + .DATA_WIDTH (8), + .DATA_DEPTH (12), + .READ_DEPTH (3), + .WRITE_DEPTH(4) + ) out_fifo ( + .clk(clk), + .reset(reset), + .read_ready(out_ready), + .read_en(out_en), + .read_data(out_data), + .write_ready(ram_read_ready), + .write_en(ram_read_en), + .write_data(ram_read_data) + ); + SDRAM inst_RAM ( + .clk(clk), + .read_en(ram_read_en), + .read_addr(ram_read_addr), + .read_data(ram_read_data), + .read_ready(ram_read_ready), + .write_en(ram_write_en), + .write_addr(ram_write_addr), + .write_data(ram_write_data), + .write_ready(ram_write_ready) + ); + + // calculate white gain always @(posedge clk) begin - if(reset) begin + if (reset) begin + red_total <= 0; + green_total <= 0; + blue_total <= 0; + cnt_flame <= 0; + cnt_in_pic <= 0; + r_white_gain[0] <= white_gain[0]; + r_white_gain[1] <= white_gain[1]; + r_white_gain[2] <= white_gain[2]; + end else begin + if (in_en && cnt_pixels < IM_SIZE) begin + red_total <= red_total + in_data[0]; + green_total <= green_total + in_data[1]; + blue_total <= blue_total + in_data[2]; + if (cnt_in_pic < IM_SIZE) cnt_in_pic <= cnt_in_pic + 1; + else cnt_in_pic <= 0; + end else begin + + end + end + end + + // calculate out data + always @(posedge clk) begin + if (reset) begin + cnt_out_pic <= 0; + end else begin + if (out_ready && is_finish_cal) begin + out_en <= 1; + end else begin + out_en <= 0; + end end end diff --git a/Crop/Crop.v b/Crop/Crop.sv similarity index 79% rename from Crop/Crop.v rename to Crop/Crop.sv index 173e0a6..c17d86a 100644 --- a/Crop/Crop.v +++ b/Crop/Crop.sv @@ -13,12 +13,12 @@ module Crop #( input wire in_en, output wire out_ready, output wire out_receive, - input wire [3 * COLOR_DEPTH - 1:0] in_data, + input wire [COLOR_DEPTH - 1:0] in_data[3], input wire in_ready, input wire in_receive, output reg out_en, - output reg [3 * COLOR_DEPTH - 1:0] out_data + output reg [COLOR_DEPTH - 1:0] out_data[3] ); reg [1:0] state, nextState; localparam reg [1:0] READ_DATA = 0; @@ -26,11 +26,11 @@ module Crop #( localparam reg [1:0] SEND_DATA = 2; reg [15:0] cnt_x, cnt_y; - reg [3 * COLOR_DEPTH - 1:0] data; + reg [COLOR_DEPTH - 1:0] data[3]; wire is_valid; // 状态切换 - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) state <= READ_DATA; else state <= nextState; end @@ -50,19 +50,25 @@ module Crop #( assign is_valid = ((OFFSET_Y <= cnt_y && cnt_y <= (OFFSET_Y + OUT_HEIGHT - 1)) && (OFFSET_X <= cnt_x && cnt_x <= (OFFSET_X + OUT_WIDTH))) ? 1 : 0; - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) begin cnt_x <= 0; cnt_y <= 0; - data <= 0; + data[0] <= 0; + data[1] <= 0; + data[2] <= 0; out_en <= 0; - out_data <= 0; + out_data[0] <= 0; + out_data[1] <= 0; + out_data[2] <= 0; end else begin case (state) READ_DATA: begin if (in_en) begin - data <= in_data; + data[0] <= in_data[0]; + data[1] <= in_data[1]; + data[2] <= in_data[2]; end end @@ -82,7 +88,9 @@ module Crop #( SEND_DATA: begin if (in_ready && !in_receive && is_valid) begin out_en <= 1; - out_data <= data; + out_data[0] <= data[0]; + out_data[1] <= data[1]; + out_data[2] <= data[2]; end else out_en <= 0; end diff --git a/Demosaic/Demosaic2.sv b/Demosaic/Demosaic2.sv index 3a35fc5..ff49849 100644 --- a/Demosaic/Demosaic2.sv +++ b/Demosaic/Demosaic2.sv @@ -41,7 +41,7 @@ module Demosaic2 #( // 三段状态机实现,窗口滑动,颜色计算 // 状态切换 - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) state <= READ_DATA; else state <= nextState; end @@ -64,7 +64,7 @@ module Demosaic2 #( assign out_receive = (in_en && state == READ_DATA) ? 1 : 0; // 各状态执行的操作 - always @(posedge clk or posedge reset) begin + always @(posedge clk) begin if (reset) begin // 外部输出初始化 out_en <= 0; diff --git a/RAM/SDRAM.v b/RAM/SDRAM.v new file mode 100644 index 0000000..b007e81 --- /dev/null +++ b/RAM/SDRAM.v @@ -0,0 +1,29 @@ +module SDRAM ( + input wire clk, + + input wire read_en, + input wire [31:0] read_addr, + output wire [31:0] read_data, + output wire read_ready, + + input wire write_en, + input wire [31:0] write_addr, + input reg [31:0] write_data, + output wire write_ready +); + reg [31:0] ram[1920*1080]; + + assign read_ready = (!read_en) ? 1 : 0; + assign write_ready = (!write_en) ? 1 : 0; + + always @(posedge clk) begin + if (read_en) + ram[read_addr] <= read_data; + end + + always @(posedge clk) begin + if (write_en) + write_data <= ram[write_addr]; + end + +endmodule diff --git a/RAM/tb_DiffWidthSyncFIFO.v b/RAM/tb_DiffWidthSyncFIFO.sv similarity index 100% rename from RAM/tb_DiffWidthSyncFIFO.v rename to RAM/tb_DiffWidthSyncFIFO.sv diff --git a/isp.sv b/isp.sv index 5faa106..53f520d 100644 --- a/isp.sv +++ b/isp.sv @@ -32,36 +32,44 @@ module isp #( // Gamma矫正,低八位为小数位 // input wire [7:0] gamma_inverse, - input wire [7:0] gamma_table [256], + input wire [7:0] gamma_table[256], input wire gamma_enable, + // 白平衡 + input wire [31:0] white_gain[3], + input wire [8:0] flame_rate, + input wire white_enable, + // 饱和度校正 input wire signed [31:0] saturation_inc, - input wire saturation_enable // -256~256 + input wire saturation_enable // -256~256 ); localparam reg [15:0] BAYER_WIDTH = IN_WIDTH - 2; localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 2; - // 三通道合成RGB图像 + + wire [COLOR_DEPTH - 1:0] w_out_data[3]; + assign out_data = {w_out_data[2], w_out_data[1], w_out_data[0]}; + + // 颜色校正,并改变色深 wire blender_en, blender_ready, blender_receive; wire [15:0] blender_r, blender_g, blender_b; + // 裁切图像 + wire crop_en, crop_ready, crop_receive; // scaler 请求数据 + reg [COLOR_DEPTH - 1:0] crop_data[3]; + // Gamma矫正 wire gamma_en, gamma_ready, gamma_receive; wire [COLOR_DEPTH - 1 : 0] gamma_data[3]; + // 白平衡 + wire white_en, white_ready, white_receive; + wire [COLOR_DEPTH - 1 : 0] white_data[3]; + // 饱和度校正 wire saturation_en, saturation_ready, saturation_receive; wire [COLOR_DEPTH - 1 : 0] saturation_data[3]; - // 任意比例缩放图像 - wire crop_en, crop_ready, crop_receive; // scaler 请求数据 - reg [COLOR_DEPTH - 1:0] crop_data[3]; - - // 写入RAM - // wire RAM_in_en; - // wire RAM_in_que; // RAM 请求数据 - // wire [3 * COLOR_DEPTH - 1:0] RAM_in_data; - assign out_clk = clk; Demosaic2 #( @@ -86,7 +94,7 @@ module isp #( ColorBlender #( .IN_DEPTH (12), - .OUT_DEPTH(8) + .OUT_DEPTH(COLOR_DEPTH) ) inst_blender ( .clk (clk), .reset(reset), @@ -96,10 +104,10 @@ 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), + .in_ready(crop_ready), + .in_receive(crop_receive), + .out_en(crop_en), + .out_data(crop_data), .gain_red(gain_red), .gain_green(gain_green), @@ -107,26 +115,26 @@ module isp #( .enable(blender_enable) ); - // 计算型Gamma校正 - // GammaCorrection #( - // .COLOR_DEPTH(COLOR_DEPTH) - // ) inst_gamma ( - // .clk (clk), - // .reset(reset), + Crop #( + .IN_WIDTH(BAYER_WIDTH), + .IN_HEIGHT(BAYER_HEIGHT), + .OUT_WIDTH(OUT_WIDTH), + .OUT_HEIGHT(OUT_HEIGHT), + .COLOR_DEPTH(COLOR_DEPTH) + ) inst_crop ( + .clk (clk), + .reset(reset), - // .in_en(gamma_en), - // .in_data(gamma_data), - // .out_ready(gamma_ready), - // .out_receive(gamma_receive), + .in_en(crop_en), + .out_ready(crop_ready), + .out_receive(crop_receive), + .in_data({crop_data[2], crop_data[1], crop_data[0]}), - // .in_ready(crop_ready), - // .in_receive(crop_receive), - // .out_en(crop_en), - // .out_data(crop_data), - - // .gamma_inverse(gamma_inverse), - // .enable(gamma_enable) - // ); + .out_en(gamma_en), + .in_ready(gamma_ready), + .in_receive(gamma_receive), + .out_data({gamma_data[2], gamma_data[1], gamma_data[0]}) + ); // 查找表型Gamma校正 GammaCorrection2 #( @@ -150,57 +158,47 @@ module isp #( ); SaturationCorrection #( - .COLOR_DEPTH(COLOR_DEPTH) - ) inst_saturation ( - .clk (clk), - .reset (reset), - - .in_en(saturation_en), - .out_ready(saturation_ready), - .out_receive(saturation_receive), - .in_data(saturation_data), - - .in_ready(crop_ready), - .in_receive(crop_receive), - .out_en(crop_en), - .out_data(crop_data), - - .saturation_inc(saturation_inc), - .enable(saturation_enable) - ); - - Crop #( - .IN_WIDTH(BAYER_WIDTH), - .IN_HEIGHT(BAYER_HEIGHT), - .OUT_WIDTH(OUT_WIDTH), - .OUT_HEIGHT(OUT_HEIGHT), .COLOR_DEPTH(COLOR_DEPTH) - ) inst_crop ( + ) inst_saturation ( .clk (clk), .reset(reset), - .in_en(crop_en), - .out_ready(crop_ready), - .out_receive(crop_receive), - .in_data({crop_data[2], crop_data[1], crop_data[0]}), + .in_en(saturation_en), + .out_ready(saturation_ready), + .out_receive(saturation_receive), + .in_data(saturation_data), - .out_en(out_en), - .in_ready(in_ready), - .in_receive(in_receive), - .out_data(out_data) + .in_ready(white_ready), + .in_receive(white_receive), + .out_en(white_en), + .out_data(white_data), + + .saturation_inc(saturation_inc), + .enable(saturation_enable) ); - // RGB_to_RAM write_to_RAM ( - // .clk(clk), - // .reset(reset), + GreyWorld #( + .COLOR_DEPTH(COLOR_DEPTH), + .IM_SIZE({16'b0, OUT_WIDTH} * {16'b0, OUT_HEIGHT}) + ) inst_whitebalance ( + .clk (clk), + .reset(reset), + + .in_en(white_en), + .in_data(white_data), + .out_ready(white_ready), + .out_receive(white_receive), + + .in_ready(in_ready), + .in_receive(in_receive), + .out_en(out_en), + .out_data(w_out_data), + + .enable(white_enable), + .flame_rate(flame_rate), + .white_gain(white_gain) + ); - // .in_en(RAM_in_en), - // .in_que(RAM_in_que), - // .in_data(RAM_in_data), - // .write_que(out_que), - // .write_en(out_en), - // .data_write(out_data) - // ); endmodule diff --git a/sim/Makefile b/sim/Makefile index eabb5aa..f04bc99 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -32,6 +32,9 @@ VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage endif VERILATOR_FLAGS = +# Specify top module +TOP_MODULE = isp +VERILATOR_FLAGS += --top-module $(TOP_MODULE) # Generate SystemC in executable form VERILATOR_FLAGS += -sc --exe # Generate makefile dependencies (not shown as complicates the Makefile) @@ -52,12 +55,11 @@ VERILATOR_FLAGS += --threads 14 #VERILATOR_FLAGS += --debug # Add this trace to get a backtrace in gdb #VERILATOR_FLAGS += --gdbbt -# Specify top module -TOP_MODULE = isp -VERILATOR_FLAGS += -top $(TOP_MODULE) -# Input files for Verilator -VERILATOR_INPUT = ../isp.sv *.cpp ../Demosaic/Demosaic2.sv ../Crop/*.sv ../Color/*.sv ../RAM/*.sv +# Input files for Verilator +SOURCES := $(wildcard ../isp.sv *.cpp ../Demosaic/Demosaic2.sv ../Crop/*.sv ../Color/*.sv) +EXCLUDES := $(wildcard ../Color/WhiteBalance.sv ../Color/GammaCorrection.sv) +VERILATOR_INPUT := $(filter-out $(EXCLUDES), $(SOURCES)) # Check if SC exists via a verilator call (empty if not) SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) diff --git a/sim/sc_main.cpp b/sim/sc_main.cpp index 6fd179b..8a7e0f6 100644 --- a/sim/sc_main.cpp +++ b/sim/sc_main.cpp @@ -23,10 +23,11 @@ static const uint16_t IN_WIDTH = 1936; static const uint16_t IN_HEIGHT = 1088; -#define IN_SIZE (IN_WIDTH * IN_HEIGHT) +static const uint32_t IN_SIZE = (IN_WIDTH * IN_HEIGHT); static const uint16_t OUT_WIDTH = 1920; static const uint16_t OUT_HEIGHT = 1080; -#define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT) +static const uint32_t OUT_SIZE = (OUT_WIDTH * OUT_HEIGHT); +static const uint32_t FLAMES = 2; // color gain for correcting color struct color_gain { @@ -42,6 +43,8 @@ static const double white_radio = 0.1; using namespace sc_core; using namespace sc_dt; +bool picProcess(uint32_t* image, uint16_t number); + SC_MODULE(TB_ISP) { sc_in_clk clk; sc_in reset; @@ -69,9 +72,10 @@ SC_MODULE(TB_ISP) { } void send_Data(void) { - uint16_t pos_x = 0, pos_y = 0; + uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0; + bool is_finish = false; while (true) { - if (in_ready.read() && pos_y < IN_HEIGHT - 2) { + if (in_ready.read() && !is_finish) { out_en.write(1); printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, @@ -85,13 +89,18 @@ SC_MODULE(TB_ISP) { out_data[1].write(image[(pos_y + 1) * IN_WIDTH + pos_x]); out_data[2].write(image[(pos_y + 2) * IN_WIDTH + pos_x]); - // wait(1); - // out_en.write(0); - - if (++pos_x >= IN_WIDTH) { + pos_x++; + if (pos_x >= IN_WIDTH) { pos_x = 0; pos_y++; } + if (pos_y >= IN_HEIGHT - 2) { + pos_y = 0; + cnt_flame++; + } + if (cnt_flame >= FLAMES) { + is_finish = true; + } } else { out_en.write(0); } @@ -102,11 +111,11 @@ SC_MODULE(TB_ISP) { void read_Data(void) { is_done.write(0); - uint16_t pos_x = 0, pos_y = 0; - uint32_t last_data = 0; - uint32_t cnt = 0; + uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0; + uint32_t last_data = 0, cnt = 0; + bool is_finish = false; while (true) { - if (im_en.read()) { + if (im_en.read() && !is_finish) { out_ready.write(false); out_receceive.write(true); @@ -116,13 +125,21 @@ SC_MODULE(TB_ISP) { pos_x = 0; pos_y++; } + if (pos_y >= OUT_HEIGHT) { + pos_y = 0; + picProcess(out.get(), cnt_flame); + cnt_flame++; + } + if (cnt_flame >= FLAMES) { + is_finish = true; + } } else { out_ready.write(true); out_receceive.write(false); } // when data didn't change some time, it end - if (last_data == im_data.read()) { + if (last_data == im_data.read() && is_finish) { cnt++; if (cnt >= 100000L) { is_done.write(1); @@ -138,13 +155,111 @@ SC_MODULE(TB_ISP) { } }; +bool picProcess(uint32_t* image, uint16_t number) { + uint8_t* data = + new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 + + // software algorthms analyze + uint32_t red_total = 0, green_total = 0, blue_total = 0; + uint8_t red_max = 0, green_max = 0, blue_max = 0; + for (int32_t y = 0; y < OUT_HEIGHT; ++y) { + for (int32_t x = 0; x < OUT_WIDTH; ++x) { + int32_t index = (y * OUT_WIDTH + x) * 3; + + uint8_t red = (image[y * OUT_WIDTH + x] & 0x00ff0000) >> 16; + uint8_t green = (image[y * OUT_WIDTH + x] & 0x0000ff00) >> 8; + uint8_t blue = (image[y * OUT_WIDTH + x] & 0x000000ff); + + // Adjust gamma line + // red = 255 * std::pow(red / 255.0, 1 / gamma_value); + // green = 255 * std::pow(green / 255.0, 1 / gamma_value); + // blue = 255 * std::pow(blue / 255.0, 1 / gamma_value); + + // Calculate white balance data + // red_max = std::max(red_max, red); + // green_max = std::max(green_max, green); + // blue_max = std::max(blue_max, blue); + // red_total += red; + // green_total += green; + // blue_total += blue; + + // Adjust vibrance + // uint8_t max = std::max({red, green, blue}); + // uint8_t min = std::min({red, green, blue}); + // double delta = (max - min) / 255.0; + // double value = (max + min) / 255.0; + // if (delta != 0) { + // double L = value / 2.0; + // // double S = (L <= 0.5) ? delta / value : delta / (2 - + // value); double S = delta / max; double alpha = 0.0; if + // (saturation_inc >= 0) { + // if ((saturation_inc + S) >= 1) + // alpha = S; + // else + // alpha = 1 - saturation_inc; + // alpha = 1 / alpha - 1; + // red = static_cast(red + (red - L * 255) * alpha); + // green = + // static_cast(green + (green - L * 255) * + // alpha); + // blue = static_cast(blue + (blue - L * 255) * + // alpha); + // } else { + // alpha = saturation_inc; + // red = static_cast(L * 255 + + // (red - L * 255) * (1 + alpha)); + // green = static_cast(L * 255 + + // (green - L * 255) * (1 + + // alpha)); + // blue = static_cast(L * 255 + + // (blue - L * 255) * (1 + + // alpha)); + // } + // } + + // save data + data[index + 0] = red; // R + data[index + 1] = green; // G + data[index + 2] = blue; // B + } + } + + // Adjust White Balance : Grey World Color Correction + // double K = static_cast(red_total + green_total + blue_total) / + // (3 * OUT_SIZE); + // white_gain.red = static_cast(K * OUT_SIZE) / red_total; + // white_gain.green = static_cast(K * OUT_SIZE) / green_total; + // white_gain.blue = static_cast(K * OUT_SIZE) / blue_total; + // printf("Gain: red = %f, green = %f, blue = %f", white_gain.red, + // white_gain.green, white_gain.blue); + // for (int32_t y = 0; y < OUT_HEIGHT; ++y) { + // for (int32_t x = 0; x < OUT_WIDTH; ++x) { + // int32_t index = (y * OUT_WIDTH + x) * 3; + + // data[index + 0] = + // static_cast(white_gain.red * data[index + 0]); + // data[index + 1] = + // static_cast(white_gain.green * data[index + 1]); + // data[index + 2] = + // static_cast(white_gain.blue * data[index + 2]); + // } + // } + + // save to bmp + std::cout << "Ready to save raw RGB image" << std::endl; + char file_name[64] = {0}; + snprintf(file_name, sizeof(file_name), "pic_%d.bmp", number); + write_bmp(file_name, data, OUT_WIDTH, OUT_HEIGHT); + delete[] data; + + return true; +} + int sc_main(int argc, char* argv[]) { std::cout << "Get into sc_main" << std::endl; // Open image std::ifstream in_image; - std::ofstream out_image; in_image.open("./transform/test.bin", std::ios::in | std::ios::binary); - // out_image.open("./transform/out.bin", std::ios::out | std::ios::binary); if (!in_image.is_open()) { std::cout << "Open image fail" << std::endl; exit(0); @@ -218,6 +333,10 @@ int sc_main(int argc, char* argv[]) { sc_signal gamma_inverse; sc_signal gamma_table[256]; + sc_signal white_gain[3]; + sc_signal flame_rate; + sc_signal white_enable; + sc_signal saturation_enable; sc_signal saturation_increase; @@ -250,6 +369,12 @@ int sc_main(int argc, char* argv[]) { isp->gamma_enable(gamma_enable); // isp->gamma_inverse(gamma_inverse); + isp->white_enable(white_enable); + isp->flame_rate(flame_rate); + isp->white_gain[0](white_gain[0]); + isp->white_gain[1](white_gain[1]); + isp->white_gain[2](white_gain[2]); + isp->saturation_enable(saturation_enable); isp->saturation_inc(saturation_increase); @@ -266,6 +391,12 @@ int sc_main(int argc, char* argv[]) { gamma_table[i] = (uint32_t)(255 * pow(i / 255.0, 1.0 / gamma_value)); } + white_enable = true; + flame_rate = 0; + white_gain[0] = 255; + white_gain[1] = 255; + white_gain[2] = 255; + saturation_enable = true; saturation_increase = (int32_t)((saturation_inc >= 0) ? (saturation_inc * std::pow(2, 8)) @@ -333,117 +464,6 @@ int sc_main(int argc, char* argv[]) { tfp = nullptr; } - uint8_t* data = - new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 - - // software algorthms analyze - uint32_t red_total = 0, green_total = 0, blue_total = 0; - uint8_t red_max = 0, green_max = 0, blue_max = 0; - for (int32_t y = 0; y < OUT_HEIGHT; ++y) { - for (int32_t x = 0; x < OUT_WIDTH; ++x) { - int32_t index = (y * OUT_WIDTH + x) * 3; - - uint8_t red = (tb_isp.out[y * OUT_WIDTH + x] & 0x00ff0000) >> 16; - uint8_t green = (tb_isp.out[y * OUT_WIDTH + x] & 0x0000ff00) >> 8; - uint8_t blue = (tb_isp.out[y * OUT_WIDTH + x] & 0x000000ff); - - // Adjust gamma line - // red = 255 * std::pow(red / 255.0, 1 / gamma_value); - // green = 255 * std::pow(green / 255.0, 1 / gamma_value); - // blue = 255 * std::pow(blue / 255.0, 1 / gamma_value); - - // Calculate white balance data - red_max = std::max(red_max, red); - green_max = std::max(green_max, green); - blue_max = std::max(blue_max, blue); - red_total += red; - green_total += green; - blue_total += blue; - - // Adjust vibrance - // uint8_t max = std::max({red, green, blue}); - // uint8_t min = std::min({red, green, blue}); - // double delta = (max - min) / 255.0; - // double value = (max + min) / 255.0; - // if (delta != 0) { - // double L = value / 2.0; - // // double S = (L <= 0.5) ? delta / value : delta / (2 - - // value); double S = delta / max; double alpha = 0.0; if - // (saturation_inc >= 0) { - // if ((saturation_inc + S) >= 1) - // alpha = S; - // else - // alpha = 1 - saturation_inc; - // alpha = 1 / alpha - 1; - // red = static_cast(red + (red - L * 255) * alpha); - // green = - // static_cast(green + (green - L * 255) * - // alpha); - // blue = static_cast(blue + (blue - L * 255) * - // alpha); - // } else { - // alpha = saturation_inc; - // red = static_cast(L * 255 + - // (red - L * 255) * (1 + alpha)); - // green = static_cast(L * 255 + - // (green - L * 255) * (1 + - // alpha)); - // blue = static_cast(L * 255 + - // (blue - L * 255) * (1 + - // alpha)); - // } - // } - - data[index + 0] = red; // R - data[index + 1] = green; // G - data[index + 2] = blue; // B - } - } - - // Adjust White Balance : Grey World Color Correction - double K = static_cast(red_total + green_total + blue_total) / (3 * OUT_SIZE); - white_gain.red = static_cast(K * OUT_SIZE) / red_total; - white_gain.green = static_cast(K * OUT_SIZE) / green_total; - white_gain.blue = static_cast(K * OUT_SIZE) / blue_total; - printf("Gain: red = %f, green = %f, blue = %f", white_gain.red, - white_gain.green, white_gain.blue); - for (int32_t y = 0; y < OUT_HEIGHT; ++y) { - for (int32_t x = 0; x < OUT_WIDTH; ++x) { - int32_t index = (y * OUT_WIDTH + x) * 3; - - data[index + 0] = - static_cast(white_gain.red * data[index + 0]); - data[index + 1] = - static_cast(white_gain.green * data[index + 1]); - data[index + 2] = - static_cast(white_gain.blue * data[index + 2]); - } - } - - // save to bin - std::cout << "Ready to save raw RGB image" << std::endl; - // for (int32_t y = 0; y < OUT_HEIGHT; ++y) { - // for (int32_t x = 0; x < OUT_WIDTH; ++x) { - // int32_t index = (y * OUT_WIDTH + x) * 3; - - // uint8_t red = data[index + 0]; - // uint8_t green = data[index + 1]; - // uint8_t blue = data[index + 2]; - - // out_image.write((const char*)&red, sizeof(red)); - // out_image.write((const char*)&green, sizeof(green)); - // out_image.write((const char*)&blue, sizeof(blue)); - - // printf("x=%4d, y=%4d, red=0x%02x, green=0x%02x, blue=0x%02x\n", - // x, - // y, red, green, blue); - // } - // } - - // save to bmp - write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT); - delete[] data; - // Return good completion status return 0; }