finish reconstruction and pass simulation

This commit is contained in:
SikongJueluo 2024-06-28 19:38:36 +08:00
parent 85910958f9
commit c527835ff6
No known key found for this signature in database
GPG Key ID: D2D3D29A993716EA
7 changed files with 372 additions and 310 deletions

View File

@ -4,34 +4,35 @@
module ColorBlender #( module ColorBlender #(
parameter reg [ 4:0] IN_DEPTH = 12, // 输入图像的色深 parameter reg [ 4:0] IN_DEPTH = 12, // 输入图像的色深
parameter reg [ 4:0] OUT_DEPTH = 8, // 输出图像的色深 parameter reg [ 4:0] OUT_DEPTH = 8, // 输出图像的色深
parameter reg [16:0] GAIN_RED = 120, // 红色增益系数 parameter reg [ 8:0] BUFF_SIZE = 32
parameter reg [16:0] GAIN_GREEN = 50, // 绿色增益系数
parameter reg [16:0] GAIN_BLUE = 95, // 蓝色增益系数
parameter reg [ 4:0] GAIN_OFFSET = 7
) ( ) (
input clk, input wire clk,
input reset, input wire reset,
input in_en, input wire in_en,
input [15:0] data_in[2], // 0:R 1:G 2:B input wire [15:0] in_data[3], // 0:R 1:G 2:B
output out_ready, output wire out_ready,
output out_receive, output wire out_receive,
// 输出相关 // 输出相关
input in_ready, input wire in_ready,
input in_receive, input wire in_receive,
output out_en, output reg out_en,
output [3 * OUT_DEPTH - 1:0] out_data, 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 input wire color_correction
); );
localparam READ_DATA = 0; localparam reg [2:0] READ_DATA = 0;
localparam CALC_DATA = 1; localparam reg [2:0] CALC_DATA = 1;
localparam SEND_DATA = 2; localparam reg [2:0] SATI_DATA = 2;
localparam reg [2:0] SEND_DATA = 3;
reg [2:0] state, nextState; 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 always @(posedge clk or posedge reset) begin
if (reset) begin if (reset) begin
@ -44,15 +45,15 @@ module ColorBlender #(
always @(*) begin always @(*) begin
case (state) case (state)
READ_DATA: nextState = (in_en) ? (color_correction ? CALC_DATA : SEND_DATA) : READ_DATA; 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; SEND_DATA: nextState = (in_receive) ? READ_DATA : SEND_DATA;
default: nextState = READ_DATA; default: nextState = READ_DATA;
endcase endcase
end end
assign out_ready = (state == READ_DATA) ? 1 : 0; assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
assign out_receive = in_en ? 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 always @(posedge clk or posedge reset) begin
if (reset) begin if (reset) begin
@ -60,28 +61,38 @@ module ColorBlender #(
data_cal[0] <= 0; data_cal[0] <= 0;
data_cal[1] <= 0; data_cal[1] <= 0;
data_cal[2] <= 0; data_cal[2] <= 0;
out_data <= 0;
out_en <= 0;
end else begin end else begin
case (state) case (state)
READ_DATA: begin READ_DATA: begin
if (in_en) begin if (in_en) begin
data_cal[0] <= ({16'b0, data_in[0]} << 8; data_cal[0] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[0]}) << (8 - (IN_DEPTH - OUT_DEPTH));
data_cal[1] <= ({16'b0, data_in[1]} << 8; data_cal[1] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[1]}) << (8 - (IN_DEPTH - OUT_DEPTH));
data_cal[2] <= ({16'b0, data_in[2]} << 8; data_cal[2] <= ({{(BUFF_SIZE - 16){1'b0}}, in_data[2]}) << (8 - (IN_DEPTH - OUT_DEPTH));
end end
end end
CALC_DATA: begin CALC_DATA: begin
data_cal[0] <= data_cal[0] * (GAIN_RED << 8) data_cal[0] <= (data_cal[0] * {{(BUFF_SIZE - 16){1'b0}}, gain_red}) >> 16;
data_cal[1] <= data_cal[1] * (GAIN_GREEN << 8) data_cal[1] <= (data_cal[1] * {{(BUFF_SIZE - 16){1'b0}}, gain_green}) >> 16;
data_cal[2] <= data_cal[2] * (GAIN_BLUE << 8) 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 end
SEND_DATA: begin SEND_DATA: begin
if (in_ready) begin if (in_ready && !in_receive) begin
out_data[0] <= data_cal[0] >> (8 + IN_DEPTH - OUT_DEPTH) out_en <= 1;
out_data[1] <= data_cal[1] >> (8 + IN_DEPTH - OUT_DEPTH) out_data <= {
out_data[2] <= data_cal[2] >> (8 + IN_DEPTH - OUT_DEPTH) data_cal[0][OUT_DEPTH-1:0], data_cal[1][OUT_DEPTH-1:0], data_cal[2][OUT_DEPTH-1:0]
end };
end else out_en <= 0;
end end
default: ; default: ;

95
Crop/Crop.v Normal file
View File

@ -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

View File

@ -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

View File

@ -1,23 +1,23 @@
module demosaic2 #( module Demosaic2 #(
parameter reg [16:0] IM_WIDTH = 512, // 图像宽度 parameter reg [15:0] IM_WIDTH = 512, // 图像宽度
parameter reg [16:0] IM_HEIGHT = 256, // 图像高度 parameter reg [15:0] IM_HEIGHT = 256, // 图像高度
parameter reg [1:0] RAW_TYPE = 3, // 0:grbg 1:rggb 2:bggr 3:gbrg parameter reg [ 1:0] RAW_TYPE = 3, // 0:grbg 1:rggb 2:bggr 3:gbrg
parameter reg [5:0] DATA_SIZE = 16 parameter reg [ 4:0] DATA_SIZE = 16
) ( ) (
// 基本信号 // 基本信号
input clk, input wire clk,
input reset, input wire reset,
// 数据输入信号 // 数据输入信号
input in_en, input wire in_en,
input [DATA_SIZE - 1:0] in_data [2], // 数据输入线012分别表示第一三行 input wire [DATA_SIZE - 1:0] in_data [3], // 数据输入线012分别表示第一三行
output out_ready, // 数据请求线高电平请求三个数据直到读取完才拉低 output wire out_ready, // 数据请求线高电平请求三个数据直到读取完才拉低
output out_receive, output wire out_receive,
// en: 输出数据有效信号高电平有效 // en: 输出数据有效信号高电平有效
input in_ready, input wire in_ready,
input in_receive, input wire in_receive,
output out_en, output reg out_en,
output reg [DATA_SIZE - 1:0] out_r, output reg [DATA_SIZE - 1:0] out_r,
output reg [DATA_SIZE - 1:0] out_g, output reg [DATA_SIZE - 1:0] out_g,
output reg [DATA_SIZE - 1:0] out_b output reg [DATA_SIZE - 1:0] out_b
@ -26,15 +26,15 @@ module demosaic2 #(
// 常量包括状态机 // 常量包括状态机
// localparam IM_SIZE = IM_HEIGHT * IM_WIDTH; // localparam IM_SIZE = IM_HEIGHT * IM_WIDTH;
localparam READ_DATA = 0; localparam reg [2:0] READ_DATA = 0;
localparam COLOR_GEN = 1; localparam reg [2:0] COLOR_GEN = 1;
localparam SEND_DATA = 2; localparam reg [2:0] SEND_DATA = 2;
localparam SLIDE_WINDOW = 3; localparam reg [2:0] SLIDE_WINDOW = 3;
// 寄存器 // 寄存器
reg [2:0] state, nextState; reg [2:0] state, nextState;
reg [15:0] data_cache[2][2]; // 缓存颜色数据行列3x3 reg [15:0] data_cache[9]; // 缓存颜色数据行列3x3
reg [11:0] pos_x, pos_y; // 滑动窗口左上角位置 reg [15:0] pos_x, pos_y; // 滑动窗口左上角位置
reg [2:0] cnt_data; // 记录输入数据数量最大值256 reg [2:0] cnt_data; // 记录输入数据数量最大值256
reg [1:0] raw_type; reg [1:0] raw_type;
reg [15:0] red, blue, green; reg [15:0] red, blue, green;
@ -47,14 +47,14 @@ module demosaic2 #(
end end
// 下一状态更新 // 下一状态更新
always @(state or cnt_data) begin always @(*) begin
case (state) case (state)
// 记录够3x3个数据后进行rgb转换 // 记录够3x3个数据后进行rgb转换
READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA; READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA;
COLOR_GEN: nextState = SEND_DATA; COLOR_GEN: nextState = SEND_DATA;
SEND_DATA: nextState = (in_receive) ? SLIDE_WINDOW : SEND_DATA; SEND_DATA: nextState = (in_receive) ? SLIDE_WINDOW : SEND_DATA;
SLIDE_WINDOW: nextState = READ_DATA; SLIDE_WINDOW: nextState = READ_DATA;
default: nextState = 0; default: nextState = READ_DATA;
endcase endcase
end end
@ -62,8 +62,6 @@ module demosaic2 #(
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_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 always @(posedge clk or posedge reset) begin
@ -85,9 +83,9 @@ module demosaic2 #(
// 读取数据 // 读取数据
READ_DATA: begin READ_DATA: begin
if (in_en) begin if (in_en) begin
data_cache[cnt_data][0] <= in_data[0]; data_cache[0 + cnt_data * 3] <= in_data[0];
data_cache[cnt_data][1] <= in_data[1]; data_cache[1 + cnt_data * 3] <= in_data[1];
data_cache[cnt_data][2] <= in_data[2]; data_cache[2 + cnt_data * 3] <= in_data[2];
cnt_data <= cnt_data + 1; cnt_data <= cnt_data + 1;
end end
@ -96,33 +94,33 @@ module demosaic2 #(
COLOR_GEN: begin COLOR_GEN: begin
// 生成rgb图像 // 生成rgb图像
// data case 0 case 1 case 2 case 3 // data case 0 case 1 case 2 case 3
// 0 1 2 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
// 3 4 5 B G B G B G G R G R G R // 1 4 7 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 // 2 5 8 G R G R G R B G B G B G
case (raw_type) case (raw_type)
0: begin // Missing B, R on G 0: begin // Missing B, R on G
blue <= (data_cache[0][1] + data_cache[2][1]) / 2; blue <= (data_cache[1] + data_cache[7]) / 2;
red <= (data_cache[1][0] + data_cache[1][2]) / 2; red <= (data_cache[3] + data_cache[5]) / 2;
green <= data_cache[1][1]; green <= data_cache[4];
end end
1: begin // Missing G, R on B 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; green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) / 4;
red <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4; red <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) / 4;
blue <= data_cache[1][1]; blue <= data_cache[4];
end end
2: begin // Missing G, B on R 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; green <= (data_cache[1] + data_cache[3] + data_cache[5] + data_cache[7]) / 4;
blue <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4; blue <= (data_cache[0] + data_cache[2] + data_cache[6] + data_cache[8]) / 4;
red <= data_cache[1][1]; red <= data_cache[4];
end end
3: begin // Missing B, R on G 3: begin // Missing B, R on G
red <= (data_cache[0][1] + data_cache[2][1]) / 2; red <= (data_cache[1] + data_cache[7]) / 2;
blue <= (data_cache[1][0] + data_cache[1][2]) / 2; blue <= (data_cache[3] + data_cache[5]) / 2;
green <= data_cache[1][1]; green <= data_cache[4];
end end
default: ; default: ;
endcase endcase
@ -136,11 +134,12 @@ module demosaic2 #(
end end
SEND_DATA: begin SEND_DATA: begin
if (in_ready) begin if (in_ready && !in_receive) begin
out_en <= 1;
out_r <= red; out_r <= red;
out_b <= blue; out_b <= blue;
out_g <= green; out_g <= green;
end end else out_en <= 0;
end end
SLIDE_WINDOW: begin SLIDE_WINDOW: begin
@ -169,12 +168,12 @@ module demosaic2 #(
cnt_data <= 2; cnt_data <= 2;
// 窗口右移 // 窗口右移
data_cache[0][0] <= data_cache[1][0]; data_cache[0] <= data_cache[3];
data_cache[0][1] <= data_cache[1][1]; data_cache[1] <= data_cache[4];
data_cache[0][2] <= data_cache[1][2]; data_cache[2] <= data_cache[5];
data_cache[1][0] <= data_cache[2][0]; data_cache[3] <= data_cache[6];
data_cache[1][1] <= data_cache[2][1]; data_cache[4] <= data_cache[7];
data_cache[1][2] <= data_cache[2][2]; data_cache[5] <= data_cache[8];
end end
end end

80
isp.v
View File

@ -1,30 +1,37 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
module isp #( module isp #(
parameter IN_WIDTH = 1936, parameter reg [15:0] IN_WIDTH = 1936,
parameter IN_HEIGHT = 1088, parameter reg [15:0] IN_HEIGHT = 1088,
parameter OUT_WIDTH = 1920, parameter reg [15:0] OUT_WIDTH = 1920,
parameter OUT_HEIGHT = 1080, parameter reg [15:0] OUT_HEIGHT = 1080,
parameter COLOR_DEPTH = 8, parameter reg [ 4:0] COLOR_DEPTH = 8,
parameter RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg parameter reg [ 1:0] RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg
) ( ) (
// 基本信号 // 基本信号
input wire clk, input wire clk,
input wire reset, input wire reset,
// 数据输入信号 // 数据输入信号
input wire data_en, input wire in_en,
input reg [15:0] data_in[2:0], // 数据输入线012分别表示第一三行 input wire [15:0] in_data[3], // 数据输入线012分别表示第一三行
output reg data_que, // 数据请求线高电平请求三个数据直到读取完才拉低 output wire out_ready, // 数据请求线高电平请求三个数据直到读取完才拉低
output wire out_receive,
output wire out_clk, output wire out_clk,
output wire out_en, 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 input wire color_correction
); );
localparam BAYER_WIDTH = IN_WIDTH - 2; localparam reg [15:0] BAYER_WIDTH = IN_WIDTH - 2;
localparam BAYER_HEIGHT = IN_HEIGHT - 2; localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 2;
// 三通道合成RGB图像 // 三通道合成RGB图像
wire blender_en, blender_ready, blender_receive; wire blender_en, blender_ready, blender_receive;
wire [15:0] blender_r, blender_g, blender_b; wire [15:0] blender_r, blender_g, blender_b;
@ -38,21 +45,19 @@ module isp #(
// wire RAM_in_que; // RAM 请求数据 // wire RAM_in_que; // RAM 请求数据
// wire [3 * COLOR_DEPTH - 1:0] RAM_in_data; // 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_WIDTH (IN_WIDTH),
.IM_HEIGHT(IN_HEIGHT), .IM_HEIGHT(IN_HEIGHT),
.RAW_TYPE (RAW_TYPE) .RAW_TYPE (RAW_TYPE)
) CFA ( ) CFA (
.clk(clk), .clk(clk),
.reset(reset), .reset(reset),
.in_en(in_en),
.in_en(data_en), .in_data(in_data),
.in_data(data_in), .out_ready(out_ready),
.out_ready(data_que), .out_receive(out_receive),
.out_en(blender_en),
.out_receive(),
.out_en(blender_en), .out_en(blender_en),
.in_ready(blender_ready), .in_ready(blender_ready),
@ -64,13 +69,9 @@ module isp #(
ColorBlender #( ColorBlender #(
.IN_DEPTH (12), .IN_DEPTH (12),
.OUT_DEPTH(8), .OUT_DEPTH(8)
.GAIN_RED(120),
.GAIN_GREEN(50),
.GAIN_BLUE(95),
) blender ( ) blender (
.clk(clk), .clk (clk),
.reset(reset), .reset(reset),
.in_en(blender_en), .in_en(blender_en),
@ -79,14 +80,17 @@ module isp #(
.out_receive(blender_receive), .out_receive(blender_receive),
.in_ready(crop_ready), .in_ready(crop_ready),
.in_receive(crop_receive) .in_receive(crop_receive),
.out_en(crop_en), .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) .color_correction(color_correction)
); );
crop #( Crop #(
.IN_WIDTH(BAYER_WIDTH), .IN_WIDTH(BAYER_WIDTH),
.IN_HEIGHT(BAYER_HEIGHT), .IN_HEIGHT(BAYER_HEIGHT),
.OUT_WIDTH(OUT_WIDTH), .OUT_WIDTH(OUT_WIDTH),
@ -96,15 +100,15 @@ module isp #(
.clk (clk), .clk (clk),
.reset(reset), .reset(reset),
.in_en (crop_en), .in_en(crop_en),
.out_ready (crop_ready), .out_ready(crop_ready),
.out_receive(crop_receive) .out_receive(crop_receive),
.in_data(crop_data), .in_data(crop_data),
.out_en (out_en), .out_en(out_en),
.in_ready(), .in_ready(in_ready),
.in_receive(), .in_receive(in_receive),
.out_data(data_out) .out_data(out_data)
); );
// RGB_to_RAM write_to_RAM ( // RGB_to_RAM write_to_RAM (
@ -113,11 +117,11 @@ module isp #(
// .in_en(RAM_in_en), // .in_en(RAM_in_en),
// .in_que(RAM_in_que), // .in_que(RAM_in_que),
// .data_in(RAM_in_data), // .in_data(RAM_in_data),
// .write_que(out_que), // .write_que(out_que),
// .write_en(out_en), // .write_en(out_en),
// .data_write(data_out) // .data_write(out_data)
// ); // );
endmodule endmodule

View File

@ -37,7 +37,7 @@ VERILATOR_FLAGS += -sc --exe
# Generate makefile dependencies (not shown as complicates the Makefile) # Generate makefile dependencies (not shown as complicates the Makefile)
#VERILATOR_FLAGS += -MMD #VERILATOR_FLAGS += -MMD
# Optimize # Optimize
# VERILATOR_FLAGS += -x-assign fast VERILATOR_FLAGS += -x-assign fast
# Warn abount lint issues; may not want this on less solid designs # Warn abount lint issues; may not want this on less solid designs
VERILATOR_FLAGS += -Wall VERILATOR_FLAGS += -Wall
# Make waveforms # Make waveforms
@ -45,7 +45,7 @@ VERILATOR_FLAGS += --trace
# Check SystemVerilog assertions # Check SystemVerilog assertions
VERILATOR_FLAGS += --assert VERILATOR_FLAGS += --assert
# Enable multithreading # Enable multithreading
# VERILATOR_FLAGS += --threads 4 VERILATOR_FLAGS += --threads 14
# Generate coverage analysis # Generate coverage analysis
# VERILATOR_FLAGS += --coverage # VERILATOR_FLAGS += --coverage
# Run Verilator in debug mode # Run Verilator in debug mode
@ -56,7 +56,7 @@ VERILATOR_FLAGS += --assert
TOP_MODULE = isp TOP_MODULE = isp
VERILATOR_FLAGS += -top $(TOP_MODULE) VERILATOR_FLAGS += -top $(TOP_MODULE)
# Input files for Verilator # 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) # Check if SC exists via a verilator call (empty if not)
SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC)
@ -64,15 +64,16 @@ SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC)
###################################################################### ######################################################################
ifneq ($(SYSTEMC_EXISTS),) ifneq ($(SYSTEMC_EXISTS),)
default: run default: build run
else else
default: nosc default: nosc
endif endif
run: lint:
@echo @echo "-- Verilator lint check ----"
@echo "-- Verilator tracing example" $(VERILATOR) -sc --lint-only $(VERILATOR_INPUT)
build:
@echo @echo
@echo "-- VERILATE ----------------" @echo "-- VERILATE ----------------"
$(VERILATOR) $(VERILATOR_FLAGS) $(VERILATOR_INPUT) $(VERILATOR) $(VERILATOR_FLAGS) $(VERILATOR_INPUT)
@ -86,17 +87,21 @@ run:
# 3. Or, call a submakefile where we can override the rules ourselves: # 3. Or, call a submakefile where we can override the rules ourselves:
$(MAKE) -j -C obj_dir -f V$(TOP_MODULE).mk $(MAKE) -j -C obj_dir -f V$(TOP_MODULE).mk
run:
@echo @echo
@echo "-- RUN ---------------------" @echo "-- RUN ---------------------"
# @rm -rf logs
# @mkdir -p logs
# obj_dir/V$(TOP_MODULE) +trace
obj_dir/V$(TOP_MODULE) obj_dir/V$(TOP_MODULE)
# @echo # @echo
# @echo "-- COVERAGE ----------------" # @echo "-- COVERAGE ----------------"
# @rm -rf logs/annotated # @rm -rf logs/annotated
# $(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat # $(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
@echo "-- DONE --------------------" @echo "-- DONE --------------------"

