diff --git a/ColorBlender/ColorBlender.v b/ColorBlender/ColorBlender.v index a79faae..3b3c108 100644 --- a/ColorBlender/ColorBlender.v +++ b/ColorBlender/ColorBlender.v @@ -2,36 +2,37 @@ // 三通道图像合成一个RGB图像 module ColorBlender #( - parameter reg [ 4:0] IN_DEPTH = 12, // 输入图像的色深 - parameter reg [ 4:0] OUT_DEPTH = 8, // 输出图像的色深 - parameter reg [16:0] GAIN_RED = 120, // 红色增益系数 - parameter reg [16:0] GAIN_GREEN = 50, // 绿色增益系数 - parameter reg [16:0] GAIN_BLUE = 95, // 蓝色增益系数 - parameter reg [ 4:0] GAIN_OFFSET = 7 + parameter reg [ 4:0] IN_DEPTH = 12, // 输入图像的色深 + parameter reg [ 4:0] OUT_DEPTH = 8, // 输出图像的色深 + parameter reg [ 8:0] BUFF_SIZE = 32 ) ( - input clk, - input reset, + input wire clk, + input wire reset, - input in_en, - input [15:0] data_in[2], // 0:R 1:G 2:B - output out_ready, - output out_receive, + input wire in_en, + input wire [15:0] in_data[3], // 0:R 1:G 2:B + output wire out_ready, + output wire out_receive, // 输出相关 - input in_ready, - input in_receive, - output out_en, - output [3 * OUT_DEPTH - 1:0] out_data, + input wire in_ready, + input wire in_receive, + output reg out_en, + output reg [3 * OUT_DEPTH - 1:0] out_data, // 颜色校正 + input wire [15:0] gain_red, + input wire [15:0] gain_green, + input wire [15:0] gain_blue, input wire color_correction ); - localparam READ_DATA = 0; - localparam CALC_DATA = 1; - localparam SEND_DATA = 2; + localparam reg [2:0] READ_DATA = 0; + localparam reg [2:0] CALC_DATA = 1; + localparam reg [2:0] SATI_DATA = 2; + localparam reg [2:0] SEND_DATA = 3; reg [2:0] state, nextState; - reg [31:0] data_cal[2]; // 用于保存运算结果,防止溢出 + reg [BUFF_SIZE - 1:0] data_cal[3]; // 用于保存运算结果,防止溢出 always @(posedge clk or posedge reset) begin if (reset) begin @@ -44,15 +45,15 @@ module ColorBlender #( always @(*) begin case (state) READ_DATA: nextState = (in_en) ? (color_correction ? CALC_DATA : SEND_DATA) : READ_DATA; - CALC_DATA: nextState = SEND_DATA; + CALC_DATA: nextState = SATI_DATA; + SATI_DATA: nextState = SEND_DATA; SEND_DATA: nextState = (in_receive) ? READ_DATA : SEND_DATA; - default: nextState = READ_DATA; + default: nextState = READ_DATA; endcase end - assign out_ready = (state == READ_DATA) ? 1 : 0; - assign out_receive = in_en ? 1 : 0; - assign out_en = (in_ready && state == SEND_DATA) ? 1 : 0; + 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 @@ -60,28 +61,38 @@ module ColorBlender #( data_cal[0] <= 0; data_cal[1] <= 0; data_cal[2] <= 0; + + out_data <= 0; + out_en <= 0; end else begin case (state) READ_DATA: begin if (in_en) begin - data_cal[0] <= ({16'b0, data_in[0]} << 8; - data_cal[1] <= ({16'b0, data_in[1]} << 8; - data_cal[2] <= ({16'b0, data_in[2]} << 8; + data_cal[0] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[0]}) << (8 - (IN_DEPTH - OUT_DEPTH)); + data_cal[1] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[1]}) << (8 - (IN_DEPTH - OUT_DEPTH)); + data_cal[2] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[2]}) << (8 - (IN_DEPTH - OUT_DEPTH)); end end CALC_DATA: begin - data_cal[0] <= data_cal[0] * (GAIN_RED << 8) - data_cal[1] <= data_cal[1] * (GAIN_GREEN << 8) - data_cal[2] <= data_cal[2] * (GAIN_BLUE << 8) + 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 + + 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]; end SEND_DATA: begin - if (in_ready) begin - out_data[0] <= data_cal[0] >> (8 + IN_DEPTH - OUT_DEPTH) - out_data[1] <= data_cal[1] >> (8 + IN_DEPTH - OUT_DEPTH) - out_data[2] <= data_cal[2] >> (8 + IN_DEPTH - OUT_DEPTH) - end + 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] + }; + end else out_en <= 0; end default: ; diff --git a/Crop/Crop.v b/Crop/Crop.v new file mode 100644 index 0000000..173e0a6 --- /dev/null +++ b/Crop/Crop.v @@ -0,0 +1,95 @@ +module Crop #( + parameter reg [15:0] IN_WIDTH = 1934, + parameter reg [15:0] IN_HEIGHT = 1086, + parameter reg [15:0] OFFSET_X = 8, + parameter reg [15:0] OFFSET_Y = 4, + parameter reg [15:0] OUT_WIDTH = 640, + parameter reg [15:0] OUT_HEIGHT = 480, + parameter reg [4:0] COLOR_DEPTH = 8 +) ( + input wire clk, + input wire reset, + + input wire in_en, + output wire out_ready, + output wire out_receive, + input wire [3 * COLOR_DEPTH - 1:0] in_data, + + input wire in_ready, + input wire in_receive, + output reg out_en, + output reg [3 * COLOR_DEPTH - 1:0] out_data +); + reg [1:0] state, nextState; + localparam reg [1:0] READ_DATA = 0; + localparam reg [1:0] HANDLE_DATA = 1; + localparam reg [1:0] SEND_DATA = 2; + + reg [15:0] cnt_x, cnt_y; + reg [3 * COLOR_DEPTH - 1:0] data; + wire is_valid; + + // 状态切换 + 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 ? HANDLE_DATA : READ_DATA; + HANDLE_DATA: nextState = SEND_DATA; + SEND_DATA: nextState = (is_valid && !in_receive) ? SEND_DATA : READ_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; + 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 + if (reset) begin + cnt_x <= 0; + cnt_y <= 0; + data <= 0; + + out_en <= 0; + out_data <= 0; + end else begin + case (state) + READ_DATA: begin + if (in_en) begin + data <= in_data; + end + end + + HANDLE_DATA: begin + if (cnt_x >= IN_WIDTH - 1) begin + cnt_x <= 0; + cnt_y <= cnt_y + 1; + end else begin + cnt_x <= cnt_x + 1; + end + + if (cnt_y >= IN_HEIGHT - 1) begin + cnt_y <= 0; + end + end + + SEND_DATA: begin + if (in_ready && !in_receive && is_valid) begin + out_en <= 1; + out_data <= data; + end else out_en <= 0; + end + + default: ; + + endcase + end + end + +endmodule diff --git a/Crop/crop.v b/Crop/crop.v deleted file mode 100644 index fc8299e..0000000 --- a/Crop/crop.v +++ /dev/null @@ -1,91 +0,0 @@ -module crop #( - parameter IN_WIDTH = 1934, - parameter IN_HEIGHT = 1086, - parameter OFFSET_X = 8, - parameter OFFSET_Y = 4, - parameter OUT_WIDTH = 640, - parameter OUT_HEIGHT = 480, - parameter COLOR_DEPTH = 8 -) ( - input clk, - input reset, - - input in_en, - output reg in_que, - input [3 * COLOR_DEPTH - 1:0] data_in, - - output reg out_en, - output reg [3 * COLOR_DEPTH - 1:0] data_out -); - localparam READ_DATA = 0; - localparam HANDLE_DATA = 1; - localparam SEND_DATA = 2; - - reg [1:0] state, nextState; - reg [31:0] cnt_x, cnt_y; - reg [3 * COLOR_DEPTH - 1:0] data; - - // 状态切换 - always @(posedge clk or posedge reset) begin - if (reset) - state <= READ_DATA; - else - state <= nextState; - end - - // 下一状态更新 - always @(*) begin - case (state) - READ_DATA: nextState = (in_que && in_en) ? HANDLE_DATA : READ_DATA; - HANDLE_DATA: nextState = SEND_DATA; - SEND_DATA: nextState = READ_DATA; - endcase - end - - always @(posedge clk or posedge reset) begin - if (reset) begin - cnt_x <= 0; - cnt_y <= 0; - data <= 0; - end - else begin - case (state) - READ_DATA: begin - in_que <= 1; - - if (in_en) begin - data <= data_in; - in_que <= 0; - end - end - - HANDLE_DATA: begin - if (OFFSET_Y <= cnt_y && cnt_y <= (OFFSET_Y + OUT_HEIGHT - 1)) begin - if (OFFSET_X <= cnt_x && cnt_x <= (OFFSET_X + OUT_WIDTH)) begin - out_en <= 1; - end - end - - if (cnt_x >= IN_WIDTH - 1) begin - cnt_x <= 0; - cnt_y <= cnt_y + 1; - end - else begin - cnt_x <= cnt_x + 1; - end - - if (cnt_y >= IN_HEIGHT - 1) begin - cnt_y <= 0; - end - end - - SEND_DATA: begin - data_out <= data; - out_en <= 0; - end - - endcase - end - end - -endmodule diff --git a/Demosaic/demosaic2.v b/Demosaic/Demosaic2.v similarity index 51% rename from Demosaic/demosaic2.v rename to Demosaic/Demosaic2.v index 2df8e6c..a91da53 100644 --- a/Demosaic/demosaic2.v +++ b/Demosaic/Demosaic2.v @@ -1,23 +1,23 @@ -module demosaic2 #( - parameter reg [16:0] IM_WIDTH = 512, // 图像宽度 - parameter reg [16:0] IM_HEIGHT = 256, // 图像高度 - parameter reg [1:0] RAW_TYPE = 3, // 0:grbg 1:rggb 2:bggr 3:gbrg - parameter reg [5:0] DATA_SIZE = 16 +module Demosaic2 #( + parameter reg [15:0] IM_WIDTH = 512, // 图像宽度 + parameter reg [15:0] IM_HEIGHT = 256, // 图像高度 + parameter reg [ 1:0] RAW_TYPE = 3, // 0:grbg 1:rggb 2:bggr 3:gbrg + parameter reg [ 4:0] DATA_SIZE = 16 ) ( // 基本信号 - input clk, - input reset, + input wire clk, + input wire reset, // 数据输入信号 - input in_en, - input [DATA_SIZE - 1:0] in_data [2], // 数据输入线,0、1、2分别表示第一、二、三行 - output out_ready, // 数据请求线,高电平:请求三个数据,直到读取完才拉低 - output out_receive, + input wire in_en, + input wire [DATA_SIZE - 1:0] in_data [3], // 数据输入线,0、1、2分别表示第一、二、三行 + output wire out_ready, // 数据请求线,高电平:请求三个数据,直到读取完才拉低 + output wire out_receive, // en: 输出数据有效信号,高电平有效 - input in_ready, - input in_receive, - output out_en, + input wire in_ready, + input wire in_receive, + output reg out_en, output reg [DATA_SIZE - 1:0] out_r, output reg [DATA_SIZE - 1:0] out_g, output reg [DATA_SIZE - 1:0] out_b @@ -26,15 +26,15 @@ module demosaic2 #( // 常量,包括状态机 // localparam IM_SIZE = IM_HEIGHT * IM_WIDTH; - localparam READ_DATA = 0; - localparam COLOR_GEN = 1; - localparam SEND_DATA = 2; - localparam SLIDE_WINDOW = 3; + localparam reg [2:0] READ_DATA = 0; + localparam reg [2:0] COLOR_GEN = 1; + localparam reg [2:0] SEND_DATA = 2; + localparam reg [2:0] SLIDE_WINDOW = 3; // 寄存器 reg [2:0] state, nextState; - reg [15:0] data_cache[2][2]; // 缓存颜色数据,行列3x3 - reg [11:0] pos_x, pos_y; // 滑动窗口左上角位置 + reg [15:0] data_cache[9]; // 缓存颜色数据,行列3x3 + reg [15:0] pos_x, pos_y; // 滑动窗口左上角位置 reg [2:0] cnt_data; // 记录输入数据数量,最大值256 reg [1:0] raw_type; reg [15:0] red, blue, green; @@ -47,23 +47,21 @@ module demosaic2 #( end // 下一状态更新 - always @(state or cnt_data) begin + always @(*) begin case (state) // 记录够3x3个数据后,进行rgb转换 - READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA; - COLOR_GEN: nextState = SEND_DATA; - SEND_DATA: nextState = (in_receive) ? SLIDE_WINDOW : SEND_DATA; + READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA; + COLOR_GEN: nextState = SEND_DATA; + SEND_DATA: nextState = (in_receive) ? SLIDE_WINDOW : SEND_DATA; SLIDE_WINDOW: nextState = READ_DATA; - default: nextState = 0; + default: nextState = READ_DATA; endcase end // 请求数据 - assign out_ready = (cnt_data <= 2 && !in_en && state == READ_DATA) ? 1 : 0; + assign out_ready = (cnt_data <= 2 && !in_en && state == READ_DATA) ? 1 : 0; // 收到数据 assign out_receive = (in_en && state == READ_DATA) ? 1 : 0; - // 发送数据有效位 - assign out_en = (in_ready && state == SEND_DATA) ? 1 : 0; // 各状态执行的操作 always @(posedge clk or posedge reset) begin @@ -85,9 +83,9 @@ module demosaic2 #( // 读取数据 READ_DATA: begin if (in_en) begin - data_cache[cnt_data][0] <= in_data[0]; - data_cache[cnt_data][1] <= in_data[1]; - data_cache[cnt_data][2] <= in_data[2]; + data_cache[0 + cnt_data * 3] <= in_data[0]; + data_cache[1 + cnt_data * 3] <= in_data[1]; + data_cache[2 + cnt_data * 3] <= in_data[2]; cnt_data <= cnt_data + 1; end @@ -96,33 +94,33 @@ module demosaic2 #( COLOR_GEN: begin // 生成rgb图像 // data case 0 case 1 case 2 case 3 - // 0 1 2 G R G R G R B G B G B G - // 3 4 5 B G B G B G G R G R G R - // 6 7 8 G R G R G R B G B G B G + // 0 3 6 G R G R G R B G B G B G + // 1 4 7 B G B G B G G R G R G R + // 2 5 8 G R G R G R B G B G B G case (raw_type) 0: begin // Missing B, R on G - blue <= (data_cache[0][1] + data_cache[2][1]) / 2; - red <= (data_cache[1][0] + data_cache[1][2]) / 2; - green <= data_cache[1][1]; + blue <= (data_cache[1] + data_cache[7]) / 2; + red <= (data_cache[3] + data_cache[5]) / 2; + green <= data_cache[4]; end 1: begin // Missing G, R on B - green <= (data_cache[0][1] + data_cache[1][0] + data_cache[1][2] + data_cache[2][1]) / 4; - red <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4; - blue <= data_cache[1][1]; + green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) / 4; + red <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) / 4; + blue <= data_cache[4]; end 2: begin // Missing G, B on R - green <= (data_cache[0][1] + data_cache[1][0] + data_cache[1][2] + data_cache[2][1]) / 4; - blue <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4; - red <= data_cache[1][1]; + green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) / 4; + blue <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) / 4; + red <= data_cache[4]; end 3: begin // Missing B, R on G - red <= (data_cache[0][1] + data_cache[2][1]) / 2; - blue <= (data_cache[1][0] + data_cache[1][2]) / 2; - green <= data_cache[1][1]; + red <= (data_cache[1] + data_cache[7]) / 2; + blue <= (data_cache[3] + data_cache[5]) / 2; + green <= data_cache[4]; end default: ; endcase @@ -136,11 +134,12 @@ module demosaic2 #( end SEND_DATA: begin - if (in_ready) begin - out_r <= red; - out_b <= blue; - out_g <= green; - end + if (in_ready && !in_receive) begin + out_en <= 1; + out_r <= red; + out_b <= blue; + out_g <= green; + end else out_en <= 0; end SLIDE_WINDOW: begin @@ -169,12 +168,12 @@ module demosaic2 #( cnt_data <= 2; // 窗口右移 - data_cache[0][0] <= data_cache[1][0]; - data_cache[0][1] <= data_cache[1][1]; - data_cache[0][2] <= data_cache[1][2]; - data_cache[1][0] <= data_cache[2][0]; - data_cache[1][1] <= data_cache[2][1]; - data_cache[1][2] <= data_cache[2][2]; + data_cache[0] <= data_cache[3]; + data_cache[1] <= data_cache[4]; + data_cache[2] <= data_cache[5]; + data_cache[3] <= data_cache[6]; + data_cache[4] <= data_cache[7]; + data_cache[5] <= data_cache[8]; end end diff --git a/isp.v b/isp.v index 49ea182..947ac92 100644 --- a/isp.v +++ b/isp.v @@ -1,58 +1,63 @@ `timescale 1ns / 1ps module isp #( - parameter IN_WIDTH = 1936, - parameter IN_HEIGHT = 1088, - parameter OUT_WIDTH = 1920, - parameter OUT_HEIGHT = 1080, - parameter COLOR_DEPTH = 8, - parameter RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg + parameter reg [15:0] IN_WIDTH = 1936, + parameter reg [15:0] IN_HEIGHT = 1088, + parameter reg [15:0] OUT_WIDTH = 1920, + parameter reg [15:0] OUT_HEIGHT = 1080, + parameter reg [ 4:0] COLOR_DEPTH = 8, + parameter reg [ 1:0] RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg ) ( // 基本信号 input wire clk, input wire reset, // 数据输入信号 - input wire data_en, - input reg [15:0] data_in[2:0], // 数据输入线,0、1、2分别表示第一、二、三行 - output reg data_que, // 数据请求线,高电平:请求三个数据,直到读取完才拉低 + input wire in_en, + input wire [15:0] in_data[3], // 数据输入线,0、1、2分别表示第一、二、三行 + output wire out_ready, // 数据请求线,高电平:请求三个数据,直到读取完才拉低 + output wire out_receive, output wire out_clk, output wire out_en, - output reg [3 * COLOR_DEPTH - 1:0] data_out, + output wire [3 * COLOR_DEPTH - 1:0] out_data, + input wire in_ready, + input wire in_receive, + // 是否启动颜色矫正 + input wire [15:0] gain_red, + input wire [15:0] gain_green, + input wire [15:0] gain_blue, input wire color_correction ); - localparam BAYER_WIDTH = IN_WIDTH - 2; - localparam BAYER_HEIGHT = IN_HEIGHT - 2; + localparam reg [15:0] BAYER_WIDTH = IN_WIDTH - 2; + localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 2; // 三通道合成RGB图像 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 [3 * COLOR_DEPTH - 1:0] crop_data; + wire crop_en, crop_ready, crop_receive; // scaler 请求数据 + reg [3 * COLOR_DEPTH - 1:0] crop_data; // 写入RAM // wire RAM_in_en; // wire RAM_in_que; // RAM 请求数据 // wire [3 * COLOR_DEPTH - 1:0] RAM_in_data; - always @(clk) out_clk <= clk; + assign out_clk = clk; - demosaic2 #( + Demosaic2 #( .IM_WIDTH (IN_WIDTH), .IM_HEIGHT(IN_HEIGHT), .RAW_TYPE (RAW_TYPE) ) CFA ( .clk(clk), .reset(reset), - - .in_en(data_en), - .in_data(data_in), - .out_ready(data_que), - .out_en(blender_en), - .out_receive(), + .in_en(in_en), + .in_data(in_data), + .out_ready(out_ready), + .out_receive(out_receive), .out_en(blender_en), .in_ready(blender_ready), @@ -64,13 +69,9 @@ module isp #( ColorBlender #( .IN_DEPTH (12), - .OUT_DEPTH(8), - - .GAIN_RED(120), - .GAIN_GREEN(50), - .GAIN_BLUE(95), + .OUT_DEPTH(8) ) blender ( - .clk(clk), + .clk (clk), .reset(reset), .in_en(blender_en), @@ -79,14 +80,17 @@ module isp #( .out_receive(blender_receive), .in_ready(crop_ready), - .in_receive(crop_receive) + .in_receive(crop_receive), .out_en(crop_en), - .data_out(crop_data), + .out_data(crop_data), + .gain_red(gain_red), + .gain_green(gain_green), + .gain_blue(gain_blue), .color_correction(color_correction) ); - crop #( + Crop #( .IN_WIDTH(BAYER_WIDTH), .IN_HEIGHT(BAYER_HEIGHT), .OUT_WIDTH(OUT_WIDTH), @@ -96,15 +100,15 @@ module isp #( .clk (clk), .reset(reset), - .in_en (crop_en), - .out_ready (crop_ready), - .out_receive(crop_receive) + .in_en(crop_en), + .out_ready(crop_ready), + .out_receive(crop_receive), .in_data(crop_data), - .out_en (out_en), - .in_ready(), - .in_receive(), - .out_data(data_out) + .out_en(out_en), + .in_ready(in_ready), + .in_receive(in_receive), + .out_data(out_data) ); // RGB_to_RAM write_to_RAM ( @@ -113,11 +117,11 @@ module isp #( // .in_en(RAM_in_en), // .in_que(RAM_in_que), - // .data_in(RAM_in_data), + // .in_data(RAM_in_data), // .write_que(out_que), // .write_en(out_en), - // .data_write(data_out) + // .data_write(out_data) // ); endmodule diff --git a/sim/Makefile b/sim/Makefile index 5fd29a8..f578806 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -37,7 +37,7 @@ VERILATOR_FLAGS += -sc --exe # Generate makefile dependencies (not shown as complicates the Makefile) #VERILATOR_FLAGS += -MMD # Optimize -# VERILATOR_FLAGS += -x-assign fast +VERILATOR_FLAGS += -x-assign fast # Warn abount lint issues; may not want this on less solid designs VERILATOR_FLAGS += -Wall # Make waveforms @@ -45,7 +45,7 @@ VERILATOR_FLAGS += --trace # Check SystemVerilog assertions VERILATOR_FLAGS += --assert # Enable multithreading -# VERILATOR_FLAGS += --threads 4 +VERILATOR_FLAGS += --threads 14 # Generate coverage analysis # VERILATOR_FLAGS += --coverage # Run Verilator in debug mode @@ -56,7 +56,7 @@ VERILATOR_FLAGS += --assert TOP_MODULE = isp VERILATOR_FLAGS += -top $(TOP_MODULE) # Input files for Verilator -VERILATOR_INPUT = ../isp.v *.cpp ../Demosaic/demosaic2.v ../Crop/*.v ../FIFO/*.v ../Merge/*.v ../RAM/*.v +VERILATOR_INPUT = ../isp.v *.cpp ../Demosaic/Demosaic2.v ../Crop/*.v ../ColorBlender/*.v ../RAM/*.v # Check if SC exists via a verilator call (empty if not) SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) @@ -64,15 +64,16 @@ SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) ###################################################################### ifneq ($(SYSTEMC_EXISTS),) -default: run +default: build run else default: nosc endif -run: - @echo - @echo "-- Verilator tracing example" +lint: + @echo "-- Verilator lint check ----" + $(VERILATOR) -sc --lint-only $(VERILATOR_INPUT) +build: @echo @echo "-- VERILATE ----------------" $(VERILATOR) $(VERILATOR_FLAGS) $(VERILATOR_INPUT) @@ -86,17 +87,21 @@ run: # 3. Or, call a submakefile where we can override the rules ourselves: $(MAKE) -j -C obj_dir -f V$(TOP_MODULE).mk +run: @echo @echo "-- RUN ---------------------" - # @rm -rf logs - # @mkdir -p logs - # obj_dir/V$(TOP_MODULE) +trace obj_dir/V$(TOP_MODULE) - # @echo - # @echo "-- COVERAGE ----------------" - # @rm -rf logs/annotated - # $(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat +# @echo +# @echo "-- COVERAGE ----------------" +# @rm -rf logs/annotated +# $(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat + @echo "-- FINISH ------------------" + +trace: + @rm -rf logs + @mkdir -p logs + obj_dir/V$(TOP_MODULE) +trace @echo @echo "-- DONE --------------------" diff --git a/sim/sc_main.cpp b/sim/sc_main.cpp index d647af1..4c881fe 100644 --- a/sim/sc_main.cpp +++ b/sim/sc_main.cpp @@ -5,51 +5,61 @@ #include // Include common routines +#include // mkdir #include #include -#include // mkdir - // Include model header, generated from Verilating "isp.v" #include "Visp.h" // Handle file #include #include + +// math +#include + #include "bmp.hpp" -#define IN_WIDTH 1936 -#define IN_HEIGHT 1088 +static const uint16_t IN_WIDTH = 1936; +static const uint16_t IN_HEIGHT = 1088; #define IN_SIZE (IN_WIDTH * IN_HEIGHT) -#define OUT_WIDTH 1920 -#define OUT_HEIGHT 1080 +static const uint16_t OUT_WIDTH = 1920; +static const uint16_t OUT_HEIGHT = 1080; #define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT) -// const float red_gain = 1.2f; // Adjust these values as necessary -// const float green_gain = 0.5f; -// const float blue_gain = 0.95f; +struct color_gain +{ + double red; + double green; + double blue; +}color_gain {1.0, 0.5, 1.1}; + using namespace std; using namespace sc_core; using namespace sc_dt; -SC_MODULE (TB_ISP) { +SC_MODULE(TB_ISP) { sc_in_clk clk; sc_in reset; - - sc_in data_que; - sc_out data_en; - sc_out data_out[3]; + + sc_in in_ready; + sc_in in_receive; + sc_out out_en; + sc_out out_data[3]; sc_in im_clk; sc_in im_en; + sc_out out_ready; + sc_out out_receceive; sc_in im_data; sc_out is_done; unique_ptr image = make_unique(IN_SIZE); unique_ptr out = make_unique(OUT_SIZE); - SC_CTOR (TB_ISP) { + SC_CTOR(TB_ISP) { SC_CTHREAD(send_Data, clk.pos()); reset_signal_is(reset, true); @@ -58,56 +68,63 @@ SC_MODULE (TB_ISP) { void send_Data(void) { uint16_t pos_x = 0, pos_y = 0; - while (true) - { - if (data_que.read() && pos_y < IN_HEIGHT - 2) { - data_en.write(1); + while (true) { + if (in_ready.read() && pos_y < IN_HEIGHT - 2) { + out_en.write(1); - printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, image[( pos_y + 0 ) * IN_WIDTH + pos_x]); - printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, image[( pos_y + 1 ) * IN_WIDTH + pos_x]); - printf("x=%4d, y=%4d, data=0x%04x\n", pos_x, pos_y, image[( pos_y + 2 ) * IN_WIDTH + pos_x]); + printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, + image[(pos_y + 0) * IN_WIDTH + pos_x]); + printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, + image[(pos_y + 1) * IN_WIDTH + pos_x]); + printf("x=%4d, y=%4d, data=0x%04x\n", pos_x, pos_y, + image[(pos_y + 2) * IN_WIDTH + pos_x]); - data_out[0].write(image[( pos_y + 0 ) * IN_WIDTH + pos_x]); - data_out[1].write(image[( pos_y + 1 ) * IN_WIDTH + pos_x]); - data_out[2].write(image[( pos_y + 2 ) * IN_WIDTH + pos_x]); + out_data[0].write(image[(pos_y + 0) * IN_WIDTH + pos_x]); + 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); - data_en.write(0); + // wait(1); + // out_en.write(0); if (++pos_x >= IN_WIDTH) { pos_x = 0; pos_y++; } } else { - data_en.write(0); + out_en.write(0); } wait(); } - } void read_Data(void) { is_done.write(0); uint16_t pos_x = 0, pos_y = 0; uint32_t last_data = 0; - uint16_t cnt = 0; - while (true) - { + uint32_t cnt = 0; + while (true) { if (im_en.read()) { + out_ready.write(false); + out_receceive.write(true); + out[pos_y * OUT_WIDTH + pos_x] = im_data.read(); if (pos_x++ >= OUT_WIDTH) { pos_x = 0; pos_y++; } + } else { + out_ready.write(true); + out_receceive.write(false); } + // when data didn't change some time, it end if (last_data == im_data.read()) { cnt++; - if (cnt >= 10000) { + if (cnt >= 100000L) { is_done.write(1); - printf("x=%d, y=%d\n",pos_x, pos_y); + printf("x=%d, y=%d\n", pos_x, pos_y); } } else { cnt = 0; @@ -142,13 +159,15 @@ int sc_main(int argc, char* argv[]) { uint32_t i = 0; for (int y = 0; y < IN_HEIGHT; y++) { for (int x = 0; x < IN_WIDTH; x++) { - image[y * IN_WIDTH + x] = (uint16_t)buf[i] + ((uint16_t)buf[i + 1] << 8); + image[y * IN_WIDTH + x] = + (uint16_t)buf[i] + ((uint16_t)buf[i + 1] << 8); i += 2; } } cout << "Finish Reading data" << endl; - // This is a more complicated example, please also see the simpler examples/make_hello_c. + // This is a more complicated example, please also see the simpler + // examples/make_hello_c. // Create logs/ directory in case we have traces to put under it Verilated::mkdir("logs"); @@ -161,7 +180,8 @@ int sc_main(int argc, char* argv[]) { // May be overridden by commandArgs argument parsing Verilated::randReset(2); - // Before any evaluation, need to know to calculate those signals only used for tracing + // Before any evaluation, need to know to calculate those signals only used + // for tracing Verilated::traceEverOn(true); // Pass arguments so Verilated code can see them, e.g. $value$plusargs @@ -176,49 +196,68 @@ int sc_main(int argc, char* argv[]) { // Define interconnect sc_signal reset; - sc_signal data_en; - sc_signal data_que; - sc_signal data_in[3]; + sc_signal in_en; + sc_signal in_ready; + sc_signal in_receive; + sc_signal in_data[3]; sc_signal out_clk; sc_signal out_en; - sc_signal data_out; + sc_signal out_ready; + sc_signal out_receive; + sc_signal out_data; sc_signal color_correction; + sc_signal gain_red; + sc_signal gain_green; + sc_signal gain_blue; sc_signal flag_done; - // Construct the Verilated model, from inside Visp.h - // Using unique_ptr is similar to "Visp* isp = new Visp" then deleting at end + // Using unique_ptr is similar to "Visp* isp = new Visp" then deleting at + // end const std::unique_ptr isp{new Visp{"isp"}}; // Attach Visp's signals to this upper model isp->clk(clk); isp->reset(reset); - isp->data_en(data_en); - isp->data_que(data_que); - isp->data_in[0](data_in[0]); - isp->data_in[1](data_in[1]); - isp->data_in[2](data_in[2]); + isp->in_en(in_en); + isp->in_ready(in_ready); + isp->in_receive(in_receive); + isp->in_data[0](in_data[0]); + isp->in_data[1](in_data[1]); + isp->in_data[2](in_data[2]); isp->out_clk(out_clk); isp->out_en(out_en); - isp->data_out(data_out); + isp->out_ready(out_ready); + isp->out_receive(out_receive); + isp->out_data(out_data); + + isp->gain_red(gain_red); + isp->gain_green(gain_green); + isp->gain_blue(gain_blue); isp->color_correction(color_correction); - color_correction.write(false); // enable color correction + 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))); // Construct testbench module TB_ISP tb_isp("tb_isp"); tb_isp.clk(clk); tb_isp.reset(reset); - tb_isp.data_que(data_que); - tb_isp.data_en(data_en); - tb_isp.data_out[0](data_in[0]); - tb_isp.data_out[1](data_in[1]); - tb_isp.data_out[2](data_in[2]); + tb_isp.in_ready(out_ready); + tb_isp.in_receive(out_receive); + tb_isp.out_en(in_en); + tb_isp.out_ready(in_ready); + tb_isp.out_receceive(in_receive); + tb_isp.out_data[0](in_data[0]); + tb_isp.out_data[1](in_data[1]); + tb_isp.out_data[2](in_data[2]); tb_isp.im_clk(out_clk); tb_isp.im_en(out_en); - tb_isp.im_data(data_out); + tb_isp.im_data(out_data); tb_isp.is_done(flag_done); tb_isp.image = move(image); @@ -251,8 +290,7 @@ int sc_main(int argc, char* argv[]) { reset.write(0); // Deassert reset } - if (flag_done.read()) - break; + if (flag_done.read()) break; // Simulate 1ns sc_start(1, SC_NS); @@ -271,30 +309,31 @@ int sc_main(int argc, char* argv[]) { cout << "Ready to save raw RGB image" << endl; // for (int y = 0; y < OUT_HEIGHT; y++) // for(int x = 0; x < OUT_WIDTH; x++) - // out_image.write((const char *)&tb_isp.out[y * OUT_WIDTH + x], sizeof(tb_isp.out[0])); + // out_image.write((const char *)&tb_isp.out[y * OUT_WIDTH + x], + // sizeof(tb_isp.out[0])); // out_image.close(); - - // save to image - uint8_t* data = new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 + uint8_t* data = + new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 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 ); + 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); - out_image.write((const char *)&red, sizeof(red)); - out_image.write((const char *)&green, sizeof(green)); - out_image.write((const char *)&blue, sizeof(blue)); + 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); + printf("x=%4d, y=%4d, red=0x%02x, green=0x%02x, blue=0x%02x\n", x, + y, red, green, blue); - data[index + 0] = red; // R - data[index + 1] = green; // G - data[index + 2] = blue; // B + data[index + 0] = red; // R + data[index + 1] = green; // G + data[index + 2] = blue; // B } }