update scaler and RAM

This commit is contained in:
SikongJueluo
2024-05-11 21:53:35 +08:00
parent f3f01c1c51
commit c96e9b57b2
20 changed files with 1393 additions and 72 deletions

259
Demosaic/demosaic.v Normal file
View File

@@ -0,0 +1,259 @@
module demosaic #(
parameter IM_WIDTH = 512,
parameter IM_HEIGHT = 256
)(
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
);
parameter IM_SIZE = IM_HEIGHT * IM_WIDTH;
// Register
reg [1:0] bilinearCase;
reg [2:0] state, nextState;
reg [3:0] counter9;
reg [6:0] round;
reg [11:0] caseCounter;
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 == IM_SIZE)? COLOR : READDATA;
COLOR: nextState = STORE9;
STORE9: nextState = (counter9 == 4'd9)? BILINEAR : STORE9;
BILINEAR: nextState = WRITEDATA;
WRITEDATA: nextState = (biCounter == ( IM_SIZE - IM_WIDTH + 1 ))? 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 == ( IM_WIDTH - 2 )) 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

165
Demosaic/demosaic2.v Normal file
View File

@@ -0,0 +1,165 @@
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], // 数据输入线012分别表示第一三行
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

169
Demosaic/sim/tb_demosaic.v Normal file
View File

@@ -0,0 +1,169 @@
`timescale 1ns/10ps
`define End_CYCLE 100000000
`define cycle 40.0
`define PAT "./test.dat"
`define OUT_F "./test.raw"
module tb_demosaic();
parameter WIDTH = 512;
parameter HEIGHT = 256;
parameter IMG_SIZE = WIDTH * HEIGHT;
integer out_f, i, in_count, cycle_count;
reg clk;
reg reset;
reg in_en;
reg flag;
wire wr_r, wr_g, wr_b;
wire done;
wire [13:0] addr_r, addr_g, addr_b;
wire [7:0] wdata_r, wdata_g, wdata_b;
reg [7:0] pixel, rdata_r, rdata_g, rdata_b;
reg [7:0] PAT [0:IMG_SIZE-1];
reg [7:0] MEM_R [0:IMG_SIZE-1];
reg [7:0] MEM_G [0:IMG_SIZE-1];
reg [7:0] MEM_B [0:IMG_SIZE-1];
demosaic #(
WIDTH,
HEIGHT
) u_demosaic (
.clk(clk),
.reset(reset),
.in_en(in_en),
.data_in(pixel),
.wr_r(wr_r),
.addr_r(addr_r),
.wdata_r(wdata_r),
.rdata_r(rdata_r),
.wr_g(wr_g),
.addr_g(addr_g),
.wdata_g(wdata_g),
.rdata_g(rdata_g),
.wr_b(wr_b),
.addr_b(addr_b),
.wdata_b(wdata_b),
.rdata_b(rdata_b),
.done(done)
);
initial begin
out_f = $fopen(`OUT_F, "wb");
end
initial begin
$readmemh(`PAT, PAT);
end
initial begin
clk = 0;
reset = 0;
in_en = 0;
in_count = 0;
cycle_count = 0;
pixel = 'hx;
rdata_r = 'hx;
rdata_g = 'hx;
rdata_b = 'hx;
flag = 0;
for(i = 0; i < IMG_SIZE; i = i + 1) begin
MEM_R[i] = 0;
MEM_G[i] = 0;
MEM_B[i] = 0;
end
end
always #(`cycle/2) clk = ~clk;
initial begin
$display("********************************************************************");
$display("** Simulation Start **");
$display("********************************************************************");
@(posedge clk); #2 reset = 1'b1;
#(`cycle*2);
@(posedge clk); #2 reset = 1'b0;
end
initial begin
@(posedge clk);
# (`cycle*3) flag = 1;
end
always @ (negedge clk or posedge reset) begin // send mosaic image
if(reset) begin
pixel <= 0;
in_en <= 0;
end
else begin
if(flag) begin
if(in_count <= IMG_SIZE-1) begin
in_en <= 1;
in_count <= in_count + 1;
pixel <= PAT[in_count];
end
else begin
in_en <= 0;
pixel <= 'hx;
end
end
end
end
always @ (negedge clk) begin // read memory, send data to module
if(!wr_r)
rdata_r <= MEM_R[addr_r];
else
rdata_r <= 'hx;
if(!wr_g)
rdata_g <= MEM_G[addr_g];
else
rdata_g <= 'hx;
if(!wr_b)
rdata_b <= MEM_B[addr_b];
else
rdata_b <= 'hx;
end
always @ (negedge clk) begin // write memory, read data and save
if(wr_r) begin
MEM_R[addr_r] <= wdata_r;
end
if(wr_g) begin
MEM_G[addr_g] <= wdata_g;
end
if(wr_b) begin
MEM_B[addr_b] <= wdata_b;
end
end
always @ (posedge clk) begin // count cycle
cycle_count <= cycle_count + 1;
if(cycle_count >= `End_CYCLE) begin
$display("********************************************************************");
$display("** Fail waiting done signal **");
$display("** You can increase END_CYCLE by yourself **");
$display("********************************************************************");
$finish;
end
end
always @ (posedge clk) begin // check result
if(done) begin
for(i = 0; i < IMG_SIZE; i = i + 1) begin
$fwrite(out_f, "%c", MEM_R[i]);
$fwrite(out_f, "%c", MEM_G[i]);
$fwrite(out_f, "%c", MEM_B[i]);
end
$fclose(out_f);
$display("********************************************************************");
$display("** Simulation completed successfully! **");
$display("********************************************************************");
$finish;
end
end
endmodule

262144
Demosaic/sim/test.dat Normal file

File diff suppressed because it is too large Load Diff

0
Demosaic/sim/test.raw Normal file
View File

Binary file not shown.

View File

@@ -0,0 +1,19 @@
import imageio
import numpy as np
cut_width = 512
cut_height = 256
if __name__ == '__main__':
txt = open('./test.dat', 'w')
image = imageio.imread_v2('./im.tif')
print(image.shape)
cut = image[0:cut_height, 0:cut_width]
print(cut.shape)
cut = np.array(cut, dtype=np.int16)
for data in list(cut.flatten()):
txt.write('%02x\n%02x\n' % (data & 0x00ff, (data & 0xff00) >> 4))
txt.close()
imageio.imsave('./test.tif', cut)

View File

@@ -0,0 +1,10 @@
import imageio
import numpy as np
im_width = 1936
im_height = 1088
if __name__ == '__main__':
raw = np.fromfile('./test.raw', dtype=np.int8)
image = raw.reshape((im_height, im_width))
imageio.imsave("./test.tif", image)

262144
Demosaic/sim/transform/test.dat Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.