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

196 lines
7.9 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 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