View File

@ -5,51 +5,61 @@
#include <systemc> #include <systemc>
// Include common routines // Include common routines
#include <sys/stat.h> // mkdir
#include <verilated.h> #include <verilated.h>
#include <verilated_vcd_sc.h> #include <verilated_vcd_sc.h>
#include <sys/stat.h> // mkdir
// Include model header, generated from Verilating "isp.v" // Include model header, generated from Verilating "isp.v"
#include "Visp.h" #include "Visp.h"
// Handle file // Handle file
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
// math
#include <cmath>
#include "bmp.hpp" #include "bmp.hpp"
#define IN_WIDTH 1936 static const uint16_t IN_WIDTH = 1936;
#define IN_HEIGHT 1088 static const uint16_t IN_HEIGHT = 1088;
#define IN_SIZE (IN_WIDTH * IN_HEIGHT) #define IN_SIZE (IN_WIDTH * IN_HEIGHT)
#define OUT_WIDTH 1920 static const uint16_t OUT_WIDTH = 1920;
#define OUT_HEIGHT 1080 static const uint16_t OUT_HEIGHT = 1080;
#define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT) #define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT)
// const float red_gain = 1.2f; // Adjust these values as necessary struct color_gain
// const float green_gain = 0.5f; {
// const float blue_gain = 0.95f; double red;
double green;
double blue;
}color_gain {1.0, 0.5, 1.1};
using namespace std; using namespace std;
using namespace sc_core; using namespace sc_core;
using namespace sc_dt; using namespace sc_dt;
SC_MODULE (TB_ISP) { SC_MODULE(TB_ISP) {
sc_in_clk clk; sc_in_clk clk;
sc_in<bool> reset; sc_in<bool> reset;
sc_in<bool> data_que; sc_in<bool> in_ready;
sc_out<bool> data_en; sc_in<bool> in_receive;
sc_out<uint32_t> data_out[3]; sc_out<bool> out_en;
sc_out<uint32_t> out_data[3];
sc_in<bool> im_clk; sc_in<bool> im_clk;
sc_in<bool> im_en; sc_in<bool> im_en;
sc_out<bool> out_ready;
sc_out<bool> out_receceive;
sc_in<uint32_t> im_data; sc_in<uint32_t> im_data;
sc_out<bool> is_done; sc_out<bool> is_done;
unique_ptr<uint16_t[]> image = make_unique<uint16_t[]>(IN_SIZE); unique_ptr<uint16_t[]> image = make_unique<uint16_t[]>(IN_SIZE);
unique_ptr<uint32_t[]> out = make_unique<uint32_t[]>(OUT_SIZE); unique_ptr<uint32_t[]> out = make_unique<uint32_t[]>(OUT_SIZE);
SC_CTOR (TB_ISP) { SC_CTOR(TB_ISP) {
SC_CTHREAD(send_Data, clk.pos()); SC_CTHREAD(send_Data, clk.pos());
reset_signal_is(reset, true); reset_signal_is(reset, true);
@ -58,56 +68,63 @@ SC_MODULE (TB_ISP) {
void send_Data(void) { void send_Data(void) {
uint16_t pos_x = 0, pos_y = 0; uint16_t pos_x = 0, pos_y = 0;
while (true) while (true) {
{ if (in_ready.read() && pos_y < IN_HEIGHT - 2) {
if (data_que.read() && pos_y < IN_HEIGHT - 2) { out_en.write(1);
data_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,
printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y, image[( pos_y + 1 ) * IN_WIDTH + pos_x]); image[(pos_y + 0) * 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 + 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]); out_data[0].write(image[(pos_y + 0) * IN_WIDTH + pos_x]);
data_out[1].write(image[( pos_y + 1 ) * IN_WIDTH + pos_x]); out_data[1].write(image[(pos_y + 1) * IN_WIDTH + pos_x]);
data_out[2].write(image[( pos_y + 2 ) * IN_WIDTH + pos_x]); out_data[2].write(image[(pos_y + 2) * IN_WIDTH + pos_x]);
wait(1); // wait(1);
data_en.write(0); // out_en.write(0);
if (++pos_x >= IN_WIDTH) { if (++pos_x >= IN_WIDTH) {
pos_x = 0; pos_x = 0;
pos_y++; pos_y++;
} }
} else { } else {
data_en.write(0); out_en.write(0);
} }
wait(); wait();
} }
} }
void read_Data(void) { void read_Data(void) {
is_done.write(0); is_done.write(0);
uint16_t pos_x = 0, pos_y = 0; uint16_t pos_x = 0, pos_y = 0;
uint32_t last_data = 0; uint32_t last_data = 0;
uint16_t cnt = 0; uint32_t cnt = 0;
while (true) while (true) {
{
if (im_en.read()) { if (im_en.read()) {
out_ready.write(false);
out_receceive.write(true);
out[pos_y * OUT_WIDTH + pos_x] = im_data.read(); out[pos_y * OUT_WIDTH + pos_x] = im_data.read();
if (pos_x++ >= OUT_WIDTH) { if (pos_x++ >= OUT_WIDTH) {
pos_x = 0; pos_x = 0;
pos_y++; 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()) { if (last_data == im_data.read()) {
cnt++; cnt++;
if (cnt >= 10000) { if (cnt >= 100000L) {
is_done.write(1); 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 { } else {
cnt = 0; cnt = 0;
@ -142,13 +159,15 @@ int sc_main(int argc, char* argv[]) {
uint32_t i = 0; uint32_t i = 0;
for (int y = 0; y < IN_HEIGHT; y++) { for (int y = 0; y < IN_HEIGHT; y++) {
for (int x = 0; x < IN_WIDTH; x++) { 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; i += 2;
} }
} }
cout << "Finish Reading data" << endl; 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 // Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs"); Verilated::mkdir("logs");
@ -161,7 +180,8 @@ int sc_main(int argc, char* argv[]) {
// May be overridden by commandArgs argument parsing // May be overridden by commandArgs argument parsing
Verilated::randReset(2); 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); Verilated::traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs // 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 // Define interconnect
sc_signal<bool> reset; sc_signal<bool> reset;
sc_signal<bool> data_en; sc_signal<bool> in_en;
sc_signal<bool> data_que; sc_signal<bool> in_ready;
sc_signal<uint32_t> data_in[3]; sc_signal<bool> in_receive;
sc_signal<uint32_t> in_data[3];
sc_signal<bool> out_clk; sc_signal<bool> out_clk;
sc_signal<bool> out_en; sc_signal<bool> out_en;
sc_signal<uint32_t> data_out; sc_signal<bool> out_ready;
sc_signal<bool> out_receive;
sc_signal<uint32_t> out_data;
sc_signal<bool> color_correction; sc_signal<bool> color_correction;
sc_signal<uint32_t> gain_red;
sc_signal<uint32_t> gain_green;
sc_signal<uint32_t> gain_blue;
sc_signal<bool> flag_done; sc_signal<bool> flag_done;
// Construct the Verilated model, from inside Visp.h // 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<Visp> isp{new Visp{"isp"}}; const std::unique_ptr<Visp> isp{new Visp{"isp"}};
// Attach Visp's signals to this upper model // Attach Visp's signals to this upper model
isp->clk(clk); isp->clk(clk);
isp->reset(reset); isp->reset(reset);
isp->data_en(data_en); isp->in_en(in_en);
isp->data_que(data_que); isp->in_ready(in_ready);
isp->data_in[0](data_in[0]); isp->in_receive(in_receive);
isp->data_in[1](data_in[1]); isp->in_data[0](in_data[0]);
isp->data_in[2](data_in[2]); isp->in_data[1](in_data[1]);
isp->in_data[2](in_data[2]);
isp->out_clk(out_clk); isp->out_clk(out_clk);
isp->out_en(out_en); 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); 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 // Construct testbench module
TB_ISP tb_isp("tb_isp"); TB_ISP tb_isp("tb_isp");
tb_isp.clk(clk); tb_isp.clk(clk);
tb_isp.reset(reset); tb_isp.reset(reset);
tb_isp.data_que(data_que); tb_isp.in_ready(out_ready);
tb_isp.data_en(data_en); tb_isp.in_receive(out_receive);
tb_isp.data_out[0](data_in[0]); tb_isp.out_en(in_en);
tb_isp.data_out[1](data_in[1]); tb_isp.out_ready(in_ready);
tb_isp.data_out[2](data_in[2]); 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_clk(out_clk);
tb_isp.im_en(out_en); 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.is_done(flag_done);
tb_isp.image = move(image); tb_isp.image = move(image);
@ -251,8 +290,7 @@ int sc_main(int argc, char* argv[]) {
reset.write(0); // Deassert reset reset.write(0); // Deassert reset
} }
if (flag_done.read()) if (flag_done.read()) break;
break;
// Simulate 1ns // Simulate 1ns
sc_start(1, SC_NS); sc_start(1, SC_NS);
@ -271,26 +309,27 @@ int sc_main(int argc, char* argv[]) {
cout << "Ready to save raw RGB image" << endl; cout << "Ready to save raw RGB image" << endl;
// for (int y = 0; y < OUT_HEIGHT; y++) // for (int y = 0; y < OUT_HEIGHT; y++)
// for(int x = 0; x < OUT_WIDTH; x++) // 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(); // out_image.close();
// save to image // 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 y = 0; y < OUT_HEIGHT; ++y) {
for (int32_t x = 0; x < OUT_WIDTH; ++x) { for (int32_t x = 0; x < OUT_WIDTH; ++x) {
int32_t index = (y * OUT_WIDTH + x) * 3; int32_t index = (y * OUT_WIDTH + x) * 3;
uint8_t red = ( tb_isp.out[y * OUT_WIDTH + x] & 0x00ff0000 ) >> 16; 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 green = (tb_isp.out[y * OUT_WIDTH + x] & 0x0000ff00) >> 8;
uint8_t blue = ( tb_isp.out[y * OUT_WIDTH + x] & 0x000000ff ); uint8_t blue = (tb_isp.out[y * OUT_WIDTH + x] & 0x000000ff);
out_image.write((const char *)&red, sizeof(red)); out_image.write((const char*)&red, sizeof(red));
out_image.write((const char *)&green, sizeof(green)); out_image.write((const char*)&green, sizeof(green));
out_image.write((const char *)&blue, sizeof(blue)); 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 + 0] = red; // R
data[index + 1] = green; // G data[index + 1] = green; // G