Files
IPA/rtl/data_cache/data_cache.v
Core_kingdom 79dee10db1 cache module
2025-08-26 16:53:22 +08:00

470 lines
20 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 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:32x8bit→256bitRGB:8x32bit→256bit
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