以下是用 Verilog 实现 AXI MASTER 的代码示例,每次传输大小为 32 字节,数据位宽为 64 位。
module axi_master(
input wire clk,
input wire rst_n,
// AXI 接口信号
output reg [31:0] awaddr,
output reg [7:0] awlen,
output reg [2:0] awsize,
output reg [1:0] awburst,
output reg awvalid,
input wire awready,
output reg [63:0] wdata,
output reg [7:0] wstrb,
output reg wlast,
output reg wvalid,
input wire wready,
input wire [1:0] bresp,
input wire bvalid,
output reg bready,
output reg [31:0] araddr,
output reg [7:0] arlen,
output reg [2:0] arsize,
output reg [1:0] arburst,
output reg arvalid,
input wire arready,
input wire [63:0] rdata,
input wire [1:0] rresp,
input wire rlast,
input wire rvalid,
output reg rready
);
// 状态定义
localparam IDLE = 3'b000;
localparam WRITE_ADDR = 3'b001;
localparam WRITE_DATA = 3'b010;
localparam WRITE_RESP = 3'b011;
localparam READ_ADDR = 3'b100;
localparam READ_DATA = 3'b101;
reg [2:0] current_state, next_state;
// 第一段:状态转移
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
current_state <= IDLE;
end else begin
current_state <= next_state;
end
end
// 第二段:状态转移条件
always @(*) begin
case (current_state)
IDLE: begin
next_state = WRITE_ADDR;
end
WRITE_ADDR: begin
if (awready) begin
next_state = WRITE_DATA;
end else begin
next_state = WRITE_ADDR;
end
end
WRITE_DATA: begin
if (wlast && wready) begin
next_state = WRITE_RESP;
end else begin
next_state = WRITE_DATA;
end
end
WRITE_RESP: begin
if (bvalid) begin
next_state = READ_ADDR;
end else begin
next_state = WRITE_RESP;
end
end
READ_ADDR: begin
if (arready) begin
next_state = READ_DATA;
end else begin
next_state = READ_ADDR;
end
end
READ_DATA: begin
if (rlast && rvalid) begin
next_state = IDLE;
end else begin
next_state = READ_DATA;
end
end
default: next_state = IDLE;
endcase
end
// 第三段:输出逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
awaddr <= 32'h0;
awlen <= 8'h0;
awsize <= 3'h2; // 32 字节传输对应 size 为 2(64 位数据位宽)
awburst <= 2'b01;
awvalid <= 1'b0;
wdata <= 64'h0;
wstrb <= 8'hFF;
wlast <= 1'b0;
wvalid <= 1'b0;
bready <= 1'b0;
araddr <= 32'h0;
arlen <= 8'h0;
arsize <= 3'h2;
arburst <= 2'b01;
arvalid <= 1'b0;
rready <= 1'b0;
end else begin
case (current_state)
IDLE: begin
awaddr <= 32'h1000; // 设置起始地址
awlen <= 8'd3; // 总共传输 4 个突发(32 字节)
awvalid <= 1'b1;
end
WRITE_ADDR: begin
awvalid <= 1'b0;
end
WRITE_DATA: begin
if (wready) begin
wdata <= wdata + 64'h1;
if (wdata == {64{1'b1}}) begin
wlast <= 1'b1;
end
wvalid <= 1'b1;
end else begin
wvalid <= 1'b0;
end
end
WRITE_RESP: begin
bready <= 1'b1;
end
READ_ADDR: begin
araddr <= 32'h1000;
arlen <= 8'd3;
arvalid <= 1'b1;
end
READ_DATA: begin
if (rvalid) begin
rready <= 1'b0;
if (rlast) begin
rready <= 1'b0;
end else begin
rready <= 1'b1;
end
end
end
default: begin
// 默认状态下的输出赋值
awaddr <= 32'h0;
awvalid <= 1'b0;
wdata <= 64'h0;
wvalid <= 1'b0;
bready <= 1'b0;
araddr <= 32'h0;
arvalid <= 1'b0;
rready <= 1'b0;
end
endcase
end
end
endmodule
在这个实现中,状态机分为三段。第一段负责状态的转移,在时钟上升沿或复位信号下降沿时更新当前状态。第二段根据当前状态确定下一个状态,考虑了各种 AXI 信号的就绪情况。第三段根据当前状态对 AXI Master 的输出信号进行赋值,控制写地址、写数据、等待写响应、读地址和读数据的过程。每次传输的数据大小为 32 字节,数据位宽为 64 位。