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=Gray,1=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通道QoS(0=默认) 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. 异步FIFO(IR时钟域→系统时钟域,传输像素数据+控制信号) 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→256bit;RGB: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