module axi_write_ctrl #( parameter AXI_ID_W = 8, // AXI ID位宽 parameter AXI_ADDR_W = 32, // AXI地址位宽 parameter AXI_DATA_W = 256, // AXI数据位宽 parameter AXI_STRB_W = AXI_DATA_W / 8 // 字节选通位宽(256bit对应32字节) ) ( input wire clk, // 系统时钟 input wire rst_n, // 异步复位,低有效 // 控制与数据输入 input wire start_en, // 写事务启动使能 input wire [AXI_ADDR_W-1:0] sram_base_addr, // SRAM基地址 input wire [AXI_DATA_W-1:0] fifo_rd_data, // FIFO读数据 input wire fifo_empty, // FIFO空标志 output reg fifo_rd_en, // FIFO读使能 // AXI AW通道 output reg [AXI_ID_W-1:0] axi_m_awid, // 写地址ID output reg [AXI_ADDR_W-1:0] axi_m_awaddr, // 写地址 output reg [3:0] axi_m_awlen, // 突发长度(0表示1个数据) output reg [2:0] axi_m_awsize, // 数据宽度(5对应32字节) output reg [1:0] axi_m_awburst, // 突发类型(0表示增量) output reg axi_m_awlock, // 锁定信号(0表示普通访问) output reg [4:0] axi_m_awcache, // 缓存属性(0表示非缓存) output reg [2:0] axi_m_awprot, // 保护属性(0表示普通) output reg [4:0] axi_m_awqos, // QoS优先级(0表示默认) output reg axi_m_awvalid, // 写地址有效 input wire axi_m_awready, // 写地址就绪 // AXI W通道 output reg [AXI_ID_W-1:0] axi_m_wid, // 写数据ID output reg [AXI_DATA_W-1:0] axi_m_wdata, // 写数据 output reg [AXI_STRB_W-1:0] axi_m_wstrb, // 字节选通(全1表示所有字节有效) output reg axi_m_wlast, // 突发结束标志 output reg axi_m_wvalid, // 写数据有效 input wire axi_m_wready, // 写数据就绪 // AXI B通道 input wire [AXI_ID_W-1:0] axi_m_bid, // 写响应ID input wire [1:0] axi_m_bresp, // 写响应(0表示OKAY) input wire axi_m_bvalid, // 写响应有效 output reg axi_m_bready, // 写响应就绪 // 状态输出 output reg axi_busy, // AXI写事务忙 output reg axi_done // AXI写事务完成 ); // 内部信号定义 reg [AXI_ADDR_W-1:0] curr_addr; // 当前写地址(基于基地址递增) reg [1:0] axi_state; // AXI状态机状态寄存器 // 状态定义 localparam AXI_IDLE = 2'd0; // 空闲状态 localparam AXI_AW = 2'd1; // 地址通道传输状态 localparam AXI_W = 2'd2; // 数据通道传输状态 localparam AXI_B = 2'd3; // 响应通道传输状态 // 1. AXI状态机时序逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin axi_state <= AXI_IDLE; curr_addr <= {AXI_ADDR_W{1'b0}}; axi_busy <= 1'b0; axi_done <= 1'b0; end else begin axi_done <= 1'b0; // 单周期有效 case (axi_state) AXI_IDLE: begin axi_busy <= 1'b0; // 启动条件: 使能信号有效且FIFO非空 if (start_en && !fifo_empty) begin axi_state <= AXI_AW; axi_busy <= 1'b1; // 初始化当前地址为基地址(首次)或保持上次地址(连续传输) curr_addr <= (curr_addr == {AXI_ADDR_W{1'b0}}) ? sram_base_addr : curr_addr; end end AXI_AW: begin // 地址通道握手完成,进入数据通道 if (axi_m_awvalid && axi_m_awready) begin axi_state <= AXI_W; // 预计算下一次地址(当前地址 + 数据宽度字节数) curr_addr <= curr_addr + (AXI_DATA_W / 8); end end AXI_W: begin // 数据通道握手完成,进入响应通道 if (axi_m_wvalid && axi_m_wready) begin axi_state <= AXI_B; end end AXI_B: begin // 响应通道握手完成,事务结束 if (axi_m_bvalid && axi_m_bready) begin axi_state <= AXI_IDLE; axi_done <= 1'b1; // 标记事务完成 end end endcase end end // 2. AXI AW通道信号生成逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin axi_m_awid <= {AXI_ID_W{1'b0}}; axi_m_awaddr <= {AXI_ADDR_W{1'b0}}; axi_m_awlen <= 4'd0; axi_m_awsize <= 3'd5; // 5对应32字节(2^5 = 32) axi_m_awburst <= 2'd0; // 0表示INCR(增量)突发 axi_m_awlock <= 1'b0; axi_m_awcache <= 5'd0; // 非缓存、非缓冲 axi_m_awprot <= 3'd0; // 普通非特权数据访问 axi_m_awqos <= 5'd0; // 默认QoS级别 axi_m_awvalid <= 1'b0; end else begin case (axi_state) AXI_AW: begin axi_m_awid <= 8'd0; // 固定ID为0 axi_m_awaddr <= curr_addr; // 当前地址 axi_m_awlen <= 4'd0; // 突发长度为1(0+1) axi_m_awsize <= 3'd5; // 保持32字节宽度 axi_m_awburst <= 2'd0; // 保持增量突发 axi_m_awvalid <= 1'b1; // 地址有效 end default: begin axi_m_awvalid <= 1'b0; // 非地址状态时无效 end endcase end end // 3. AXI W通道信号生成逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin axi_m_wid <= {AXI_ID_W{1'b0}}; axi_m_wdata <= {AXI_DATA_W{1'b0}}; axi_m_wstrb <= {AXI_STRB_W{1'b1}}; // 所有字节有效 axi_m_wlast <= 1'b1; // 单拍突发,始终为1 axi_m_wvalid <= 1'b0; fifo_rd_en <= 1'b0; end else begin case (axi_state) AXI_AW: begin // 地址握手完成前预读FIFO if (axi_m_awready) begin fifo_rd_en <= 1'b1; // 读取FIFO数据 axi_m_wid <= 8'd0; // 与AW通道ID保持一致 axi_m_wdata <= fifo_rd_data; // 锁存FIFO数据 axi_m_wvalid <= 1'b1; // 数据有效 end else begin fifo_rd_en <= 1'b0; axi_m_wvalid <= 1'b0; end end AXI_W: begin fifo_rd_en <= 1'b0; // 停止读FIFO // 数据握手完成后失效 if (axi_m_wready) begin axi_m_wvalid <= 1'b0; end end default: begin fifo_rd_en <= 1'b0; axi_m_wvalid <= 1'b0; end endcase end end // 4. AXI B通道信号生成逻辑 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin axi_m_bready <= 1'b0; end else begin case (axi_state) AXI_B: begin axi_m_bready <= 1'b1; // 准备接收响应 // 响应握手完成后失效 if (axi_m_bvalid) begin axi_m_bready <= 1'b0; end end default: begin axi_m_bready <= 1'b0; end endcase end end endmodule