秦韵FPGA 转载或原创(七)
基于高云的fpga做一个axi lite从机总线。
- 简单介绍一下axi总线
- 写一个简单的axi从机例程
- 总结一下axi ,amba总线。
1 )简介
Axi_Lite 总线为轻量级的总线架构,一般情况下进行寄存器的读取, 慢速的数据传输,比如:读取状态寄存器,控制寄存器以及异常存储的寄存器,监控一下drm(sdram,ddr2/3...)的控制器的工作状态等等。理解起来也比较容易,简单来说就是地址,数据,读写使能,在axi总线上由相应通道如下图:很清楚的看出axi总线的工作情况,读通道,写通道。
贴一段代码看看信号名称,简单的理解一下总线的信号端口:
这部分时写通道的,包括地址与控制通道,写数据通道,写响应通道。
//--- AXI4-Lite Control and address Channel ------------------------------
input [C_AXI_ADDR_WIDTH-1:0] axi_awaddr,
input [2:0] axi_awport, //表示着传输的特权与安全
input axi_awvalid, //表示主机可以控制写数据总线实现写功能
output axi_awready,
input [C_AXI_DATA_WIDTH-1 : 0] axi_wdata,
input [(C_AXI_DATA_WIDTH/8)-1 : 0] axi_wstrb, //表示写字节通道保持有效,在每8位的写数据总线上有1位被选通
input axi_wvalid,
output axi_wready, //表示从机可以接收主机发送的数据
output [1:0] axi_bresp, //标志从机是否接收到主机发送的数据
output axi_bvalid, //表示从机接收到主机发送的数据
input axi_bready, //表示主机可以接收到写答复信号
这部分是读通道,包括读数据,地址与控制通道。
//--- AXI4-Lite Control and address Channel ------------------------------
input axi_araddr,
input [2:0] axi_arport,
input axi_arvalid,
output axi_arready, //表示主机可以读取数据
//--- AXI4-Lite Read Data Channel ------------------------------
output [C_AXI_DATA_WIDTH-1 : 0] axi_rdata,
output [1:0] axi_rresp, //表示读数据传输的状态
output axi_rvalid, //表示有效的数据已传输
input axi_rready, //表示主机可以接收从机发送的数据
加一些用户寄存器端口:
// localparam C_AXI_DATA_WIDTH = 32
//------------------------------------------------------------
output reg [C_AXI_DATA_WIDTH-1:0] RUN_CONT_REG, //运行与控制寄存器
output reg [C_AXI_DATA_WIDTH-1:0] PACKET_CNT_REG, //当前包数量寄存器
output reg [C_AXI_DATA_WIDTH-1:0] START_REG, //
output reg [C_AXI_DATA_WIDTH-1:0] SAMPLE_REG,
output reg [C_AXI_DATA_WIDTH-1:0] FLU_HIGH_REG,
output reg [C_AXI_DATA_WIDTH-1:0] FLU_LOW_REG,
output reg [C_AXI_DATA_WIDTH-1:0] FLU_START_REG,
output reg [C_AXI_DATA_WIDTH-1:0] FLU_STOP_REG,
.......
#### 2)代码分析
主要展示一下,axi总线的读和写部分:
if (slv_reg_wren)
begin
case ( axi_awaddr[3:0] )
4'h0:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
RUN_CONT_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h1:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
PACKET_CNT_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h2:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
START_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h3:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
SAMPLE_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h4:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
FLU_HIGH_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h5:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
FLU_LOW_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
4'h6:
for ( byte_index = 0; byte_index <= (C_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( axi_wstrb[byte_index] == 1 ) begin
FLU_START_REG[(byte_index*8) +: 8] <= axi_wdata[(byte_index*8) +: 8];
end
default : begin
RUN_CONT_REG<= RUN_CONT_REG;
PACKET_CNT_REG<= PACKET_CNT_REG;
START_REG<= 32'h0;
SAMPLE_REG<= 32'h0;
FLU_HIGH_REG<=FLU_HIGH_REG;
FLU_LOW_REG<= FLU_LOW_REG;
FLU_START_REG<= FLU_START_REG;
end
endcase
end
读 :
此地址空间暂时预留4bit ,可以添加16个寄存器,按需求适当增加地址位宽。
always @(*)
begin
case ( axi_araddr[3:0] )
4'h0 : reg_data_out <= RUN_CONT_REG;
4'h1 : reg_data_out <= packet_cnt;
4'h2 : reg_data_out <= Status_flag;
4'h3 : reg_data_out <= error_flag;
4'h4 : reg_data_out <= FLU_HIGH_REG;
4'h5 : reg_data_out <= FLU_LOW_REG;
4'h6 : reg_data_out <= FLU_START_REG;
default : reg_data_out <= 0;
endcase
end
//.......