diff --git a/.justfile b/.justfile index 9397c4d..7bd57bb 100644 --- a/.justfile +++ b/.justfile @@ -1,3 +1,4 @@ +alias a := all alias c := clean-build alias b := build alias r := run @@ -13,6 +14,10 @@ clean-all: clean-build: rm -rf ./build/* +# clean images +clean-img: + rm -rf ./logs/*.bmp + # build and run default target all: build run diff --git a/CMakeLists.txt b/CMakeLists.txt index e3d715d..b1a2fc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,7 @@ target_include_directories( # Add the Verilated circuit to the target verilate(Visp_Pipeline SYSTEMC COVERAGE TRACE INCLUDE_DIRS ${RTL_SUBDIR} - VERILATOR_ARGS +librescan +libext+.v+.sv+.vh+.svh -y . -x-assign fast -Wno-WIDTHEXPAND + VERILATOR_ARGS +librescan +libext+.v+.sv+.vh+.svh -y . -x-assign fast -Wno-WIDTHEXPAND -Wno-WIDTHTRUNC SOURCES ${PROJECT_SOURCE_DIR}/rtl/isp_Pipeline.sv TOP_MODULE isp_Pipeline ) diff --git a/FPGA.nix b/FPGA.nix index d36b8e4..c7f7180 100644 --- a/FPGA.nix +++ b/FPGA.nix @@ -21,7 +21,7 @@ # languages.cplusplus.enable = true; languages.python = { enable = true; - version = "3.11"; + version = "3.11.8"; venv.enable = true; venv.requirements = '' teroshdl diff --git a/rtl/BayerProcess/DPC.sv b/rtl/BayerProcess/DPC.sv new file mode 100644 index 0000000..f84d602 --- /dev/null +++ b/rtl/BayerProcess/DPC.sv @@ -0,0 +1,298 @@ +`timescale 1ns / 1ps + +module DPC #( + parameter reg [15:0] TOTAL_WIDTH = 512 + 3, // 总图像宽度 + parameter reg [15:0] TOTAL_HEIGHT = 256 + 3, // 总图像高度 + parameter reg [ 1:0] RAW_TYPE = 3, // (0,0)位置算起RAW_TYPE的值 + parameter reg [ 4:0] DATA_WIDTH = 16 // 输入/输出数据位宽 +) ( + input wire clk, + input wire reset, + + input wire [DATA_WIDTH - 1:0] in_data [5*5], + output reg [DATA_WIDTH - 1:0] out_data, + + input wire in_valid, + output wire out_valid, + + input wire in_ready, + output wire out_ready +); + + localparam WINDOW_LENGTH = 5; + localparam DATA_NUM = WINDOW_LENGTH * WINDOW_LENGTH; + localparam EXPAND_BITS = 5; + localparam PIPILINE = 9; + + reg [PIPILINE-1:0] pipeline_valid; + wire pipeline_running; + assign pipeline_running = in_ready | ~pipeline_valid[PIPILINE-1]; + + //out_ready :只要本模块可以接收数据就一直拉高 + assign out_ready = pipeline_running; + //out_valid :只要本模块可以发出数据就一直拉高 + assign out_valid = pipeline_valid[PIPILINE-1]; + + reg [DATA_WIDTH-1:0] data_cache[DATA_NUM]; // 缓存颜色数据,行列nxn + reg [DATA_WIDTH-1:0] data_cache0[DATA_NUM]; // 缓存颜色数据,行列nxn + reg [DATA_WIDTH-1:0] channel_cache[9]; // 缓存颜色通道数据,channel_cache[4]就是中心像素点 + reg [DATA_WIDTH-1:0] + channel_cache0, + channel_cache1, + channel_cache2, + channel_cache3, + channel_cache4; // 缓存中心像素点的颜色数据 + reg signed [DATA_WIDTH-1+EXPAND_BITS:0] + grad_h_cache[3], grad_v_cache[3], grad_45_cache[3], grad_135_cache[3]; + reg [DATA_WIDTH-1+EXPAND_BITS:0] + grad_h_cache0[3], grad_v_cache0[3], grad_45_cache0[3], grad_135_cache0[3]; + reg [DATA_WIDTH-1+EXPAND_BITS:0] + grad_h_cache1[3], grad_v_cache1[3], grad_45_cache1[3], grad_135_cache1[3]; + reg [DATA_WIDTH-1+EXPAND_BITS:0] + grad_h_cache2[3], grad_v_cache2[3], grad_45_cache2[3], grad_135_cache2[3]; + reg [DATA_WIDTH-1+EXPAND_BITS:0] grad_median_cache[4]; + reg [1:0] flag_which_dict; + reg [DATA_WIDTH-1:0] + channel_cache_correct[4], + channel_cache_correct0[4], + channel_cache_correct1[4], + channel_cache_correct2[4]; + reg [DATA_WIDTH-1:0] channel_cache_correct_final; + reg flag_if_need_corection; + reg [15:0] pos_x; + reg pos_y_bit; + reg [1:0] raw_type; + + integer i; + always @(posedge clk) begin + if (reset) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache[i] <= 0; + for (i = 0; i < DATA_NUM; i = i + 1) data_cache0[i] <= 0; + for (i = 0; i < 9; i = i + 1) channel_cache[i] <= 0; + channel_cache0 <= 0; + channel_cache1 <= 0; + channel_cache2 <= 0; + channel_cache3 <= 0; + channel_cache4 <= 0; + channel_cache_correct_final <= 0; + for (i = 0; i < 3; i = i + 1) grad_h_cache[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_h_cache1[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_h_cache2[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_v_cache[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_v_cache1[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_v_cache2[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_45_cache[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_45_cache1[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_45_cache2[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_135_cache[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_135_cache1[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_135_cache2[i] <= 0; + for (i = 0; i < 3; i = i + 1) grad_median_cache[i] <= 0; + flag_which_dict <= 0; + flag_if_need_corection <= 0; + for (i = 0; i < 4; i = i + 1) channel_cache_correct[i] <= 0; + for (i = 0; i < 4; i = i + 1) channel_cache_correct1[i] <= 0; + for (i = 0; i < 4; i = i + 1) channel_cache_correct0[i] <= 0; + for (i = 0; i < 4; i = i + 1) channel_cache_correct2[i] <= 0; + + pipeline_valid <= 0; + out_data <= 0; + pos_x <= ~0; + pos_y_bit <= ~0; + raw_type <= RAW_TYPE; + end else if (pipeline_running) begin + + pipeline_valid <= {pipeline_valid[PIPILINE-2:0], in_valid}; + + if (in_valid) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache0[i] <= in_data[i]; + pos_x <= (pos_x >= TOTAL_WIDTH - 1) ? (0) : (pos_x + 1); + pos_y_bit <= (pos_x >= TOTAL_WIDTH - 1) ? (~pos_y_bit) : (pos_y_bit); + end + + if (pipeline_valid[0]) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache[i] <= data_cache0[i]; + case (RAW_TYPE) + 2'b00: raw_type <= {pos_y_bit, pos_x[0]}; + 2'b01: raw_type <= {pos_y_bit, ~pos_x[0]}; + 2'b10: raw_type <= {~pos_y_bit, pos_x[0]}; + 2'b11: raw_type <= {~pos_y_bit, ~pos_x[0]}; + endcase + end + + if (pipeline_valid[1]) begin + case (raw_type) + 1, 2: begin + channel_cache[0] <= data_cache[00]; + channel_cache[1] <= data_cache[10]; + channel_cache[2] <= data_cache[20]; + channel_cache[3] <= data_cache[02]; + channel_cache[4] <= data_cache[12]; + channel_cache[5] <= data_cache[22]; + channel_cache[6] <= data_cache[04]; + channel_cache[7] <= data_cache[14]; + channel_cache[8] <= data_cache[24]; + end + 0, 3: begin + channel_cache[0] <= data_cache[02]; + channel_cache[1] <= data_cache[06]; + channel_cache[2] <= data_cache[10]; + channel_cache[3] <= data_cache[08]; + channel_cache[4] <= data_cache[12]; + channel_cache[5] <= data_cache[16]; + channel_cache[6] <= data_cache[14]; + channel_cache[7] <= data_cache[18]; + channel_cache[8] <= data_cache[22]; + end + endcase + end + + if (pipeline_valid[2]) begin //计算梯度,同时开始校正后数据的部分计算 + channel_cache0 <= channel_cache[4]; + + grad_h_cache[0] <= channel_cache[0] + channel_cache[2] - 2 * channel_cache[1]; + grad_h_cache[1] <= channel_cache[3] + channel_cache[5] - 2 * channel_cache[4]; + grad_h_cache[2] <= channel_cache[6] + channel_cache[8] - 2 * channel_cache[7]; + grad_v_cache[0] <= channel_cache[0] + channel_cache[6] - 2 * channel_cache[3]; + grad_v_cache[1] <= channel_cache[1] + channel_cache[7] - 2 * channel_cache[4]; + grad_v_cache[2] <= channel_cache[2] + channel_cache[8] - 2 * channel_cache[5]; + grad_45_cache[0] <= 2 * (channel_cache[1] - channel_cache[3]); + grad_45_cache[1] <= channel_cache[6] + channel_cache[2] - 2 * channel_cache[4]; + grad_45_cache[2] <= 2 * (channel_cache[7] - channel_cache[5]); + grad_135_cache[0] <= 2 * (channel_cache[1] - channel_cache[5]); + grad_135_cache[1] <= channel_cache[0] + channel_cache[8] - 2 * channel_cache[4]; + grad_135_cache[2] <= 2 * (channel_cache[3] - channel_cache[7]); + + channel_cache_correct[0] <= channel_cache[3] / 2 + channel_cache[5] / 2; + channel_cache_correct[1] <= channel_cache[1] / 2 + channel_cache[7] / 2; + channel_cache_correct[2] <= channel_cache[2] / 2 + channel_cache[6] / 2; + channel_cache_correct[3] <= channel_cache[0] / 2 + channel_cache[8] / 2; + end + + if(pipeline_valid[3]) begin //计算绝对值,同时完成校正后数据的计算,注意grad_h_cache等是singed,可能为负数 + channel_cache1 <= channel_cache0; + + grad_h_cache0 [0] <= grad_h_cache [0][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_h_cache [0] + 1) : (grad_h_cache [0]); + grad_h_cache0 [1] <= grad_h_cache [1][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_h_cache [1] + 1) : (grad_h_cache [1]); + grad_h_cache0 [2] <= grad_h_cache [2][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_h_cache [2] + 1) : (grad_h_cache [2]); + grad_v_cache0 [0] <= grad_v_cache [0][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_v_cache [0] + 1) : (grad_v_cache [0]); + grad_v_cache0 [1] <= grad_v_cache [1][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_v_cache [1] + 1) : (grad_v_cache [1]); + grad_v_cache0 [2] <= grad_v_cache [2][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_v_cache [2] + 1) : (grad_v_cache [2]); + grad_45_cache0 [0] <= grad_45_cache [0][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_45_cache [0] + 1) : (grad_45_cache [0]); + grad_45_cache0 [1] <= grad_45_cache [1][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_45_cache [1] + 1) : (grad_45_cache [1]); + grad_45_cache0 [2] <= grad_45_cache [2][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_45_cache [2] + 1) : (grad_45_cache [2]); + grad_135_cache0[0] <= grad_135_cache[0][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_135_cache[0] + 1) : (grad_135_cache[0]); + grad_135_cache0[1] <= grad_135_cache[1][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_135_cache[1] + 1) : (grad_135_cache[1]); + grad_135_cache0[2] <= grad_135_cache[2][DATA_WIDTH-1+EXPAND_BITS] ? (~grad_135_cache[2] + 1) : (grad_135_cache[2]); + channel_cache_correct0[0] <= channel_cache_correct[0] + grad_h_cache[0]/4 + grad_h_cache[2]/4; + channel_cache_correct0[1] <= channel_cache_correct[1] + grad_v_cache[0]/4 + grad_v_cache[2]/4; + channel_cache_correct0[2] <= channel_cache_correct[2] + grad_45_cache[0]/4 + grad_45_cache[2]/4; + channel_cache_correct0[3] <= channel_cache_correct[3] + grad_135_cache[0]/4 + grad_135_cache[2]/4; + end + + if (pipeline_valid[4]) begin //计算中位数 + channel_cache2 <= channel_cache1; + for (i = 0; i < 4; i = i + 1) channel_cache_correct1[i] <= channel_cache_correct0[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_h_cache1[i] <= grad_h_cache0[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_v_cache1[i] <= grad_v_cache0[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_45_cache1[i] <= grad_45_cache0[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_135_cache1[i] <= grad_135_cache0[i]; + + grad_median_cache[0] <= MEDIAN(grad_h_cache0); + grad_median_cache[1] <= MEDIAN(grad_v_cache0); + grad_median_cache[2] <= MEDIAN(grad_45_cache0); + grad_median_cache[3] <= MEDIAN(grad_135_cache0); + end + + if (pipeline_valid[5]) begin //计算最小值,判断最小梯度方向 + channel_cache3 <= channel_cache2; + for (i = 0; i < 4; i = i + 1) channel_cache_correct2[i] <= channel_cache_correct1[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_h_cache2[i] <= grad_h_cache1[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_v_cache2[i] <= grad_v_cache1[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_45_cache2[i] <= grad_45_cache1[i]; + for (i = 0; i < 3 + EXPAND_BITS; i = i + 1) grad_135_cache2[i] <= grad_135_cache1[i]; + + flag_which_dict <= MIN(grad_median_cache); + end + + if (pipeline_valid[6]) begin //在最小梯度方向上判断中心点是否是坏点 + channel_cache4 <= channel_cache3; + channel_cache_correct_final <= channel_cache_correct2[flag_which_dict]; + case (flag_which_dict) + 2'b00: + flag_if_need_corection <= grad_h_cache2[1] > 4 * (grad_h_cache2[0] + grad_h_cache2[2]); + 2'b01: + flag_if_need_corection <= grad_v_cache2[1] > 4 * (grad_v_cache2[0] + grad_v_cache2[2]); + 2'b10: + flag_if_need_corection <= grad_45_cache2[1] > 3 * (grad_45_cache2[0] + grad_45_cache2[2]); + 2'b11: + flag_if_need_corection <= grad_135_cache2[1] > 3*(grad_135_cache2[0] + grad_135_cache2[2]); + endcase + end + + if(pipeline_valid[7]) begin //如果是坏点,输出计算后的值;如果不是坏点,输出原值 + out_data <= (flag_if_need_corection) ? (channel_cache_correct_final) : (channel_cache4); + end + end + end + + function [DATA_WIDTH-1+EXPAND_BITS:0] MEDIAN; + input [DATA_WIDTH-1+EXPAND_BITS:0] inx[3]; + begin + if ((inx[0] >= inx[1] && inx[1] >= inx[2]) || (inx[2] >= inx[1] && inx[1] >= inx[0])) + MEDIAN = inx[1]; + else if ((inx[1] >= inx[0]) || (inx[0] >= inx[1])) MEDIAN = inx[0]; + else MEDIAN = inx[2]; + end + endfunction + + function [1:0] MIN; + input [DATA_WIDTH-1+EXPAND_BITS:0] inx[4]; + begin + if (inx[0] >= inx[1] && inx[0] >= inx[2] && inx[0] >= inx[3]) MIN = 2'b00; + else if (inx[1] >= inx[0] && inx[1] >= inx[2] && inx[1] >= inx[3]) MIN = 2'b01; + else if (inx[2] >= inx[0] && inx[2] >= inx[1] && inx[2] >= inx[3]) MIN = 2'b10; + else MIN = 2'b11; + end + endfunction + + /* + 00 05 10 15 20 + 01 06 11 16 21 0 1 2 + 02 07 12 17 22 -> 3 4 5 + 03 08 13 18 23 6 7 8 + 04 09 14 19 24 + + rawtype==0: center is GREEN + g r g r g / / g / / + b g b g b / g / g / + g r g r g -> g / G / g + b g b g b / g / g / + g r g r g / / g / / + + rawtype==1: center is RED + r g r g r r / r / r + g b g b g / / / / / + r g r g r -> r / R / r + g b g b g / / / / / + r g r g r r / r / r + + rawtype==2: center is BLUE + b g b g b b / b / b + g r g r g / / / / / + b g b g b -> b / B / b + g r g r g / / / / / + b g b g b b / b / b + + rawtype==3: center is GREEN + g b g b g / / g / / + r g r g r / g / g / + g b g b g -> g / G / g + r g r g r / g / g / + r g r g r / / g / / + + + */ + +endmodule + diff --git a/rtl/Demosaic/Demosaic2.sv b/rtl/BayerProcess/Demosaic2.sv similarity index 100% rename from rtl/Demosaic/Demosaic2.sv rename to rtl/BayerProcess/Demosaic2.sv diff --git a/rtl/BayerProcess/Demosaic_Pipeline.sv b/rtl/BayerProcess/Demosaic_Pipeline.sv new file mode 100644 index 0000000..1667c48 --- /dev/null +++ b/rtl/BayerProcess/Demosaic_Pipeline.sv @@ -0,0 +1,121 @@ +`timescale 1ns / 1ps +module Demosaic_Pipeline #( + parameter WINDOW_LENGTH = 3, + parameter reg [15:0] TOTAL_WIDTH = 512 + 3, // 总图像宽度 + parameter reg [15:0] TOTAL_HEIGHT = 256 + 3, // 总图像高度 + parameter reg [ 1:0] RAW_TYPE = 3, // (0,0)位置算起RAW_TYPE的值 + parameter reg [ 4:0] DATA_WIDTH = 16 // 输入/输出数据位宽 +) ( + input wire clk, + input wire reset, + + input wire [DATA_WIDTH - 1:0] in_data [WINDOW_LENGTH*WINDOW_LENGTH], // 数据输入线.第一列数据在[0],[1],[2]中 + output reg [DATA_WIDTH - 1:0] out_data[3], // 数据输出线,3、2、1分别表示r、g、b + + input wire in_valid, + output wire out_valid, + + input wire in_ready, + output wire out_ready, + + output reg out_hsync, // 行同步,一行第一个像素点输出的同时高电平 + output reg out_fsync // 帧同步,一帧第一个像素点输出的同时高电平 +); + + localparam DATA_NUM = WINDOW_LENGTH * WINDOW_LENGTH; + localparam PIPILINE = 4; + + reg [PIPILINE-1:0] pipeline_valid; + wire pipeline_running; + assign pipeline_running = in_ready | ~pipeline_valid[PIPILINE-1]; + + //out_ready :只要本模块可以接收数据就一直拉高 + assign out_ready = pipeline_running; + //out_valid :只要本模块可以发出数据就一直拉高 + assign out_valid = pipeline_valid[PIPILINE-1]; + + reg [DATA_WIDTH-1:0] data_cache [DATA_NUM]; // 缓存颜色数据,行列nxn + reg [DATA_WIDTH-1:0] data_cache0[DATA_NUM]; // 缓存颜色数据,行列nxn + reg [31:0] pos_x, pos_y, temp_pos_x1, temp_pos_y1, temp_pos_x2, temp_pos_y2; + reg [DATA_WIDTH-1:0] red, blue, green; + reg [1:0] raw_type; + + integer i; + always @(posedge clk) begin + if (reset) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache[i] <= 0; + for (i = 0; i < DATA_NUM; i = i + 1) data_cache0[i] <= 0; + pipeline_valid <= 0; + {red, green, blue} <= 0; + {out_data[2], out_data[1], out_data[0]} <= 0; + {out_hsync, out_fsync} <= 0; + pos_x <= ~0; + pos_y <= ~0; + temp_pos_x1 <= ~0; + temp_pos_y1 <= ~0; + temp_pos_x2 <= ~0; + temp_pos_y2 <= ~0; + raw_type <= RAW_TYPE; + end else if (pipeline_running) begin + + // First level pipeline for reading data + pipeline_valid <= {pipeline_valid[PIPILINE-2:0], in_valid}; + + if (in_valid) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache0[i] <= in_data[i]; + pos_x <= (pos_x >= TOTAL_WIDTH - 1) ? (0) : (pos_x + 1); + pos_y <= (pos_x >= TOTAL_WIDTH - 1)?((pos_y >= TOTAL_HEIGHT - 1)?(0):(pos_y + 1)):(pos_y); + end + + if (pipeline_valid[0]) begin + for (i = 0; i < DATA_NUM; i = i + 1) data_cache[i] <= data_cache0[i]; + temp_pos_x1 <= pos_x; + temp_pos_y1 <= pos_y; + case (RAW_TYPE) + 2'b00: raw_type <= {pos_y[0], pos_x[0]}; + 2'b01: raw_type <= {pos_y[0], ~pos_x[0]}; + 2'b10: raw_type <= {~pos_y[0], pos_x[0]}; + 2'b11: raw_type <= {~pos_y[0], ~pos_x[0]}; + endcase + end + + if (pipeline_valid[1]) begin + temp_pos_x2 <= temp_pos_x1; + temp_pos_y2 <= temp_pos_y1; + case (raw_type) + 0: begin // Missing B, R on G + blue <= (data_cache[1] >> 1) + (data_cache[7] >> 1); + red <= (data_cache[3] >> 1) + (data_cache[5] >> 1); + green <= data_cache[4]; + end + 1: begin // Missing G, R on B + green <= (data_cache[1] >> 2) + (data_cache[3] >> 2) + (data_cache[5] >> 2) + (data_cache[7] >> 2); + red <= (data_cache[0] >> 2) + (data_cache[2] >> 2) + (data_cache[6] >> 2) + (data_cache[8] >> 2); + blue <= data_cache[4]; + end + 2: begin // Missing G, B on R + green <= (data_cache[1] >> 2) + (data_cache[3] >> 2) + (data_cache[5] >> 2) + (data_cache[7] >> 2); + blue <= (data_cache[0] >> 2) + (data_cache[2] >> 2) + (data_cache[6] >> 2) + (data_cache[8] >> 2); + red <= data_cache[4]; + end + 3: begin // Missing B, R on G + red <= (data_cache[1] >> 1) + (data_cache[7] >> 1); + blue <= (data_cache[3] >> 1) + (data_cache[5] >> 1); + green <= data_cache[4]; + end + endcase + end + + if (pipeline_valid[2]) begin + {out_data[2], out_data[1], out_data[0]} <= {red, blue, green}; + out_hsync <= (temp_pos_x2 == 0); + out_fsync <= ((temp_pos_x2 == 0) && (temp_pos_y2 == 0)); + end + end + end + + // 0:grg 1:rgr 2:bgb 3:gbg 036 窗口右移,0<->1 2<->3; 窗口下移,0<->2,1<->3。 + // bgb gbg grg rgr 147 + // grg rgr bgb gbg 258 +endmodule + diff --git a/rtl/BayerProcess/Gowin_SDPB.sv b/rtl/BayerProcess/Gowin_SDPB.sv new file mode 100644 index 0000000..090bc4b --- /dev/null +++ b/rtl/BayerProcess/Gowin_SDPB.sv @@ -0,0 +1,35 @@ +//Gowin SDPB IP�˷����ļ� +`timescale 1ns / 1ps +module Gowin_SDPB ( + input wire clka, + input wire clkb, //no use + input wire reset, + + input wire cea, + input wire ceb, + + input wire [10:0] ada, + input wire [10:0] adb, + + input wire [15:0] din, + output reg [15:0] dout, + + input wire oce //no use +); + + reg [15:0] bram[2048]; + integer i; + initial for (i = 0; i < 2048; i = i + 1) bram[i] = 0; + + always @(posedge clka) begin + if (reset) for (i = 0; i < 2048; i = i + 1) bram[i] <= 0; + else if (cea) bram[ada] <= din; + end + + always @(posedge clka) begin + if (reset) dout <= 0; + else if (ceb) dout <= bram[adb]; + end + + +endmodule diff --git a/rtl/BayerProcess/SHIFT_REGISTER.sv b/rtl/BayerProcess/SHIFT_REGISTER.sv new file mode 100644 index 0000000..b3b0851 --- /dev/null +++ b/rtl/BayerProcess/SHIFT_REGISTER.sv @@ -0,0 +1,72 @@ +//RAM-BASED移位寄存器 +`timescale 1ns / 1ps + +module SHIFT_REGISTER #( + parameter reg [4:0] DATA_WIDTH = 16, // 输入/输出数据位宽 + parameter IMAGE_WIDTH = 1936, //MAX 2048 + parameter IFOUTIMME = 1'b0 //此项为0时,直至RAM存满IMAGE_WIDTH后再输出valid,为1时立即输出valid,无论是否存满 +) ( + // 基本信号 + input wire clk, + input wire reset, + // 数据线 + input wire [DATA_WIDTH - 1:0] in_data, + output wire [DATA_WIDTH - 1:0] out_data, + // 有效信号 + input wire in_valid, // 上一模块输出数据有效 + output wire out_valid // 当前模块输出数据有效 +); + + reg [10:0] addr_a, addr_b; + wire cea, ceb; + reg fulldone; + + reg in_valid_temp0, in_valid_temp1; + always @(posedge clk) in_valid_temp0 <= in_valid && (fulldone || IFOUTIMME); + always @(posedge clk) in_valid_temp1 <= in_valid_temp0; + + assign cea = in_valid; + assign ceb = in_valid_temp0; + assign out_valid = in_valid_temp1; + + always @(posedge clk) begin + if (reset) fulldone <= 0; + else if (addr_b == IMAGE_WIDTH - 1) fulldone <= 1; + else fulldone <= fulldone; + end + + + always @(posedge clk) begin + if (reset) begin + addr_a <= IMAGE_WIDTH + 1; + addr_b <= 0; + end else if (cea) begin + addr_a <= addr_a + 1; + addr_b <= addr_b + 1; + end else begin + addr_a <= addr_a; + addr_b <= addr_b; + end + end + + // Single-Double-Port-BRAM-IP Bypass Normal + Gowin_SDPB Gowin_SDPB_inst ( + .clka (clk), //input clka + .clkb (clk), //input clkb + .reset(reset), //input reset + + .cea(cea), //input cea + .ceb(ceb), //input ceb + + .ada(addr_a), //input [10:0] ada + .adb(addr_b), //input [10:0] adb + + .din (in_data), //input [15:0] din + .dout(out_data), //output [15:0] dout + + .oce(1) //input oce + ); + +endmodule + + diff --git a/rtl/BayerProcess/Windows.sv b/rtl/BayerProcess/Windows.sv new file mode 100644 index 0000000..4b5b916 --- /dev/null +++ b/rtl/BayerProcess/Windows.sv @@ -0,0 +1,119 @@ +`timescale 1ns / 1ps +module Windows #( + parameter DATA_WIDTH = 16, + parameter IMAGE_WIDTH = 1936, + parameter IMAGE_HEIGHT = 1088, + parameter WINDOWS_WIDTH = 3, + parameter WINDOWS_ANCHOR_X = 1, //禁止大于WINDOWS_WIDTH-1 + parameter WINDOWS_ANCHOR_Y = 1 //禁止大于WINDOWS_WIDTH-1 +) ( + // 基本信号 + input wire clk, + input wire reset, + // 数据线 + input wire [DATA_WIDTH - 1:0] in_data, + output reg [DATA_WIDTH - 1:0] out_data[WINDOWS_WIDTH*WINDOWS_WIDTH], // 数据输出线 + // 有效信号 + input wire in_valid, // 上一模块输出数据有效 + output reg out_valid, // 当前模块输出数据有效 + // 准备信号 Windows模块无法停止,因此默认不处理准备信号 + input wire in_ready, + output wire out_ready +); + + assign out_ready = 1'b1; + + reg [DATA_WIDTH - 1:0] regx_in_data [WINDOWS_WIDTH-1]; + reg [DATA_WIDTH - 1:0] regx_out_data[WINDOWS_WIDTH-1]; + reg [WINDOWS_WIDTH - 2:0] regx_in_valid, regx_out_valid; + + reg [DATA_WIDTH - 1:0] data_out_shift[WINDOWS_WIDTH-1][2*(WINDOWS_WIDTH-1)]; + + + /* outdata[x]: +SHIFT_REG1 -> 0 3 6 . . +SHIFT_REG0 -> 1 4 7 . . + in_data -> 2 5 8 . . + . . . + . . . +*/ + + reg [15:0] pos_x, pos_y; + always @(posedge clk) begin + if (reset) begin + pos_x <= 0; + pos_y <= 0; + end else if (regx_out_valid[WINDOWS_WIDTH-2]) begin + pos_x <= (pos_x >= IMAGE_WIDTH - 1) ? (0) : (pos_x + 1); + pos_y <= (pos_x >= IMAGE_WIDTH - 1)?((pos_y >= IMAGE_HEIGHT - 1)?(0):(pos_y + 1)):(pos_y); + end else begin + pos_x <= pos_x; + pos_y <= pos_y; + end + end + + integer i, j; + always @(posedge clk) begin + if (reset) begin + for (i = 0; i < WINDOWS_WIDTH * WINDOWS_WIDTH; i = i + 1) out_data[i] <= 0; + out_valid <= 0; + end else if (regx_out_valid[WINDOWS_WIDTH-2]) begin + for (i = 0; i < WINDOWS_WIDTH; i = i + 1) begin + for (j = 0; j < WINDOWS_WIDTH; j = j + 1) begin + if (i == WINDOWS_WIDTH - 1) begin + if (j == 0) out_data[(WINDOWS_WIDTH*i)+j] <= regx_out_data[WINDOWS_WIDTH-2]; + else out_data[(WINDOWS_WIDTH*i)+j] <= data_out_shift[j-1][2*i-1]; + end else out_data[(WINDOWS_WIDTH*i)+j] <= out_data[(WINDOWS_WIDTH*(i+1))+j]; + end + end + out_valid <= ~((pos_y <= WINDOWS_WIDTH-WINDOWS_ANCHOR_Y-1 && pos_x < WINDOWS_WIDTH-WINDOWS_ANCHOR_X-1) || (pos_y < WINDOWS_WIDTH-WINDOWS_ANCHOR_Y-1)); + end else begin + for (i = 0; i < WINDOWS_WIDTH * WINDOWS_WIDTH - 1; i = i + 1) out_data[i] <= out_data[i]; + out_valid <= 0; + end + end + + always @(posedge clk) begin + if (reset) + for (i = 0; i < WINDOWS_WIDTH - 1; i = i + 1) + for (j = 0; j < WINDOWS_WIDTH - 1; j = j + 1) data_out_shift[i][j] <= 0; + else + for (i = 0; i < WINDOWS_WIDTH - 1; i = i + 1) begin + for (j = 0; j < 2 * (WINDOWS_WIDTH - 1); j = j + 1) begin + if (i == WINDOWS_WIDTH - 2 && j == 0) data_out_shift[i][j] <= in_data; + else if (j == 0) data_out_shift[i][j] <= regx_out_data[(WINDOWS_WIDTH-2-i)-1]; + else data_out_shift[i][j] <= data_out_shift[i][j-1]; + end + end + end + + always @(*) begin + for (i = 0; i < WINDOWS_WIDTH - 1; i = i + 1) begin + if (i == 0) regx_in_data[i] = in_data; + else regx_in_data[i] = regx_out_data[i-1]; + end + for (i = 0; i < WINDOWS_WIDTH - 1; i = i + 1) begin + if (i == 0) regx_in_valid[i] = in_valid; + else regx_in_valid[i] = regx_out_valid[i-1]; + end + end + + generate + genvar o; + for (o = 0; o < WINDOWS_WIDTH - 1; o = o + 1'b1) begin : shift_register + SHIFT_REGISTER #( + .DATA_WIDTH (DATA_WIDTH), + .IMAGE_WIDTH(IMAGE_WIDTH), + .IFOUTIMME (1'b1) + ) shift_registerx ( + .clk (clk), + .reset (reset), + .in_data (regx_in_data[o]), + .out_data (regx_out_data[o]), + .in_valid (regx_in_valid[o]), + .out_valid(regx_out_valid[o]) + ); + end + endgenerate + +endmodule diff --git a/rtl/Color/ColorBlender_Pipeline.sv b/rtl/Color/ColorBlender_Pipeline.sv index a936f1c..11eafd9 100644 --- a/rtl/Color/ColorBlender_Pipeline.sv +++ b/rtl/Color/ColorBlender_Pipeline.sv @@ -2,24 +2,24 @@ // 三通道图像合成一个RGB图像 module ColorBlender_Pipeline #( - parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深 + parameter reg [4:0] DATA_WIDTH = 12, // 输入图像的色深 parameter reg [4:0] OUT_DEPTH = 8 // 输出图像的色深 ) ( input wire clk, input wire reset, - - input wire [16 - 1:0] in_data [3], + + input wire [DATA_WIDTH - 1:0] in_data [3], output reg [OUT_DEPTH - 1:0] out_data [3], - + input wire in_valid, output wire out_valid, - + input wire in_ready, output wire out_ready, - + input wire in_hsync, input wire in_fsync, - + output wire out_hsync, output wire out_fsync, @@ -29,7 +29,6 @@ module ColorBlender_Pipeline #( input wire [15:0] gain_blue, input wire enable ); - localparam PIPELINE = 4; reg [PIPELINE-1:0] pipeline_hsync, pipeline_fsync, pipeline_valid; @@ -65,9 +64,9 @@ module ColorBlender_Pipeline #( pipeline_fsync <= {pipeline_fsync[PIPELINE-2:0], in_fsync}; /************* 1:计算1 ************/ if(in_valid) begin - data_cal0[0] <= ({16'b0, in_data[0]}) << (8 - (IN_DEPTH - OUT_DEPTH)); - data_cal0[1] <= ({16'b0, in_data[1]}) << (8 - (IN_DEPTH - OUT_DEPTH)); - data_cal0[2] <= ({16'b0, in_data[2]}) << (8 - (IN_DEPTH - OUT_DEPTH)); + data_cal0[0] <= (in_data[0]) << (8 - (DATA_WIDTH - OUT_DEPTH)); + data_cal0[1] <= (in_data[1]) << (8 - (DATA_WIDTH - OUT_DEPTH)); + data_cal0[2] <= (in_data[2]) << (8 - (DATA_WIDTH - OUT_DEPTH)); end /************* 2:计算2 ************/ if(pipeline_valid[0]) begin @@ -83,9 +82,9 @@ module ColorBlender_Pipeline #( end /************* 3:计算3 ************/ if(pipeline_valid[1]) begin - data_cal2[0] <= (data_cal1[0][31 : OUT_DEPTH] != 0) ? {32{1'b1}} : data_cal1[0]; - data_cal2[1] <= (data_cal1[1][31 : OUT_DEPTH] != 0) ? {32{1'b1}} : data_cal1[1]; - data_cal2[2] <= (data_cal1[2][31 : OUT_DEPTH] != 0) ? {32{1'b1}} : data_cal1[2]; + data_cal2[0] <= (|data_cal1[0][31 : OUT_DEPTH]) ? {32{1'b1}} : data_cal1[0]; + data_cal2[1] <= (|data_cal1[1][31 : OUT_DEPTH]) ? {32{1'b1}} : data_cal1[1]; + data_cal2[2] <= (|data_cal1[2][31 : OUT_DEPTH]) ? {32{1'b1}} : data_cal1[2]; end /************* 4:发送结果 ************/ if(pipeline_valid[2]) begin diff --git a/rtl/Color/GammaCorrection_Pipeline.sv b/rtl/Color/GammaCorrection_Pipeline.sv new file mode 100755 index 0000000..f3089d8 --- /dev/null +++ b/rtl/Color/GammaCorrection_Pipeline.sv @@ -0,0 +1,85 @@ +`timescale 1ns / 1ps + +module GammaCorrection_Pipeline #( + parameter reg [4:0] COLOR_DEPTH = 8 + ) ( + input wire clk, + input wire reset, + + input wire in_valid, + output reg out_valid, + + input wire in_ready, + output wire out_ready, + + input wire in_hsync, + output wire out_hsync, + + input wire [COLOR_DEPTH - 1 : 0] in_data[3], + + output reg [COLOR_DEPTH - 1 : 0] out_data[3], + + input wire [7:0] gamma_table[256], + input wire enable + ); + reg [7:0] data_cache[3]; + + assign out_ready = (!in_en && state == READ_DATA && !reset) ? 1 : 0; + assign out_receive = (in_en && state == READ_DATA && !reset) ? 1 : 0; + + always @(posedge clk) + 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 && !in_receive) + 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/rtl/Demosaic/Demosaic_Pipeline.sv b/rtl/Demosaic/Demosaic_Pipeline.sv deleted file mode 100644 index 8585bdd..0000000 --- a/rtl/Demosaic/Demosaic_Pipeline.sv +++ /dev/null @@ -1,132 +0,0 @@ -`timescale 1ns / 1ps -module Demosaic_Pipeline #( - parameter WINDOW_LENGTH = 3, - parameter reg [15:0] TOTAL_WIDTH = 512+3, // 总图像宽度 - parameter reg [15:0] TOTAL_HEIGHT = 256+3, // 总图像高度 - parameter reg [ 1:0] RAW_TYPE = 3, // (0,0)位置算起RAW_TYPE的值 - parameter reg [ 4:0] DATA_WIDTH = 16 // 输入/输出数据位宽 - )( - input wire clk, - input wire reset, - - input wire [DATA_WIDTH - 1:0] in_data [WINDOW_LENGTH*WINDOW_LENGTH], // 数据输入线.第一列数据在[0],[1],[2]中 - output reg [DATA_WIDTH - 1:0] out_data [3], // 数据输出线,3、2、1分别表示r、g、b - - input wire in_valid, - output wire out_valid, - - input wire in_ready, - output wire out_ready, - - output reg out_hsync, // 行同步,一行第一个像素点输出的同时高电平 - output reg out_fsync // 帧同步,一帧第一个像素点输出的同时高电平 - ); - - localparam DATA_NUM = WINDOW_LENGTH*WINDOW_LENGTH; - localparam PIPILINE = 3; - - reg [PIPILINE-1:0] pipeline_valid; - wire pipeline_running; - assign pipeline_running = in_ready | ~pipeline_valid[PIPILINE-1]; - - //out_ready :只要本模块可以接收数据就一直拉高 - assign out_ready = pipeline_running; - //out_valid :只要本模块可以发出数据就一直拉高 - assign out_valid = pipeline_valid[PIPILINE-1]; - - reg [DATA_WIDTH-1:0] data_cache[DATA_NUM]; // 缓存颜色数据,行列nxn - reg [31:0] pos_x, pos_y, temp_pos_x, temp_pos_y; - reg [DATA_WIDTH-1:0] red, blue, green; - reg [1:0] raw_type; - - integer i; - always @(posedge clk) - begin - if(reset) - begin - for(i=0;i= TOTAL_WIDTH - 1)?(0):(pos_x + 1); - pos_y <= (pos_x >= TOTAL_WIDTH - 1)?((pos_y >= TOTAL_HEIGHT - 1)?(0):(pos_y + 1)):(pos_y); - end - - if(pipeline_valid[0]) - begin - temp_pos_x <= pos_x; - temp_pos_y <= pos_y; - case (raw_type) - 0: - begin // Missing B, R on G - blue <= (data_cache[1] + data_cache[7]) >> 1; - red <= (data_cache[3] + data_cache[5]) >> 1; - green <= data_cache[4]; - end - 1: - begin // Missing G, R on B - green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) >> 2; - red <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) >> 2; - blue <= data_cache[4]; - end - 2: - begin // Missing G, B on R - green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) >> 2; - blue <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) >> 2; - red <= data_cache[4]; - end - 3: - begin // Missing B, R on G - red <= (data_cache[1] + data_cache[7]) >> 1; - blue <= (data_cache[3] + data_cache[5]) >> 1; - green <= data_cache[4]; - end - endcase - end - - if(pipeline_valid[1]) - begin - {out_data[2],out_data[1],out_data[0]} <= {red,blue,green}; - out_hsync <= (temp_pos_x == 0); - out_fsync <= ((temp_pos_x == 0) && (temp_pos_y == 0)); - end - end - end - - // 0:gr 1:rg 2:bg 3:gb 窗口右移,0<->1 2<->3; 窗口下移,0<->2,1<->3。 - // bg gb gr rg - always @(*) - begin - if(reset) - raw_type = RAW_TYPE; - else - case (RAW_TYPE) - 2'b00: - raw_type = {pos_y[0], pos_x[0]}; - 2'b01: - raw_type = {pos_y[0], ~pos_x[0]}; - 2'b10: - raw_type = {~pos_y[0], pos_x[0]}; - 2'b11: - raw_type = {~pos_y[0], ~pos_x[0]}; - endcase - end - -endmodule - diff --git a/rtl/Demosaic/Windows.sv b/rtl/Demosaic/Windows.sv deleted file mode 100644 index d68b619..0000000 --- a/rtl/Demosaic/Windows.sv +++ /dev/null @@ -1,56 +0,0 @@ -`timescale 1ns / 1ps -module Windows #( -parameter reg [ 4:0] DATA_WIDTH = 16 // 输入/输出数据位宽 -)( - // 基本信号 - input wire clk, - input wire reset, - // 数据线 - input wire [DATA_WIDTH - 1:0] in_data [3], // 0、1、2分别表示第一、二、三行 - output reg [DATA_WIDTH - 1:0] out_data [3*3], // 数据输出线 - // 有效信号 - input wire in_valid, // 上一模块输出数据有效 - output wire out_valid, // 当前模块输出数据有效 - // 准备信号 - input wire in_ready, // 下一模块可接受新数据 - output wire out_ready // 当前模块可接收新数据 -); - - localparam PIPILINE = 3; - - reg [PIPILINE-1:0] pipeline_valid; - - //out_ready :只要本模块可以接收数据就一直拉高 - assign out_ready = (pipeline_valid != {PIPILINE{1'b1}}) | ((pipeline_valid == {PIPILINE{1'b1}}) && in_ready); - //out_valid :只要本模块可以发出数据就一直拉高 - assign out_valid = (pipeline_valid == {PIPILINE{1'b1}}); - - integer i; - always @(posedge clk) begin - if(reset) begin - for(i=0;i<9;i=i+1) out_data[i] <= 0; - pipeline_valid <= 0; - end else begin - if((pipeline_valid != {PIPILINE{1'b1}}) || ((pipeline_valid == {PIPILINE{1'b1}}) && in_ready))begin - pipeline_valid[0] <= in_valid; - out_data[6] <= in_data[0]; - out_data[7] <= in_data[1]; - out_data[8] <= in_data[2]; - end - if((pipeline_valid[2] == 0) || (pipeline_valid[1] == 0) || ((pipeline_valid == {PIPILINE{1'b1}}) && in_ready))begin - pipeline_valid[1] <= pipeline_valid[0]; - out_data[3] <= out_data[6]; - out_data[4] <= out_data[7]; - out_data[5] <= out_data[8]; - end - if((pipeline_valid[2] == 0) || ((pipeline_valid == {PIPILINE{1'b1}}) && in_ready))begin - pipeline_valid[2] <= pipeline_valid[1]; - out_data[0] <= out_data[3]; - out_data[1] <= out_data[4]; - out_data[2] <= out_data[5]; - end - end - end - -endmodule - diff --git a/rtl/isp_Pipeline.sv b/rtl/isp_Pipeline.sv index 5f846f1..c8ac04a 100644 --- a/rtl/isp_Pipeline.sv +++ b/rtl/isp_Pipeline.sv @@ -1,6 +1,13 @@ `timescale 1ns / 1ps - +/* TODO 1. ISP寄存器配置模式,如配置是否启用什么什么矫正,矫正系数多少。能读能写。选好通信协议,要不要用AXI? + 2. 白平衡,GAMMA矫正。白平衡做RAW白平衡吗? + 3. 寄存器中应该有一个寄存器标识ISP运行状态。比如裁切模块,直接修改寄存器值数据就乱了。 + 4. 缩放模块。如何处理模块进出数据量不匹配? + 5. 旋转模块。这怎么做? + 6. ISP不应该只有一条线,比如存进SDRAM后,读出来时也可以做处理。 +*/ module isp_Pipeline #( + parameter reg [15:0] DATA_WIDTH = 12, parameter reg [15:0] IN_WIDTH = 1936, parameter reg [15:0] IN_HEIGHT = 1088, parameter OFFSET_X = 7, @@ -15,8 +22,10 @@ module isp_Pipeline #( input wire reset, // 数据线 - input wire [15:0] in_data[3], // 数据输入线,0、1、2分别表示第一、二、三行 + input wire [DATA_WIDTH-1:0] in_data, // 数据输入线 output wire [3 * COLOR_DEPTH - 1:0] out_data, + output wire fsync, + output wire hsync, // 数据有效信号 input wire in_valid, @@ -33,29 +42,70 @@ module isp_Pipeline #( input wire blender_enable // 是否启用颜色校正 ); - wire [15:0] Demosaic2_data[3]; - wire [15:0] Windows_data[9]; + wire [DATA_WIDTH-1:0] DPC_data; + wire [DATA_WIDTH-1:0] Demosaic_data[3]; + wire [DATA_WIDTH-1:0] Windows_DPC_data[5*5]; + wire [DATA_WIDTH-1:0] Windows_Demosaic_data[3*3]; wire [COLOR_DEPTH - 1 : 0] Blender_data[3]; wire [COLOR_DEPTH - 1 : 0] Crop_data[3]; - wire Windows_valid, Demosaic2_valid, Blender_valid, Crop_valid; - wire Windows_ready, Demosaic2_ready, Blender_ready, Crop_ready; - wire Demosaic2_hsync, Blender_hsync, Crop_hsync; - wire Demosaic2_fsync, Blender_fsync, Crop_fsync; + wire Windows_DPC_valid, DPC_valid, Windows_Demosaic_valid, Demosaic_valid, Blender_valid, Crop_valid; + wire Windows_DPC_ready, DPC_ready, Windows_Demosaic_ready, Demosaic_ready, Blender_ready, Crop_ready; + wire Demosaic_hsync, Blender_hsync, Crop_hsync; + wire Demosaic_fsync, Blender_fsync, Crop_fsync; assign out_valid = Crop_valid; - assign out_ready = Windows_ready; - assign out_data = {Crop_data[2], Crop_data[1], Crop_data[0]}; + assign out_ready = Windows_DPC_ready; + assign out_data = {Crop_data[2], Crop_data[1], Crop_data[0]}; + assign fsync = Crop_fsync; + assign hsync = Crop_hsync; Windows #( - .DATA_WIDTH(16) - ) Windows_inst ( + .DATA_WIDTH (DATA_WIDTH), + .IMAGE_WIDTH (IN_WIDTH), + .WINDOWS_WIDTH (5), + .WINDOWS_ANCHOR_X(2), + .WINDOWS_ANCHOR_Y(2) + ) Windows_DPC_inst ( .clk (clk), .reset (reset), .in_data (in_data), - .out_data (Windows_data), + .out_data (Windows_DPC_data), .in_valid (in_valid), - .out_valid(Windows_valid), - .in_ready (Demosaic2_ready), - .out_ready(Windows_ready) + .out_valid(Windows_DPC_valid), + .in_ready (DPC_ready), + .out_ready(Windows_DPC_ready) + ); + + DPC #( + .TOTAL_WIDTH (IN_WIDTH), + .TOTAL_HEIGHT(IN_HEIGHT), + .RAW_TYPE (3), + .DATA_WIDTH (DATA_WIDTH) + ) DPC_inst ( + .clk (clk), + .reset (reset), + .in_data (Windows_DPC_data), + .out_data (DPC_data), + .in_valid (Windows_DPC_valid), + .out_valid(DPC_valid), + .in_ready (Windows_Demosaic_ready), + .out_ready(DPC_ready) + ); + + Windows #( + .DATA_WIDTH (DATA_WIDTH), + .IMAGE_WIDTH (IN_WIDTH), + .WINDOWS_WIDTH (3), + .WINDOWS_ANCHOR_X(1), + .WINDOWS_ANCHOR_Y(1) + ) Windows_Demosaic_inst ( + .clk (clk), + .reset (reset), + .in_data (DPC_data), + .out_data (Windows_Demosaic_data), + .in_valid (DPC_valid), + .out_valid(Windows_Demosaic_valid), + .in_ready (Demosaic_ready), + .out_ready(Windows_Demosaic_ready) ); @@ -63,35 +113,35 @@ module isp_Pipeline #( .WINDOW_LENGTH(3), .TOTAL_WIDTH (IN_WIDTH), .TOTAL_HEIGHT (IN_HEIGHT), - .RAW_TYPE (RAW_TYPE), - .DATA_WIDTH (16) - ) Demosaic2_inst ( + .RAW_TYPE (3), + .DATA_WIDTH (DATA_WIDTH) + ) Demosaic_inst ( .clk (clk), .reset (reset), - .in_data (Windows_data), - .out_data (Demosaic2_data), - .in_valid (Windows_valid), - .out_valid(Demosaic2_valid), + .in_data (Windows_Demosaic_data), + .out_data (Demosaic_data), + .in_valid (Windows_Demosaic_valid), + .out_valid(Demosaic_valid), .in_ready (Blender_ready), - .out_ready(Demosaic2_ready), - .out_hsync(Demosaic2_hsync), - .out_fsync(Demosaic2_fsync) + .out_ready(Demosaic_ready), + .out_hsync(Demosaic_hsync), + .out_fsync(Demosaic_fsync) ); ColorBlender_Pipeline #( - .IN_DEPTH(12), // 输入图像的色深 - .OUT_DEPTH(COLOR_DEPTH) // 输出图像的色深 + .DATA_WIDTH(DATA_WIDTH), // 输入图像的色深 + .OUT_DEPTH (COLOR_DEPTH) // 输出图像的色深 ) ColorBlender_inst ( .clk (clk), .reset (reset), - .in_data (Demosaic2_data), + .in_data (Demosaic_data), .out_data (Blender_data), - .in_valid (Demosaic2_valid), + .in_valid (Demosaic_valid), .out_valid(Blender_valid), .in_ready (Crop_ready), .out_ready(Blender_ready), - .in_hsync (Demosaic2_hsync), - .in_fsync (Demosaic2_fsync), + .in_hsync (Demosaic_hsync), + .in_fsync (Demosaic_fsync), .out_hsync(Blender_hsync), .out_fsync(Blender_fsync), diff --git a/src/sc_main.cpp b/src/sc_main.cpp index a4bc729..c06c010 100755 --- a/src/sc_main.cpp +++ b/src/sc_main.cpp @@ -21,9 +21,7 @@ // Include model header, generated from Verilating "isp.v" #include "Visp.h" - -// Write Pictures -#include "bitmap_image.hpp" +#include "tb_isp.hpp" // Image Parameters static const uint16_t IN_WIDTH = 1936; @@ -56,161 +54,6 @@ static const double contrast = 1.2; using namespace sc_core; using namespace sc_dt; -SC_MODULE(TB_ISP) { - sc_in_clk clk; - sc_in rst; - - sc_in in_ready; // next module ready to receive data - sc_out out_valid; // next module data valid signal - sc_out out_data[3]; // next module receive data - - sc_in in_valid; // this module receive data valid signal - sc_out out_ready; // this module ready to receive data - sc_in in_data; // this module receive data - - bool is_done; // when receive all data - std::vector image; // the data of image - std::vector process_image = std::vector( - OUT_SIZE, 0); // after isp process, the data of image - - SC_CTOR(TB_ISP) { - SC_CTHREAD(sendData, clk.pos()); // when clk posedge, exec sendData - reset_signal_is(rst, true); // set rst signal - - SC_CTHREAD(readData, clk.pos()); - reset_signal_is(rst, true); // set rst signal - } - - void sendData(void) { - // init var - uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0; - bool is_finish = false; // when send all data - // reset - out_valid = false; - for (auto &data : out_data) - data = 0; - - while (true) { - if (in_ready && !is_finish) { - // valid and send data - out_valid = true; - out_data[0] = image[(pos_y + 0) * IN_WIDTH + pos_x]; - out_data[1] = image[(pos_y + 1) * IN_WIDTH + pos_x]; - out_data[2] = image[(pos_y + 2) * IN_WIDTH + pos_x]; - - // print data - std::printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, - image[(pos_y + 0) * IN_WIDTH + pos_x]); - std::printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, - image[(pos_y + 1) * IN_WIDTH + pos_x]); - std::printf("x=%4d, y=%4d, data=0x%04x\n", pos_x, pos_y, - image[(pos_y + 2) * IN_WIDTH + pos_x]); - pos_x++; - - // calculate position and recognize when to finish - if (pos_x >= IN_WIDTH) { - pos_x = 0; - pos_y++; - } - if (pos_y >= IN_HEIGHT - 1) { - pos_y = 0; - cnt_flame++; - } - if (cnt_flame >= FLAMES) { - is_finish = true; - } - } else { - out_valid = false; - } - - // wait for next clk - wait(); - } - } - - void readData(void) { - // init local var - uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0; - uint32_t last_data = 0, cnt = 0; - bool is_finish = false; - // reset - out_ready = false; - is_done = false; - - while (true) { - if (!is_finish) { - out_ready = true; - - // when data valid, write it down - if (in_valid) { - process_image[pos_y * OUT_WIDTH + pos_x] = in_data; - - // calculate position - pos_x++; - - if (pos_x >= OUT_WIDTH) { - pos_x = 0; - pos_y++; - } - if (pos_y >= OUT_HEIGHT) { - pos_y = 0; - saveData( - ("output_img_" + std::to_string(cnt_flame) + ".bmp").c_str()); - cnt_flame++; - } - if (cnt_flame >= FLAMES) { - is_finish = true; - } - } - } else { - out_ready = false; - } - - // when no data send, give finish signal - if (is_finish && (last_data == in_data)) { - cnt++; - if (cnt >= 100000L) { // when receive many times the same data - is_done = true; - std::printf("Finish Reading data; pos_x = %d, pos_y = %d\n", pos_x, - pos_y); - } - } else { - cnt = 0; - } - last_data = in_data; - - // wait for next clk - wait(); - } - } - - bool saveData(const char *name) { - bool ret = true; - - // Check Image Size - if (process_image.size() > OUT_SIZE) { - std::cout << "Process Image Over Size!!!\n" - << "Image Size:" << process_image.size() << "\n"; - return false; - } - - // Write BMP image - bitmap_image bmp(OUT_WIDTH, OUT_HEIGHT); - if (!bmp) { - std::cout << "Output Image Open Failed!!!\n"; - return false; - } - for (int y = 0; y < OUT_HEIGHT; y++) - for (int x = 0; x < OUT_WIDTH; x++) - bmp.set_pixel(x, y, - (process_image[y * OUT_WIDTH + x] & 0x00ff0000) >> 16, - (process_image[y * OUT_WIDTH + x] & 0x0000ff00) >> 8, - (process_image[y * OUT_WIDTH + x] & 0x000000ff) >> 0); - bmp.save_image(std::string(OUTPUT_DIR) + name); - return ret; - } -}; - int sc_main(int argc, char *argv[]) { std::printf("Enter into sc_main\n"); @@ -295,25 +138,6 @@ int sc_main(int argc, char *argv[]) { // Construct the Verilated model, from inside Visp.h Visp isp("Visp"); - // isp.clk(clk); - // isp.reset(rst); - // // Connect input signal - // isp.in_valid(in_valid); - // isp.in_ready(in_ready); - // for (int i = 0; i < 3; i++) - // isp.in_data[i](in_data[i]); - // // Connect output signal - // isp.out_valid(out_valid); - // isp.out_ready(out_ready); - // isp.out_data(out_data); - // // Connect ISP modules enable signal - // isp.blender_enable(blender_enable); - // // Connect ISP modules configuration signal - // isp.gain_red(gain_red); - // isp.gain_green(gain_green); - // isp.gain_blue(gain_blue); - - // ISP Old Version isp.clk(clk); isp.reset(rst); isp.in_en(in_valid); @@ -340,7 +164,7 @@ int sc_main(int argc, char *argv[]) { isp.white_gain[i](white_gain[i]); // Construct testbench module - TB_ISP tb_isp("tb_isp"); + TB_ISP tb_isp("tb_isp", IN_WIDTH, IN_HEIGHT, OUT_WIDTH, OUT_HEIGHT, FLAMES, OUTPUT_DIR); tb_isp.image = std::move(in_image); tb_isp.clk(clk); tb_isp.rst(rst); diff --git a/src/sc_main.cpp.back b/src/sc_main.cpp.back deleted file mode 100644 index fb219d1..0000000 --- a/src/sc_main.cpp.back +++ /dev/null @@ -1,525 +0,0 @@ -// For std::unique_ptr -#include -#include - -// SystemC global header -#include -#include - -// Include common routines -#include // mkdir -#include -#include -#include - -// Include model header, generated from Verilating "isp.v" -#include "Visp.h" - -// Handle file -#include -#include - -// math -#include - -#include "bitmap_image.hpp" - -static const uint16_t IN_WIDTH = 1936; -static const uint16_t IN_HEIGHT = 1088; -static const uint32_t IN_SIZE = (IN_WIDTH * IN_HEIGHT); -static const uint16_t OUT_WIDTH = 1920; -static const uint16_t OUT_HEIGHT = 1080; -static const uint32_t OUT_SIZE = (OUT_WIDTH * OUT_HEIGHT); -static const uint32_t FLAMES = 2; - -// Input image path and Output directory path -#ifndef INPUT_IMG -const char *INPUT_IMG = "./src/transform/test.bin"; -#endif -#ifndef OUTPUT_DIR -const char *OUTPUT_DIR = "./logs/"; -#endif - -// color gain for correcting color -struct color_gain { - double red; - double green; - double blue; -} color_gain{1.1, 0.7, 1.3}, white_gain; - -static const double gamma_value = 2.2; -static const double saturation_inc = 0.5; -static const double contrast = 1.2; -// 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; - - sc_in in_ready; - sc_in in_receive; - sc_out out_en; - sc_out out_data[3]; - - sc_in im_en; - sc_out out_ready; - // sc_out out_receceive; - sc_in im_data; - - sc_out is_done; - std::vector image; // the data of image - std::vector process_image = std::vector( - OUT_SIZE, 0); // after isp process, the data of image - - SC_CTOR(TB_ISP) { - SC_CTHREAD(send_Data, clk.pos()); - reset_signal_is(reset, true); - - SC_CTHREAD(read_Data, clk.pos()); - } - - void send_Data(void) { - uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0; - bool is_finish = false; - while (true) { - if (in_ready.read() && !is_finish) { - 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]); - - 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]); - - pos_x++; - if (pos_x >= IN_WIDTH) { - pos_x = 0; - pos_y++; - } - if (pos_y >= IN_HEIGHT - 1) { - pos_y = 0; - cnt_flame++; - } - if (cnt_flame >= FLAMES) { - is_finish = true; - } - } else { - out_en.write(0); - } - - wait(); - } - } - - void read_Data(void) { - is_done.write(0); - uint32_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() && !is_finish) { - out_ready.write(false); - - process_image[pos_y * OUT_WIDTH + pos_x] = im_data.read(); - pos_x++; - - if (pos_x >= OUT_WIDTH) { - pos_x = 0; - pos_y++; - } - if (pos_y >= OUT_HEIGHT) { - pos_y = 0; - saveData( - ("output_img_" + std::to_string(cnt_flame) + ".bmp").c_str()); - 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() && is_finish) { - cnt++; - if (cnt >= 100000L) { - is_done.write(1); - printf("x=%d, y=%d\n", pos_x, pos_y); - } - } else { - cnt = 0; - } - last_data = im_data.read(); - - wait(); - } - } - - bool saveData(const char *name) { - bool ret = true; - - // Check Image Size - if (process_image.size() > OUT_SIZE) { - std::cout << "Process Image Over Size!!!\n" - << "Image Size:" << process_image.size() << "\n"; - return false; - } - - // Transform isp image - // std::vector bmp_image(3 * OUT_SIZE); - // for (int i = 0; i < OUT_SIZE; i++) { - // bmp_image[3 * i + 0] = (process_image[i] & 0x00ff0000) >> 16; - // bmp_image[3 * i + 1] = (process_image[i] & 0x0000ff00) >> 8; - // bmp_image[3 * i + 2] = (process_image[i] & 0x000000ff) >> 0; - // } - - // Write BMP image - bitmap_image bmp(OUT_WIDTH, OUT_HEIGHT); - if (!bmp) { - std::cout << "Output Image Open Failed!!!\n"; - return false; - } - for (int y = 0; y < OUT_HEIGHT; y++) - for (int x = 0; x < OUT_WIDTH; x++) - bmp.set_pixel(x, y, - (process_image[y * OUT_WIDTH + x] & 0x00ff0000) >> 16, - (process_image[y * OUT_WIDTH + x] & 0x0000ff00) >> 8, - (process_image[y * OUT_WIDTH + x] & 0x000000ff) >> 0); - bmp.save_image(std::string(OUTPUT_DIR) + name); - return ret; - } -}; - -// 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)); -// // } -// // } - -// // Contrast enhancement -// // red = static_cast(contrast * (red - 128) + 128); -// // green = static_cast(contrast * (green - 128) + 128); -// // blue = static_cast(contrast * (blue - 128) + 128); - -// // 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::printf("Enter into sc_main\n"); - - // Open Image - std::ifstream image; - image.open(INPUT_IMG, std::ios::in | std::ios::binary); - // Check image whether is open - if (!image.is_open()) { - std::printf("Open Image Failed!!!\n"); - exit(0); - } else { - std::printf("Open Image Successfully!!!\n"); - } - - // Read and Transform Image - std::vector in_image(IN_SIZE); - uint8_t *buf = new uint8_t[2 * IN_SIZE]; - image.read((char *)buf, 2 * IN_SIZE); - uint32_t i = 0; - for (int y = 0; y < IN_HEIGHT; y++) { - for (int x = 0; x < IN_WIDTH; x++) { - in_image[y * IN_WIDTH + x] = - (uint16_t)buf[i] + ((uint16_t)buf[i + 1] << 8); - i += 2; - } - } - // Close and delete image - image.close(); - delete[] buf; - std::printf("Finish Reading Image\n"); - - // 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"); - - // Set debug level, 0 is off, 9 is highest presently used - // May be overridden by commandArgs argument parsing - Verilated::debug(0); - - // Randomization reset policy - // May be overridden by commandArgs argument parsing - Verilated::randReset(2); - - // 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 - // This needs to be called before you create any model - Verilated::commandArgs(argc, argv); - - // General logfile - std::ios::sync_with_stdio(); - - // Define clocks - sc_clock clk{"clk", 10, SC_NS, 0.5, 3, SC_NS, true}; - // Define interconnect - sc_signal reset; - - 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 out_ready; - sc_signal out_receive; - sc_signal out_data; - - 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 white_gain[3]; - sc_signal flame_rate; - sc_signal white_enable; - - sc_signal saturation_enable; - sc_signal saturation_increase; - - 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 - const std::unique_ptr isp{new Visp{"isp"}}; - // Attach Visp's signals to this upper model - isp->clk(clk); - isp->reset(reset); - 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_en(out_en); - 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->blender_enable(blender_enable); - - 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); - - blender_enable = true; // enable color correction - gain_red = static_cast(color_gain.red * std::pow(2, 8)); - gain_green = static_cast(color_gain.green * std::pow(2, 8)); - gain_blue = static_cast(color_gain.blue * std::pow(2, 8)); - - gamma_enable = true; - gamma_inverse = static_cast((1.0 / gamma_value) * std::pow(2, 8)); - for (int i = 0; i < 256; i++) { - // calculate gamma table - isp->gamma_table[i](gamma_table[i]); - gamma_table[i] = - static_cast(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)) - : (saturation_inc * std::pow(2, 8))); - - // Construct testbench module - TB_ISP tb_isp("tb_isp"); - tb_isp.clk(clk); - tb_isp.reset(reset); - 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_en(out_en); - tb_isp.im_data(out_data); - tb_isp.is_done(flag_done); - tb_isp.image = std::move(in_image); - - // You must do one evaluation before enabling waves, in order to allow - // SystemC to interconnect everything for testing. - sc_start(SC_ZERO_TIME); - - // If verilator was invoked with --trace argument, - // and if at run time passed the +trace argument, turn on tracing - VerilatedVcdSc *tfp = nullptr; - const char *flag = Verilated::commandArgsPlusMatch("trace"); - if (flag && 0 == std::strcmp(flag, "+trace")) { - std::cout << "Enabling waves into logs/vlt_dump.vcd...\n"; - tfp = new VerilatedVcdSc; - isp->trace(tfp, 99); // Trace 99 levels of hierarchy - Verilated::mkdir("logs"); - tfp->open("logs/vlt_dump.vcd"); - } - - // Simulate until $finish - while (!Verilated::gotFinish()) { - // Flush the wave files each cycle so we can immediately see the OUTPUT_DIR - // Don't do this in "real" programs, do it in an abort() handler instead - if (tfp) - tfp->flush(); - - // Apply inputs - if (sc_time_stamp() < sc_time(10, SC_NS)) { - reset.write(1); // Assert reset - } else { - reset.write(0); // Deassert reset - } - - if (flag_done.read()) - break; - - // Simulate 1ns - sc_start(1, SC_NS); - } - - // Final model cleanup - isp->final(); - - // Close trace if opened - if (tfp) { - tfp->close(); - tfp = nullptr; - } - - // Return good completion status - return 0; -} diff --git a/src/sc_main_pipeline.cpp b/src/sc_main_pipeline.cpp index faab916..a052bb2 100755 --- a/src/sc_main_pipeline.cpp +++ b/src/sc_main_pipeline.cpp @@ -118,11 +118,13 @@ int sc_main(int argc, char *argv[]) { // ISP Modules in ports sc_signal in_valid; sc_signal in_ready; - sc_signal in_data[3]; + sc_signal in_data; // ISP Modules out ports sc_signal out_valid; sc_signal out_ready; sc_signal out_data; + sc_signal out_hsync; + sc_signal out_fsync; // ISP Modules Enable Ports sc_signal blender_enable; sc_signal gamma_enable; @@ -144,12 +146,13 @@ int sc_main(int argc, char *argv[]) { // Connect input signal isp.in_valid(in_valid); isp.in_ready(in_ready); - for (int i = 0; i < 3; i++) - isp.in_data[i](in_data[i]); + isp.in_data(in_data); // Connect output signal isp.out_valid(out_valid); isp.out_ready(out_ready); isp.out_data(out_data); + isp.hsync(out_hsync); + isp.fsync(out_fsync); // Connect ISP modules enable signal isp.blender_enable(blender_enable); // Connect ISP modules configuration signal @@ -158,7 +161,8 @@ int sc_main(int argc, char *argv[]) { isp.gain_blue(gain_blue); // Construct testbench module - TB_ISP tb_isp("tb_isp", IN_WIDTH, IN_HEIGHT, OUT_WIDTH, OUT_HEIGHT, FLAMES, OUTPUT_DIR); + TB_ISP tb_isp("tb_isp", IN_WIDTH, IN_HEIGHT, OUT_WIDTH, OUT_HEIGHT, FLAMES, + OUTPUT_DIR); tb_isp.image = std::move(in_image); tb_isp.clk(clk); tb_isp.rst(rst); @@ -169,8 +173,7 @@ int sc_main(int argc, char *argv[]) { // Connect output signal tb_isp.out_valid(in_valid); tb_isp.out_ready(in_ready); - for (int i = 0; i < 3; i++) - tb_isp.out_data[i](in_data[i]); + tb_isp.out_data(in_data); // Set ISP modules parameters // Color Blender diff --git a/src/tb_isp.hpp b/src/tb_isp.hpp index e7448c5..e3578ba 100644 --- a/src/tb_isp.hpp +++ b/src/tb_isp.hpp @@ -13,7 +13,7 @@ SC_MODULE(TB_ISP) { sc_core::sc_in in_ready; // next module ready to receive data sc_core::sc_out out_valid; // next module data valid signal - sc_core::sc_out out_data[3]; // next module receive data + sc_core::sc_out out_data; // next module receive data sc_core::sc_in in_valid; // this module receive data valid signal sc_core::sc_out out_ready; // this module ready to receive data @@ -53,24 +53,17 @@ SC_MODULE(TB_ISP) { bool is_finish = false; // when send all data // reset out_valid = false; - for (auto &data : out_data) - data = 0; + out_data = 0; while (true) { if (in_ready && !is_finish) { // valid and send data out_valid = true; - out_data[0] = image[(pos_y + 0) * IN_WIDTH + pos_x]; - out_data[1] = image[(pos_y + 1) * IN_WIDTH + pos_x]; - out_data[2] = image[(pos_y + 2) * IN_WIDTH + pos_x]; + out_data = image[(pos_y + 0) * IN_WIDTH + pos_x]; // print data - std::printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, - image[(pos_y + 0) * IN_WIDTH + pos_x]); - std::printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, - image[(pos_y + 1) * IN_WIDTH + pos_x]); std::printf("x=%4d, y=%4d, data=0x%04x\n", pos_x, pos_y, - image[(pos_y + 2) * IN_WIDTH + pos_x]); + image[pos_y * IN_WIDTH + pos_x]); pos_x++; // calculate position and recognize when to finish @@ -78,7 +71,7 @@ SC_MODULE(TB_ISP) { pos_x = 0; pos_y++; } - if (pos_y >= IN_HEIGHT - 1) { + if (pos_y >= IN_HEIGHT) { pos_y = 0; cnt_flame++; }