Files
IPA/rtl/data_cache/data_cache.v

470 lines
20 KiB
Coq
Raw Normal View History

2025-08-26 16:53:22 +08:00
module data_cache #(
// 异步FIFO参数IR系统时钟域
parameter ASYNC_FIFO_DEPTH = 1024, // 异步FIFO深度
parameter ASYNC_FIFO_DATA_W = 27, // 27bit=1(ir_valid)+1(ir_vs)+1(ir_hs)+8(ch0)+8(ch1)+8(ch2)
// 同步FIFO参数系统时钟域256bit数据缓存
parameter SYNC_FIFO_DEPTH = 2048, // 同步FIFO深度适配256x256图像
parameter SYNC_FIFO_DATA_W = 256, // 同步FIFO数据位宽AXI写数据位宽
// 直方图RAM参数1x256每个通道1个
parameter HIST_RAM_DEPTH = 256, // 直方图RAM深度0~255对应8bit像素值
parameter HIST_RAM_DATA_W = 1, // 直方图RAM数据位宽1bit存在标记
// AXI参数
parameter AXI_ID_W = 8, // AXI AW/W ID位宽
parameter AXI_ADDR_W = 32, // AXI地址位宽
parameter AXI_DATA_W = 256, // AXI数据位宽与SYNC_FIFO_DATA_W一致
parameter AXI_STRB_W = AXI_DATA_W / 8 // AXI WSTRB位宽32bit
) (
// -------------------------- Common 端口 --------------------------
input wire clk, // 系统时钟AXI/控制逻辑时钟
input wire rst_n, // 系统复位低有效同步clk
// -------------------------- 配置信号端口 --------------------------
input wire ipa_en, // IPA总使能
input wire update_src_trig, // 更新原始图像触发高有效
input wire input_pixel_type, // 输入像素类型0=Gray1=RGB
input wire [15:0] src_pixel_height, // 原始图像高度
input wire [15:0] src_pixel_width, // 原始图像宽度
input wire [15:0] histogram_low_num, // 直方图低位数计算min用
input wire [15:0] histogram_high_num, // 直方图高位数计算max用
output reg src_image_cache_done, // 原始图像缓存完成高有效
// -------------------------- 连接Windowed模块端口 --------------------------
output reg [7:0] dwidth_conv_min_ch0, // CH0归一化min值
output reg [7:0] dwidth_conv_max_ch0, // CH0归一化max值
output reg [7:0] dwidth_conv_min_ch1, // CH1归一化min值
output reg [7:0] dwidth_conv_max_ch1, // CH1归一化max值
output reg [7:0] dwidth_conv_min_ch2, // CH2归一化min值
output reg [7:0] dwidth_conv_max_ch2, // CH2归一化max值
// -------------------------- IR图像输入端口IR时钟域 --------------------------
input wire ir_clk, // IR像素同步时钟
input wire ir_valid, // IR像素有效信号
input wire ir_vs, // IR垂直同步帧起始
input wire ir_hs, // IR水平同步行起始
input wire [7:0] ir_ch0, // IR CH0数据Gray时有效
input wire [7:0] ir_ch1, // IR CH1数据RGB时有效
input wire [7:0] ir_ch2, // IR CH2数据RGB时有效
// -------------------------- AXI写总线端口系统时钟域 --------------------------
output reg [AXI_ID_W-1:0] axi_m_awid, // AXI AW通道ID
output reg [AXI_ADDR_W-1:0] axi_m_awaddr, // AXI AW通道地址SRAM起始地址
output reg [3:0] axi_m_awlen, // AXI AW通道突发长度0=1拍
output reg [2:0] axi_m_awsize, // AXI AW通道数据宽度5=32字节=256bit
output reg [1:0] axi_m_awburst, // AXI AW通道突发类型0=INCR
output reg axi_m_awlock, // AXI AW通道锁定0=普通
output reg [3:0] axi_m_awcache, // AXI AW通道缓存属性0=非缓存
output reg [2:0] axi_m_awprot, // AXI AW通道保护属性0=普通
output reg [3:0] axi_m_awqos, // AXI AW通道QoS0=默认
output reg axi_m_awvalid, // AXI AW通道有效
input wire axi_m_awready, // AXI AW通道就绪
output reg [AXI_ID_W-1:0] axi_m_wid, // AXI W通道ID与AW一致
output reg [AXI_DATA_W-1:0] axi_m_wdata, // AXI W通道数据256bit
output reg [AXI_STRB_W-1:0] axi_m_wstrb, // AXI W通道字节使能全1=有效
output reg axi_m_wlast, // AXI W通道突发结束标记
output reg axi_m_wvalid, // AXI W通道有效
input wire axi_m_wready, // AXI W通道就绪
input wire [AXI_ID_W-1:0] axi_m_bid, // AXI B通道ID
input wire [1:0] axi_m_bresp, // AXI B通道响应0=OKAY
input wire axi_m_bvalid, // AXI B通道有效
output reg axi_m_bready // AXI B通道就绪
);
// -------------------------- 内部信号定义 --------------------------
// 1. 复位同步跨时钟域复位处理
wire rst_n_ir; // IR时钟域同步后的复位
wire rst_n_sys; // 系统时钟域同步后的复位
// 2. 异步FIFO信号IR系统时钟域
wire async_fifo_wr_en; // 异步FIFO写使能IR时钟域
wire [ASYNC_FIFO_DATA_W-1:0] async_fifo_wr_data; // 异步FIFO写数据IR时钟域
wire async_fifo_full; // 异步FIFO满IR时钟域
wire async_fifo_rd_en; // 异步FIFO读使能系统时钟域
wire [ASYNC_FIFO_DATA_W-1:0] async_fifo_rd_data; // 异步FIFO读数据系统时钟域
wire async_fifo_empty; // 异步FIFO空系统时钟域
// 3. 跨域后像素信号系统时钟域
wire ir_valid_sys; // 跨域后像素有效
wire ir_vs_sys; // 跨域后帧起始
wire ir_hs_sys; // 跨域后行起始
wire [7:0] ir_ch0_sys; // 跨域后CH0数据
wire [7:0] ir_ch1_sys; // 跨域后CH1数据
wire [7:0] ir_ch2_sys; // 跨域后CH2数据
reg flag;
// 4. 直方图控制信号
wire hist_rst; // 直方图RAM复位帧起始/更新触发
wire hist_wr_en_ch0; // CH0直方图写使能
wire [7:0] hist_wr_addr_ch0; // CH0直方图写地址像素值
wire hist_wr_en_ch1; // CH1直方图写使能
wire [7:0] hist_wr_addr_ch1; // CH1直方图写地址像素值
wire hist_wr_en_ch2; // CH2直方图写使能
wire [7:0] hist_wr_addr_ch2; // CH2直方图写地址像素值
reg hist_calc_en; // 直方图min/max计算使能帧结束后
wire hist_calc_done; // 直方图min/max计算完成
// 5. 数据拼接信号
wire assemble_en; // 数据拼接使能
wire assemble_done; // 数据拼接完成256bit就绪
wire [255:0] assemble_data; // 拼接后256bit数据
// 6. 同步FIFO信号系统时钟域
wire sync_fifo_wr_en; // 同步FIFO写使能
wire [255:0] sync_fifo_wr_data;// 同步FIFO写数据拼接后256bit
wire sync_fifo_full; // 同步FIFO满
wire sync_fifo_rd_en; // 同步FIFO读使能
wire [255:0] sync_fifo_rd_data;// 同步FIFO读数据
wire sync_fifo_empty; // 同步FIFO空
// 7. 帧计数与状态信号
reg [15:0] col_cnt; // 列计数器像素宽度计数
reg [15:0] row_cnt; // 行计数器像素高度计数
reg frame_active; // 帧活跃标记IR_VS后到帧结束
reg axi_write_busy; // AXI写事务忙标记
wire axi_write_done; // 来自 axi_write_ctrl 的写完成标志
// 8. 状态机定义
// typedef enum logic [2:0] {
// S_IDLE, // 空闲等待IPA使能
// S_WAIT_VS, // 等待帧起始IR_VS
// S_RECEIVE_DATA, // 接收像素数据写直方图+拼接
// S_WRITE_FIFO, // 拼接完成写同步FIFO
// S_WAIT_AXI, // 等待AXI写完成
// S_FRAME_DONE // 帧缓存完成置位src_image_cache_done
// } data_cache_state_t;
localparam [3:0] S_IDLE = 3'b000;
localparam [3:0] S_WAIT_VS = 3'b001;
localparam [3:0] S_RECEIVE_DATA = 3'b010;
localparam [3:0] S_WRITE_FIFO = 3'b011;
localparam [3:0] S_WAIT_AXI = 3'b100;
localparam [3:0] S_FRAME_DONE = 3'b101;
reg [2:0] curr_state;
reg [2:0] next_state;
// -------------------------- 子模块实例化 --------------------------
// 1. 复位同步确保跨时钟域复位稳定
rst_sync #(
.SYNC_STAGE(2) // 2级同步
) u_rst_sync_ir (
.clk(ir_clk),
.rst_n_in(rst_n),
.rst_n_out(rst_n_ir)
);
rst_sync #(
.SYNC_STAGE(2)
) u_rst_sync_sys (
.clk(clk),
.rst_n_in(rst_n),
.rst_n_out(rst_n_sys)
);
// 2. 异步FIFOIR时钟域系统时钟域传输像素数据+控制信号
async_fifo #(
.FIFO_DEPTH(ASYNC_FIFO_DEPTH),
.DATA_WIDTH(ASYNC_FIFO_DATA_W)
) u_async_fifo (
// 写端口IR时钟域
.wr_clk(ir_clk),
.wr_rst_n(rst_n_ir),
.wr_en(async_fifo_wr_en),
.wr_data(async_fifo_wr_data),
.full(async_fifo_full),
// 读端口系统时钟域
.rd_clk(clk),
.rd_rst_n(rst_n_sys),
.rd_en(async_fifo_rd_en),
.rd_data(async_fifo_rd_data),
.empty(async_fifo_empty)
);
// 3. 直方图控制模块统计CH0/CH1/CH2直方图计算min/max
histogram_ctrl #(
.HIST_RAM_DEPTH(HIST_RAM_DEPTH),
.HIST_RAM_DATA_W(HIST_RAM_DATA_W)
) u_histogram_ctrl (
.clk(clk),
.rst_n(rst_n_sys),
.hist_rst(hist_rst),
.input_pixel_type(input_pixel_type),
.hist_wr_en_ch0(hist_wr_en_ch0),
.hist_wr_addr_ch0(hist_wr_addr_ch0),
.hist_wr_en_ch1(hist_wr_en_ch1),
.hist_wr_addr_ch1(hist_wr_addr_ch1),
.hist_wr_en_ch2(hist_wr_en_ch2),
.hist_wr_addr_ch2(hist_wr_addr_ch2),
.histogram_low_num(histogram_low_num),
.histogram_high_num(histogram_high_num),
.calc_en(hist_calc_en),
.calc_done(hist_calc_done),
.dwidth_conv_min_ch0(dwidth_conv_min_ch0),
.dwidth_conv_max_ch0(dwidth_conv_max_ch0),
.dwidth_conv_min_ch1(dwidth_conv_min_ch1),
.dwidth_conv_max_ch1(dwidth_conv_max_ch1),
.dwidth_conv_min_ch2(dwidth_conv_min_ch2),
.dwidth_conv_max_ch2(dwidth_conv_max_ch2)
);
// 4. 数据拼接模块Gray:32x8bit256bitRGB:8x32bit256bit
data_assemble #(
.PIXEL_WIDTH(8), // 单通道像素位宽
.GRAY_PIXEL_CNT(32), // Gray模式拼接像素数32x8bit=256bit
.RGB_PIXEL_CNT(8) // RGB模式拼接像素数8x32bit=256bit
) u_data_assemble (
.clk(clk),
.rst_n(rst_n_sys),
.en(assemble_en),
.input_pixel_type(input_pixel_type),
.ir_ch0(ir_ch0_sys),
.ir_ch1(ir_ch1_sys),
.ir_ch2(ir_ch2_sys),
.pixel_valid(async_fifo_rd_data[26]),
.done(assemble_done),
.assembled_data(assemble_data)
);
// 5. 同步FIFO缓存拼接后的256bit数据适配AXI写速度
sync_fifo #(
.FIFO_DEPTH(SYNC_FIFO_DEPTH),
.DATA_WIDTH(SYNC_FIFO_DATA_W)
) u_sync_fifo (
.clk(clk),
.rst_n(rst_n_sys),
.wr_en(sync_fifo_wr_en),
.wr_data(sync_fifo_wr_data),
.full(sync_fifo_full),
.rd_en(sync_fifo_rd_en),
.rd_data(sync_fifo_rd_data),
.empty(sync_fifo_empty)
);
// 6. AXI写控制模块从同步FIFO读数据发起AXI写事务
axi_write_ctrl #(
.AXI_ID_W(AXI_ID_W),
.AXI_ADDR_W(AXI_ADDR_W),
.AXI_DATA_W(AXI_DATA_W),
.AXI_STRB_W(AXI_STRB_W)
) u_axi_write_ctrl (
.clk(clk),
.rst_n(rst_n_sys),
.start_en(!sync_fifo_empty && !axi_write_busy), // FIFO非空且AXI空闲时启动
.sram_base_addr(32'h0000_0000), // SRAM基地址可配置
.fifo_rd_data(sync_fifo_rd_data),
.fifo_empty(sync_fifo_empty),
.fifo_rd_en(sync_fifo_rd_en),
.axi_m_awid(axi_m_awid),
.axi_m_awaddr(axi_m_awaddr),
.axi_m_awlen(axi_m_awlen),
.axi_m_awsize(axi_m_awsize),
.axi_m_awburst(axi_m_awburst),
.axi_m_awlock(axi_m_awlock),
.axi_m_awcache(axi_m_awcache),
.axi_m_awprot(axi_m_awprot),
.axi_m_awqos(axi_m_awqos),
.axi_m_awvalid(axi_m_awvalid),
.axi_m_awready(axi_m_awready),
.axi_m_wid(axi_m_wid),
.axi_m_wdata(axi_m_wdata),
.axi_m_wstrb(axi_m_wstrb),
.axi_m_wlast(axi_m_wlast),
.axi_m_wvalid(axi_m_wvalid),
.axi_m_wready(axi_m_wready),
.axi_m_bid(axi_m_bid),
.axi_m_bresp(axi_m_bresp),
.axi_m_bvalid(axi_m_bvalid),
.axi_m_bready(axi_m_bready),
.axi_busy(axi_write_busy),
.axi_done(axi_write_done)
);
// -------------------------- 核心逻辑实现 --------------------------
// assign flag = (col_cnt == src_pixel_width-1'd1);
assign axi_write_done = (axi_m_bvalid && axi_m_bready);
// 1. 异步FIFO写控制IR时钟域
assign async_fifo_wr_data = {ir_valid, ir_vs, ir_hs, ir_ch2, ir_ch1, ir_ch0};
assign async_fifo_wr_en = ir_valid && !async_fifo_full && ipa_en; // 像素有效且FIFO未满
// 2. 异步FIFO读控制系统时钟域
assign async_fifo_rd_en = !async_fifo_empty &&
(curr_state == S_WAIT_VS || frame_active) && !flag; // 帧活跃且FIFO非空
// 3. 跨域后信号解析系统时钟域
assign ir_valid_sys = async_fifo_rd_data[26] && !flag; // [26] = ir_valid
assign ir_vs_sys = async_fifo_rd_data[25]; // [25] = ir_vs
assign ir_hs_sys = async_fifo_rd_data[24]; // [24] = ir_hs
assign ir_ch2_sys = async_fifo_rd_data[23:16];// [23:16] = ir_ch2
assign ir_ch1_sys = async_fifo_rd_data[15:8]; // [15:8] = ir_ch1
assign ir_ch0_sys = async_fifo_rd_data[7:0]; // [7:0] = ir_ch0
// 4. 直方图写控制系统时钟域
assign hist_rst = update_src_trig || ir_vs_sys; // 更新触发或帧起始时复位直方图
assign hist_wr_en_ch0 = ir_valid_sys && frame_active; // CH0始终写Gray/RGB均有效
assign hist_wr_addr_ch0 = ir_ch0_sys;
assign hist_wr_en_ch1 = ir_valid_sys && frame_active && (input_pixel_type == 1'b1); // RGB时写CH1
assign hist_wr_addr_ch1 = ir_ch1_sys;
assign hist_wr_en_ch2 = ir_valid_sys && frame_active && (input_pixel_type == 1'b1); // RGB时写CH2
assign hist_wr_addr_ch2 = ir_ch2_sys;
//assign hist_calc_en = (row_cnt == src_pixel_height-1'd1) && (col_cnt == src_pixel_width-1'd1); // 帧结束后计算min/max
// 5. 数据拼接使能控制
assign assemble_en = frame_active && ir_valid_sys && !ir_vs_sys;
// 6. 同步FIFO写控制
assign sync_fifo_wr_en = assemble_done && !sync_fifo_full;
assign sync_fifo_wr_data = assemble_data;
// 7. 帧计数逻辑 - 修复frame_active激活关键不依赖frame_active读FIFO
always @(posedge clk or negedge rst_n_sys) begin
if (!rst_n_sys) begin
col_cnt <= 16'd0;
row_cnt <= 16'd0;
frame_active <= 1'b0;
end else if (update_src_trig) begin
col_cnt <= 16'd0;
row_cnt <= 16'd0;
frame_active <= 1'b0;
end else if (ir_vs_sys && curr_state == S_WAIT_VS) begin
// WAIT_VS状态下ir_vs_sys=1 激活frame_active
col_cnt <= 16'd0;
row_cnt <= 16'd0;
frame_active <= 1'b1;
end else if (curr_state == S_RECEIVE_DATA) begin
// RECEIVE_DATA状态下保持frame_active=1直到帧结束
frame_active <= 1'b1;
if (ir_valid_sys && !ir_vs_sys) begin
col_cnt <= col_cnt + 16'd1;
if (col_cnt == src_pixel_width - 16'd1) begin
col_cnt <= 16'd0;
row_cnt <= row_cnt + 16'd1;
if (row_cnt == src_pixel_height - 16'd1) begin
frame_active <= 1'b0;
end
end
end
end else begin
frame_active <= 1'b0;
end
end
// 8. 状态机时序逻辑
always @(posedge clk or negedge rst_n_sys) begin
if (!rst_n_sys) begin
curr_state <= S_IDLE;
end else begin
curr_state <= next_state;
end
end
// 9. 状态机组合逻辑状态转移
always @(*) begin
next_state = curr_state;
case (curr_state)
S_IDLE: begin
// 等待IPA使能
if (ipa_en && !update_src_trig) begin
next_state = S_WAIT_VS;
end
end
S_WAIT_VS: begin
// 等待帧起始IR_VS
if (ir_vs_sys) begin
next_state = S_RECEIVE_DATA;
end else if (update_src_trig) begin
next_state = S_IDLE;
end
end
S_RECEIVE_DATA: begin
// 接收数据直到帧结束/列计数满
if ((row_cnt == src_pixel_height-1'd1) && (col_cnt == src_pixel_width-1'd1)) begin
next_state = S_WRITE_FIFO;
end else if (update_src_trig) begin
next_state = S_IDLE;
end
end
S_WRITE_FIFO: begin
// 条件1同步FIFO已空数据已全部读出到AXI控制器但AXI仍在忙碌 等待AXI完成
if (sync_fifo_empty && axi_write_busy) begin
next_state = S_WAIT_AXI;
end
// 条件2同步FIFO已空且AXI已完成所有写操作 直接进入帧完成
else if (sync_fifo_empty && !axi_write_busy) begin
next_state = S_FRAME_DONE;
end
// 条件3收到更新触发 强制回到IDLE
else if (update_src_trig) begin
next_state = S_IDLE;
end
end
S_WAIT_AXI: begin
// AXI写完成后进入帧完成状态
if (axi_write_done) begin
next_state = S_FRAME_DONE;
end
// 收到更新触发 强制回到IDLE
else if (update_src_trig) begin
next_state = S_IDLE;
end
end
S_FRAME_DONE: begin
// 帧完成保持1拍后回到等待VS支持连续帧
if (src_image_cache_done) begin
next_state = S_WAIT_VS;
end else begin
next_state = S_FRAME_DONE;
end
end
endcase
end
// 10. 状态机输出逻辑控制各模块行为
always @(posedge clk or negedge rst_n_sys) begin
if (!rst_n_sys) begin
src_image_cache_done <= 1'b0;
end else begin
src_image_cache_done <= 1'b0;
case (curr_state)
S_FRAME_DONE: begin
// 帧完成置位缓存完成信号并等待直方图计算完成
src_image_cache_done <= hist_calc_done;
end
default: begin
src_image_cache_done <= 1'b0;
end
endcase
end
end
always @(posedge clk or negedge rst_n_sys) begin
if (!rst_n_sys) begin
hist_calc_en <= 'd0;
end else begin
hist_calc_en <= (row_cnt == src_pixel_height-1'd1) && (col_cnt == src_pixel_width-1'd1);
end
end
// always @(posedge clk or negedge rst_n_sys) begin
// if (!rst_n_sys) begin
// assemble_en <= 'd0;
// end else begin
// assemble_en <= frame_active && ir_valid_sys && !ir_vs_sys;
// end
// end
reg [1:0] flag_cnt;
always @(posedge clk or negedge rst_n_sys) begin
if (!rst_n_sys) begin
flag <= 'd0;
flag_cnt <='d0;
end else if (flag == 1'b1)begin
flag_cnt <= flag_cnt + 1'b1;
if (flag_cnt == 2'd2) begin
flag <= 'd0;
flag_cnt <='d0;
end
end else if (col_cnt == src_pixel_width-1'd1) begin
flag <= 1'b1;
end
end
endmodule