From 536bb715b1c98e565c56002dbbb51fa0b16e9753 Mon Sep 17 00:00:00 2001 From: SelfConfusion <1822250894@qq.com> Date: Thu, 9 May 2024 22:56:32 +0800 Subject: [PATCH] finish and test CFA --- .gitignore | 2 + CFA/cfa.v | 12 --- CFA/demosaic.v | 252 +++++++++++++++++++++++++++++++++++++++++++++++++ isp.v | 9 ++ 4 files changed, 263 insertions(+), 12 deletions(-) create mode 100644 .gitignore delete mode 100644 CFA/cfa.v create mode 100644 CFA/demosaic.v diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2f290a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/CFA/sim/** +!/CFA/sim/demosaic.v \ No newline at end of file diff --git a/CFA/cfa.v b/CFA/cfa.v deleted file mode 100644 index d6b1502..0000000 --- a/CFA/cfa.v +++ /dev/null @@ -1,12 +0,0 @@ -`timescale 1 ns / 1 ps -`default_nettype none - -module cfa -#( - parameter IM_WIDTH = 1936; - parameter IM_HEIGHT = 1088; -)( - -); - -endmodule \ No newline at end of file diff --git a/CFA/demosaic.v b/CFA/demosaic.v new file mode 100644 index 0000000..f0ee3f6 --- /dev/null +++ b/CFA/demosaic.v @@ -0,0 +1,252 @@ +module demosaic(clk, reset, in_en, data_in, wr_r, addr_r, wdata_r, rdata_r, wr_g, addr_g, wdata_g, rdata_g, wr_b, addr_b, wdata_b, rdata_b, done); +input clk; +input reset; +input in_en; +input [7:0] data_in; +output reg wr_r; +output reg [13:0] addr_r; +output reg [7:0] wdata_r; +input [7:0] rdata_r; +output reg wr_g; +output reg [13:0] addr_g; +output reg [7:0] wdata_g; +input [7:0] rdata_g; +output reg wr_b; +output reg [13:0] addr_b; +output reg [7:0] wdata_b; +input [7:0] rdata_b; +output reg done; + +// Register +reg [1:0] bilinearCase; +reg [2:0] state, nextState; +reg [3:0] counter9; +reg [6:0] caseCounter, round; +reg [7:0] data [8:0]; +reg [7:0] red, blue, green; +reg [14:0] counter, biCounter; // bicounter store the center address + +// State parameter +localparam READDATA = 0; // Read data, then wirte to wdata +localparam COLOR = 1; // Choose the case of color +localparam STORE9 = 2; // Store 9 element to register data +localparam BILINEAR = 3; // Bilinear Interpolation +localparam WRITEDATA = 4; // Write data to memory +localparam FINISH = 5; // Done + +// State control +always @(posedge clk or posedge reset) begin + if(reset) + state <= READDATA; + else + state <= nextState; +end + +//next state logic +always @(*) begin + case (state) + READDATA: nextState = (counter == 15'd16384)? COLOR : READDATA; + COLOR: nextState = STORE9; + STORE9: nextState = (counter9 == 4'd9)? BILINEAR : STORE9; + BILINEAR: nextState = WRITEDATA; + WRITEDATA: nextState = (biCounter == 15'd16257)? FINISH : COLOR; + FINISH: nextState = FINISH; + default: nextState = READDATA; + endcase +end + +always @(posedge clk or posedge reset) begin + if (reset) begin + done <= 1'd0; + wr_r <= 1'd0; + wr_g <= 1'd0; + wr_b <= 1'd0; + bilinearCase <= 2'd0; + counter9 <= 4'd0; + caseCounter <= 7'd0; + round <= 7'd0; + red <= 9'd0; + blue <= 9'd0; + green <= 9'd0; + addr_r <= 14'd0; + addr_g <= 14'd0; + addr_b <= 14'd0; + biCounter <= 15'd129; + counter <= 15'd0; + end + else begin + case (state) + READDATA: begin + if(in_en) begin + wr_r <= 1'd1; + wr_g <= 1'd1; + wr_b <= 1'd1; + addr_r <= counter; + addr_g <= counter; + addr_b <= counter; + wdata_r <= data_in; + wdata_g <= data_in; + wdata_b <= data_in; + counter <= counter + 1; + end + end + + COLOR: begin + wr_r <= 1'd0; + wr_g <= 1'd0; + wr_b <= 1'd0; + + if(!(round & 1)) begin // Even round, 0,2,4,6,8,... + if(!(caseCounter & 1)) // Even case, 0,2,4,6,8,... + bilinearCase <= 2'd0; + else // Odd case, 1,3,5,7,9,... + bilinearCase <= 2'd1; + end + else begin // Odd round, 1,3,5,7,9,... + if(!(caseCounter & 1)) // Even case, 0,2,4,6,8,... + bilinearCase <= 2'd2; + else // Odd case, 1,3,5,7,9,... + bilinearCase <= 2'd3; + end + caseCounter <= caseCounter + 7'd1; + end + + STORE9: begin + wr_r <= 1'd0; + wr_g <= 1'd0; + wr_b <= 1'd0; + + /* + * I use R,G,B memory to store pattern data. when in case 0(the middle color is green), I will update the missing blue and red data to memory. + * In next turn is case 1(the middle color is blue). It will use previous data, but the blue and red data are changed in previous turn. So the + * previous green data is the origin data. + */ + if(counter9 > 4'd0) begin + case (bilinearCase) + 0: begin + case (counter9) + 2: data[counter9 - 1] <= rdata_r; + 4: data[counter9 - 1] <= rdata_b; + default: data[counter9 - 1] <= rdata_g; + endcase + end + 1: begin + case (counter9) + 1,3: data[counter9 - 1] <= rdata_r; + 2,4: data[counter9 - 1] <= rdata_g; + default: data[counter9 - 1] <= rdata_b; + endcase + end + 2: begin + case (counter9) + 1,3: data[counter9 - 1] <= rdata_b; + 2,4: data[counter9 - 1] <= rdata_g; + default: data[counter9 - 1] <= rdata_r; + endcase + end + 3: begin + case (counter9) + 2: data[counter9 - 1] <= rdata_b; + 4: data[counter9 - 1] <= rdata_r; + default: data[counter9 - 1] <= rdata_g; + endcase + end + endcase + end + counter9 <= counter9 + 4'd1; + + case (counter9) // For y axis (row) + 0,1,2: begin + addr_g[13:7] <= biCounter[13:7] - 7'd1; + addr_r[13:7] <= biCounter[13:7] - 7'd1; + addr_b[13:7] <= biCounter[13:7] - 7'd1; + end + 3,4,5: begin + addr_g[13:7] <= biCounter[13:7]; + addr_r[13:7] <= biCounter[13:7]; + addr_b[13:7] <= biCounter[13:7]; + end + 6,7,8: begin + addr_g[13:7] <= biCounter[13:7] + 7'd1; + addr_r[13:7] <= biCounter[13:7] + 7'd1; + addr_b[13:7] <= biCounter[13:7] + 7'd1; + end + endcase + + case (counter9) // For x axis (col) + 0,3,6: begin + addr_g[6:0] <= biCounter[6:0] - 7'd1; + addr_r[6:0] <= biCounter[6:0] - 7'd1; + addr_b[6:0] <= biCounter[6:0] - 7'd1; + end + 1,4,7: begin + addr_g[6:0] <= biCounter[6:0]; + addr_r[6:0] <= biCounter[6:0]; + addr_b[6:0] <= biCounter[6:0]; + end + 2,5,8: begin + addr_g[6:0] <= biCounter[6:0] + 7'd1; + addr_r[6:0] <= biCounter[6:0] + 7'd1; + addr_b[6:0] <= biCounter[6:0] + 7'd1; + end + endcase + end + + BILINEAR: begin + // 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 (bilinearCase) + 0: begin // Missing B, R on G + red <= (data[1] + data[7]) / 2; + blue <= (data[3] + data[5]) / 2; + green <= data[4]; + end + + 1: begin // Missing G, R on B + green <= (data[1] + data[3] + data[5] + data[7]) / 4; + red <= (data[0] + data[2] + data[6] + data[8]) / 4; + blue <= data[4]; + end + + 2: begin // Missing G, B on R + green <= (data[1] + data[3] + data[5] + data[7]) / 4; + blue <= (data[0] + data[2] + data[6] + data[8]) / 4; + red <= data[4]; + end + + 3: begin // Missing B, R on G + blue <= (data[1] + data[7]) / 2; + red <= (data[3] + data[5]) / 2; + green <= data[4]; + end + endcase + end + + WRITEDATA: begin + wr_r <= 1'd1; + wr_g <= 1'd1; + wr_b <= 1'd1; + addr_r <= biCounter; + addr_g <= biCounter; + addr_b <= biCounter; + wdata_r <= red; + wdata_g <= green; + wdata_b <= blue; + if(caseCounter == 7'd126) begin // Finish one row, then initialize the caseCounter + caseCounter <= 7'd0; + round <= round + 7'd1; + biCounter <= biCounter + 15'd3; // Skip the edge + end + else + biCounter <= biCounter + 15'd1; + end + + FINISH: begin + done <= 1'd1; + end + endcase + end +end +endmodule \ No newline at end of file diff --git a/isp.v b/isp.v index e69de29..a02d740 100644 --- a/isp.v +++ b/isp.v @@ -0,0 +1,9 @@ +`timescale 1ns/1ps + +module isp #( + parameters +) ( + ports +); + +endmodule \ No newline at end of file