ISP/CFA/demosaic2.v

165 lines
5.8 KiB
Coq
Raw Normal View History

2024-05-10 20:13:58 +08:00
module demosaic2 #(
parameter IM_WIDTH = 512, // 图像宽度
parameter IM_HEIGHT = 256, // 图像高度
parameter RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg
)(
// 基本信号
input clk,
input reset,
// 数据输入信号
input data_en,
input [15:0] data_in [2:0], // 数据输入线012分别表示第一三行
output reg data_que, // 数据请求线高电平请求三个数据直到读取完才拉低
output reg data_line, // 新一行请求数据线高电平请求九个数据直到读取完才拉低
// en: 输出数据有效信号高电平有效
output reg out_en,
output reg [15:0] out_r,
output reg [15:0] out_g,
output reg [15:0] out_b
);
// 常量包括状态机
2024-05-10 21:41:47 +08:00
// localparam IM_SIZE = IM_HEIGHT * IM_WIDTH;
2024-05-10 20:13:58 +08:00
localparam READ_DATA = 0;
localparam COLOR_GEN = 1;
localparam WRITE_DATA = 2;
localparam SLIDE_WINDOW = 3;
// 寄存器
reg [2:0] state, nextState;
reg [15:0] data_cache [2:0][2:0]; // 缓存颜色数据行列3x3
reg [11:0] pos_x, pos_y; // 滑动窗口左上角位置
reg [1: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 @(*) begin
case (state)
// 记录够3x3个数据后进行rgb转换
READ_DATA: nextState = (cnt_data >= 3) ? COLOR_GEN : READ_DATA;
COLOR_GEN: nextState = WRITE_DATA;
WRITE_DATA: nextState = SLIDE_WINDOW;
SLIDE_WINDOW: nextState = READ_DATA;
endcase
end
// 各状态执行的操作
always @(posedge clk or posedge reset) begin
if (reset) begin
// 外部输出初始化
out_en <= 0;
out_r <= 0;
out_g <= 0;
out_r <= 0;
data_que <= 0;
data_line <= 1;
// 内部寄存器初始化
pos_x <= 0;
pos_y <= 0;
cnt_data <= 0;
raw_type <= RAW_TYPE;
end
else begin
// 状态机执行
case (state)
// 读取数据
READ_DATA: begin
data_que <= 1;
if (cnt_data < 2)
data_line <= 1;
if (data_en) begin
data_cache[cnt_data][0] <= data_in[0];
data_cache[cnt_data][1] <= data_in[1];
data_cache[cnt_data][2] <= data_in[2];
cnt_data <= cnt_data + 1;
end
end
COLOR_GEN: begin
// 取消数据请求
data_que <= 0;
data_line <= 0;
// 生成rgb图像
case (raw_type)
0: 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
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
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
endcase
raw_type <= raw_type + 1;
end
WRITE_DATA: begin
out_en <= 1;
out_r <= red;
out_b <= blue;
out_g <= green;
end
SLIDE_WINDOW: begin
// 恢复相关寄存器变量
out_en <= 0;
// 记录位置寄存器自增并处理缓存数据
pos_x <= pos_x + 1;
if (pos_x >= IM_WIDTH - 2) begin
cnt_data <= 0;
pos_x <= 0;
pos_y <= pos_y + 1;
2024-05-10 21:41:47 +08:00
if (pos_y >= IM_HEIGHT - 2)
pos_y <= 0;
2024-05-10 20:13:58 +08:00
end
else begin
cnt_data <= 2;
// 窗口右移
2024-05-10 21:41:47 +08:00
data_cache[0][0] <= data_cache[0][1];
data_cache[1][0] <= data_cache[1][1];
data_cache[2][0] <= data_cache[2][1];
data_cache[0][1] <= data_cache[0][2];
data_cache[1][1] <= data_cache[1][2];
data_cache[2][1] <= data_cache[2][2];
2024-05-10 20:13:58 +08:00
end
end
endcase
end
end
endmodule