ISP/Demosaic/demosaic2.v

166 lines
5.9 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module demosaic2 #(
parameter IM_WIDTH = 512, // 图像宽度
parameter IM_HEIGHT = 256, // 图像高度
parameter RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg
parameter DATA_SIZE = 16,
)(
// 基本信号
input clk,
input reset,
// 数据输入信号
input data_en,
input [DATA_SIZE - 1:0] data_in [2:0], // 数据输入线0、1、2分别表示第一、二、三行
output reg data_que, // 数据请求线,高电平:请求三个数据,直到读取完才拉低
output reg data_line, // 新一行请求数据线,高电平:请求九个数据,直到读取完才拉低
// en: 输出数据有效信号,高电平有效
output reg out_en,
output reg [DATA_SIZE - 1:0] out_r,
output reg [DATA_SIZE - 1:0] out_g,
output reg [DATA_SIZE - 1:0] out_b
);
// 常量,包括状态机
// localparam IM_SIZE = IM_HEIGHT * IM_WIDTH;
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;
if (pos_y >= IM_HEIGHT - 2)
pos_y <= 0;
end
else begin
cnt_data <= 2;
// 窗口右移
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];
end
end
endcase
end
end
endmodule