module demosaic2 #( 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 ) ( // 基本信号 input clk, input reset, // 数据输入信号 input in_en, input [DATA_SIZE - 1:0] in_data [2], // 数据输入线,0、1、2分别表示第一、二、三行 output out_ready, // 数据请求线,高电平:请求三个数据,直到读取完才拉低 output out_receive, // en: 输出数据有效信号,高电平有效 input in_ready, input in_receive, output 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 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 end 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 end default: ; endcase end end endmodule