2024-05-10 20:13:58 +08:00
|
|
|
|
module demosaic2 #(
|
2024-06-27 21:52:46 +08:00
|
|
|
|
parameter reg [16:0] IM_WIDTH = 512, // 图像宽度
|
|
|
|
|
parameter reg [16:0] IM_HEIGHT = 256, // 图像高度
|
|
|
|
|
parameter reg [1:0] RAW_TYPE = 3, // 0:grbg 1:rggb 2:bggr 3:gbrg
|
|
|
|
|
parameter reg [5:0] DATA_SIZE = 16
|
|
|
|
|
) (
|
2024-05-10 20:13:58 +08:00
|
|
|
|
// 基本信号
|
|
|
|
|
input clk,
|
|
|
|
|
input reset,
|
|
|
|
|
|
|
|
|
|
// 数据输入信号
|
2024-06-27 21:52:46 +08:00
|
|
|
|
input in_en,
|
|
|
|
|
input [DATA_SIZE - 1:0] in_data [2], // 数据输入线,0、1、2分别表示第一、二、三行
|
|
|
|
|
output out_ready, // 数据请求线,高电平:请求三个数据,直到读取完才拉低
|
|
|
|
|
output out_receive,
|
2024-05-10 20:13:58 +08:00
|
|
|
|
|
|
|
|
|
// en: 输出数据有效信号,高电平有效
|
2024-06-27 21:52:46 +08:00
|
|
|
|
input in_ready,
|
|
|
|
|
input in_receive,
|
|
|
|
|
output out_en,
|
2024-05-11 21:53:35 +08:00
|
|
|
|
output reg [DATA_SIZE - 1:0] out_r,
|
|
|
|
|
output reg [DATA_SIZE - 1:0] out_g,
|
|
|
|
|
output reg [DATA_SIZE - 1:0] out_b
|
2024-05-10 20:13:58 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
2024-06-27 21:52:46 +08:00
|
|
|
|
// 常量,包括状态机
|
|
|
|
|
// localparam IM_SIZE = IM_HEIGHT * IM_WIDTH;
|
|
|
|
|
localparam READ_DATA = 0;
|
|
|
|
|
localparam COLOR_GEN = 1;
|
|
|
|
|
localparam SEND_DATA = 2;
|
|
|
|
|
localparam SLIDE_WINDOW = 3;
|
|
|
|
|
|
|
|
|
|
// 寄存器
|
|
|
|
|
reg [2:0] state, nextState;
|
|
|
|
|
reg [15:0] data_cache[2][2]; // 缓存颜色数据,行列3x3
|
|
|
|
|
reg [11:0] pos_x, pos_y; // 滑动窗口左上角位置
|
|
|
|
|
reg [2:0] cnt_data; // 记录输入数据数量,最大值256
|
|
|
|
|
reg [1:0] raw_type;
|
|
|
|
|
reg [15:0] red, blue, green;
|
|
|
|
|
|
|
|
|
|
// 三段状态机实现,窗口滑动,颜色计算
|
|
|
|
|
// 状态切换
|
|
|
|
|
always @(posedge clk or posedge reset) begin
|
|
|
|
|
if (reset) state <= READ_DATA;
|
|
|
|
|
else state <= nextState;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
// 下一状态更新
|
|
|
|
|
always @(state or cnt_data) begin
|
|
|
|
|
case (state)
|
|
|
|
|
// 记录够3x3个数据后,进行rgb转换
|
|
|
|
|
READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA;
|
|
|
|
|
COLOR_GEN: nextState = SEND_DATA;
|
|
|
|
|
SEND_DATA: nextState = (in_receive) ? SLIDE_WINDOW : SEND_DATA;
|
|
|
|
|
SLIDE_WINDOW: nextState = READ_DATA;
|
|
|
|
|
default: nextState = 0;
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
// 请求数据
|
|
|
|
|
assign out_ready = (cnt_data <= 2 && !in_en && state == READ_DATA) ? 1 : 0;
|
|
|
|
|
// 收到数据
|
|
|
|
|
assign out_receive = (in_en && state == READ_DATA) ? 1 : 0;
|
|
|
|
|
// 发送数据有效位
|
|
|
|
|
assign out_en = (in_ready && state == SEND_DATA) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
// 各状态执行的操作
|
|
|
|
|
always @(posedge clk or posedge reset) begin
|
|
|
|
|
if (reset) begin
|
|
|
|
|
// 外部输出初始化
|
|
|
|
|
out_en <= 0;
|
|
|
|
|
out_r <= 0;
|
|
|
|
|
out_g <= 0;
|
|
|
|
|
out_r <= 0;
|
|
|
|
|
|
|
|
|
|
// 内部寄存器初始化
|
|
|
|
|
pos_x <= 0;
|
|
|
|
|
pos_y <= 0;
|
|
|
|
|
cnt_data <= 0;
|
|
|
|
|
raw_type <= RAW_TYPE;
|
|
|
|
|
end else begin
|
|
|
|
|
// 状态机执行
|
|
|
|
|
case (state)
|
|
|
|
|
// 读取数据
|
|
|
|
|
READ_DATA: begin
|
|
|
|
|
if (in_en) begin
|
|
|
|
|
data_cache[cnt_data][0] <= in_data[0];
|
|
|
|
|
data_cache[cnt_data][1] <= in_data[1];
|
|
|
|
|
data_cache[cnt_data][2] <= in_data[2];
|
|
|
|
|
|
|
|
|
|
cnt_data <= cnt_data + 1;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
COLOR_GEN: begin
|
|
|
|
|
// 生成rgb图像
|
|
|
|
|
// data case 0 case 1 case 2 case 3
|
|
|
|
|
// 0 1 2 G R G R G R B G B G B G
|
|
|
|
|
// 3 4 5 B G B G B G G R G R G R
|
|
|
|
|
// 6 7 8 G R G R G R B G B G B G
|
|
|
|
|
case (raw_type)
|
|
|
|
|
0: begin // Missing B, R on G
|
|
|
|
|
blue <= (data_cache[0][1] + data_cache[2][1]) / 2;
|
|
|
|
|
red <= (data_cache[1][0] + data_cache[1][2]) / 2;
|
|
|
|
|
green <= data_cache[1][1];
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
1: begin // Missing G, R on B
|
|
|
|
|
green <= (data_cache[0][1] + data_cache[1][0] + data_cache[1][2] + data_cache[2][1]) / 4;
|
|
|
|
|
red <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4;
|
|
|
|
|
blue <= data_cache[1][1];
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
2: begin // Missing G, B on R
|
|
|
|
|
green <= (data_cache[0][1] + data_cache[1][0] + data_cache[1][2] + data_cache[2][1]) / 4;
|
|
|
|
|
blue <= (data_cache[0][0] + data_cache[0][2] + data_cache[2][0] + data_cache[2][2]) / 4;
|
|
|
|
|
red <= data_cache[1][1];
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3: begin // Missing B, R on G
|
|
|
|
|
red <= (data_cache[0][1] + data_cache[2][1]) / 2;
|
|
|
|
|
blue <= (data_cache[1][0] + data_cache[1][2]) / 2;
|
|
|
|
|
green <= data_cache[1][1];
|
|
|
|
|
end
|
|
|
|
|
default: ;
|
|
|
|
|
endcase
|
|
|
|
|
|
|
|
|
|
case (raw_type)
|
|
|
|
|
0: raw_type <= 1;
|
|
|
|
|
1: raw_type <= 0;
|
|
|
|
|
2: raw_type <= 3;
|
|
|
|
|
3: raw_type <= 2;
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
SEND_DATA: begin
|
|
|
|
|
if (in_ready) begin
|
|
|
|
|
out_r <= red;
|
|
|
|
|
out_b <= blue;
|
|
|
|
|
out_g <= green;
|
|
|
|
|
end
|
2024-05-10 20:13:58 +08:00
|
|
|
|
end
|
2024-06-27 21:52:46 +08:00
|
|
|
|
|
|
|
|
|
SLIDE_WINDOW: begin
|
|
|
|
|
// 记录位置寄存器自增,并处理缓存数据
|
|
|
|
|
pos_x <= pos_x + 1;
|
|
|
|
|
if (pos_x >= IM_WIDTH - 2 - 1) begin
|
|
|
|
|
cnt_data <= 0;
|
|
|
|
|
pos_x <= 0;
|
|
|
|
|
pos_y <= pos_y + 1;
|
|
|
|
|
if (pos_y >= IM_HEIGHT - 2 - 1) begin
|
|
|
|
|
pos_y <= 0;
|
|
|
|
|
end
|
|
|
|
|
// 换行后切换Bayer格式
|
|
|
|
|
if (pos_y % 2 == 1) begin
|
|
|
|
|
raw_type <= RAW_TYPE;
|
|
|
|
|
end else begin
|
|
|
|
|
case (RAW_TYPE)
|
|
|
|
|
0: raw_type <= 2;
|
|
|
|
|
1: raw_type <= 3;
|
|
|
|
|
2: raw_type <= 0;
|
|
|
|
|
3: raw_type <= 1;
|
|
|
|
|
default: ;
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
end else begin
|
|
|
|
|
cnt_data <= 2;
|
|
|
|
|
|
|
|
|
|
// 窗口右移
|
|
|
|
|
data_cache[0][0] <= data_cache[1][0];
|
|
|
|
|
data_cache[0][1] <= data_cache[1][1];
|
|
|
|
|
data_cache[0][2] <= data_cache[1][2];
|
|
|
|
|
data_cache[1][0] <= data_cache[2][0];
|
|
|
|
|
data_cache[1][1] <= data_cache[2][1];
|
|
|
|
|
data_cache[1][2] <= data_cache[2][2];
|
|
|
|
|
end
|
2024-05-10 20:13:58 +08:00
|
|
|
|
end
|
2024-06-27 21:52:46 +08:00
|
|
|
|
|
|
|
|
|
default: ;
|
|
|
|
|
endcase
|
|
|
|
|
end
|
|
|
|
|
end
|
2024-05-10 20:13:58 +08:00
|
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
|
|