196 lines
7.9 KiB
Coq
196 lines
7.9 KiB
Coq
![]() |
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
|
|||
|
|