FPGA实现AXI4总线的读写_如何写axi4逻辑
一、AXI4 接口描述
通道 | 信号 | 源 | 信号描述 |
全局信号 | aclk | 主机 | 全局时钟 |
aresetn | 主机 | 全局复位,低有效 | |
写通道地址与控制信号通道 | M_AXI_WR_awid[3:0] | 主机 | 写地址ID,用来标志一组写信号 |
M_AXI_WR_awaddr[31:0] | 主机 | 写地址,给出一次写突发传输的写地址 | |
M_AXI_WR_awlen[7:0] | 主机 | 突发长度,给出突发传输的次数 | |
M_AXI_WR_awsize[2:0] | 主机 | 突发大小,给出每次突发传输的字节数 | |
M_AXI_WR_awburst[1:0] | 主机 | 突发类型 | |
M_AXI_WR_awlock | 主机 | 总线锁信号,可提供操作的原子性 | |
M_AXI_WR_awcache[3:0] | 主机 | 内存类型,表明一次传输是怎样通过系统的 | |
M_AXI_WR_awprot[2:0] | 主机 | 保护类型,表明一次传输的特权级及安全等级 | |
M_AXI_WR_awqos[3:0] | 主机 | 质量服务QoS | |
M_AXI_WR_awvalid | 主机 | 有效信号,表明此通道的地址控制信号有效 | |
M_AXI_WR_awready | 从机 | 表明“从”可以接收地址和对应的控制信号 | |
写通道数据通道 | M_AXI_WR_wdata[63:0] | 主机 | 写数据 |
M_AXI_WR_wstrb[7:0] | 主机 | 写数据有效的字节线,用来表明哪8bits数据是有效的 | |
M_AXI_WR_wlast | 主机 | 表明此次传输是最后一个突发传输 | |
M_AXI_WR_wvalid | 主机 | 写有效,表明此次写有效 | |
M_AXI_WR_wready | 从机 | 表明从机可以接收写数据 | |
写通道响应通道 | M_AXI_WR_bid[3:0] | 从机 | 写响应ID TAG |
M_AXI_WR_bresp[1:0] | 从机 | 写响应,表明写传输的状态 | |
M_AXI_WR_bvalid | 从机 | 写响应有效 | |
M_AXI_WR_bready | 主机 | 表明主机能够接收写响应 | |
读通道地址与控制信号通道 | M_AXI_RD_arid[3:0] | 主机 | 读地址ID,用来标志一组写信号 |
M_AXI_RD_araddr[31:0] | 主机 | 读地址,给出一次写突发传输的读地址 | |
M_AXI_RD_arlen[7:0] | 主机 | 突发长度,给出突发传输的次数 | |
M_AXI_RD_arsize[2:0] | 主机 | 突发大小,给出每次突发传输的字节数 | |
M_AXI_RD_arburst[1:0] | 主机 | 突发类型 | |
M_AXI_RD_arlock[1:0] | 主机 | 总线锁信号,可提供操作的原子性 | |
M_AXI_RD_arcache[3:0] | 主机 | 内存类型,表明一次传输是怎样通过系统的 | |
M_AXI_RD_arprot[2:0] | 主机 | 保护类型,表明一次传输的特权级及安全等级 | |
M_AXI_RD_arqos[3:0] | 主机 | 质量服务QOS | |
M_AXI_RD_arvalid | 主机 | 有效信号,表明此通道的地址控制信号有效 | |
M_AXI_RD_arready | 从机 | 表明“从”可以接收地址和对应的控制信号 | |
读通道数据通道 | M_AXI_RD_rid[3:0] | 从机 | 读IDtag |
M_AXI_RD_rdata[63:0] | 从机 | 读数据 | |
M_AXI_RD_rresp[1:0] | 从机 | 读响应,表明读传输的状态 | |
M_AXI_RD_rlast | 从机 | 表明读突发的最后一次传输 | |
M_AXI_RD_rvalid | 从机 | 表明此通道信号有效 | |
M_AXI_RD_rready | 主机 | 表明主机能够接收读数据和响应信息 |
二、地址通道的控制信号与地址描述
1、地址ID
AWID[3:0]与ARID[3:0]:对于只有一个主机从机设备,该值可设置为任意
2、地址结构
AWADDR[31:0]与ARADDR[31:0]:AXI协议是基于burst(突发)的,主机只给出突发传输的第一个字节的地址,从机必须计算突发传输后续的地址。突发传输不能跨4KB边界(防止突发跨越两个从机的边界,也限制了从机所需支持的地址自增数
3、突发长度
AWLEN[7:0]与ARLEN[7:0]:ARLEN[7:0]决定读传输的突发长度,AWLEN[7:0]决定写传输的突发长度。AXI4扩展突发长度支持INCR突发类型为1256次传输,对于其他的传输类型依然保持116次突发传输(Burst_Length=AxLEN[7:0]+1)
4、突发大小
ARSIZE[2:0],读突发传输;AWSIZE[2:0],写突发传输。
AxSIZE[2:0] | 传输字节大小 |
3'b000 | 1 |
3'b001 | 2 |
3'b010 | 4 |
3'b011 | 8 |
3'b100 | 16 |
3'b101 | 32 |
3'b110 | 64 |
3'b111 | 128 |
5、突发类型
AWBURST[1:0]与ARBURST[1:0]:
AxBURST[1:0] | 突发类型 |
2'b00 | FIXED |
2'b01 | INCR |
2'b10 | WRAP |
2'b11 | Reserved |
FIXED:突发传输过程中地址固定,用于FIFO访问
INCR:增量突发,传输过程中,地址递增。增加量取决AxSIZE的值
WRAP:回环突发,和增量突发类似,但会在特定高地址的边界处回到低地址处。回环突发的长度只能是2,4,8,16次传输,传输首地址和每次传输的大小对齐。最低的地址整个传输的数据大小对齐。回环边界等于(AxSIZE*AxLEN)
三、数据通道信号描述
1、WDATA与RDATA:写与读数据线信号
WSTRB:有效字节,WSTRB[n:0]对应于对应的写字节,WSTRB[n]对应WDATA[8n+7:8n],也就是对于的数据宽度的字节数是否有效。WVALID为低时,WSTRB可以为任意值,WVALID为高时,WSTRB为高的字节线必须指示有效的数据。对于一般应用,将WSTRB全部置1即可,保证全部数据有效。读通道无该信号。
2、WLAST与RLAST
写与读最后一个字节,拉高表示传输最后一个字节,也意味着传输结束
3、burst[1:0]
描述读写相应结构
burst[1:0] | |
00 | 常规访问成功 |
01 | 独占访问成功 |
10 | 从机错误 |
11 | 解码错误 |
四、突发写时序:
AXI4突发写可以分为7个状态,写空闲,写通道写地址等待,写通道写地址,写数据等待,写数据循环,接受写应答,写结束这7种状态。之所以划分为7个状态是为了后续写程序的状态机做准备。
7种状态
1、写空闲:等待触发突发信号
2、写通道写地址等待:准备好写地址AWADDR,然后拉高AWVALID。
3、写通道写地址:从机接受到AWVALID,发出AWREADY。
4、写数据等待:准备好数据WDATA,拉高WVALID。
5、写数据循环:从机接受WVALID,确认数据WDATA有效并且接受,发出WREADY,AXI是突发传输:循环该操作到接受到WLAST最后一个数据标志位。
6、接受写应答:接受到从机发出的BVALID,主机发出BREADY。
7、写结束:拉低未拉低的信号,进入写空闲
五、突发读时序
AXI4突发读可以分为6个状态,读空闲,读通道写地址等待,读通道写地址,读数据等待,读数据循环,读结束这6种状态。之所以划分为6个状态是为了后续写程序的状态机做准备。
6种状态
1、读空闲:等待触发突发信号。
2、读通道写地址等待:准备好写地址ARADDR,然后拉高ARVALID。
3、读通道写地址:从机接受到ARVALID,发出ARREADY。
4、读数据等待:从机准备好数据WDATA,从机拉高RVALID。
5、读数据循环:主机接受RVALID,确认数据RDATA有效并且接受,发出RREADY给从机,AXI是突发传输:循环该操作到接受到RLAST最后一个数据标志位
6、读结束:拉低未拉低的信号,进入读空闲
注:
1、读数据必须总是跟在与其数据相关联的地址之后。
2、写响应必须总是跟在与其相关联的写事务的最后出现。
六、写时序状态机
七、写时序代码
module axi4_write(input clk ,input resetn ,input enable_write , //写使能input [31:0] w_addr , //地址input [63:0] w_data , //数据output reg write_done , //写完成output reg write_data , //表示数据写入,突发模式下可用于切换数据的指示信号//axi4写通道地址通道output [3:0] m_axi_awid , //写地址ID,用来标志一组写信号output reg[31:0] m_axi_awaddr ,//写地址,给出一次写突发传输的写地址 output [7:0] m_axi_awlen , //突发长度,给出突发传输的次数 output [2:0] m_axi_awsize , //突发大小,给出每次突发传输的字节数 output [1:0] m_axi_awburst , //突发类型 output m_axi_awlock , //总线锁信号,可提供操作的原子性 output [3:0] m_axi_awcache , //内存类型,表明一次传输是怎样通过系统的output [2:0] m_axi_awprot , //保护类型,表明一次传输的特权级及安全等级 output [3:0] m_axi_awqos , //质量服务QoSoutput reg m_axi_awvalid , //有效信号,表明此通道的地址控制信号有效 input m_axi_awready , //表明“从”可以接收地址和对应的控制信号//axi4写通道数据通道output reg[63:0] m_axi_wdata , //写数据 output [7:0] m_axi_wstrb , //写数据有效的字节线 output reg m_axi_wlast , //表明此次传输是最后一个突发传输output reg m_axi_wvalid , //写有效,表明此次写有效input m_axi_wready , //表明从机可以接收写数据 //axi4写通道应答通道 input [3:0] m_axi_bid , //写响应ID TAGinput [1:0] m_axi_bresp , //写响应,表明写传输的状态input m_axi_bvalid , //写响应有效output reg m_axi_bready //表明主机能够接收写响应);//*******************参数*****************************localparam W_IDLEW = 3'b001 ; //空闲等待localparam W_DRIVEW = 3'b011 ; //准备、取地址localparam W_HANDS = 3'b010 ; //握手localparam W_WSTBR = 3'b110 ; //突发localparam W_WAIT = 3'b111 ; //等待结束的信息localparam W_END = 3'b101 ; //写数据阶段parameter LEN_NUM = 1 ;parameter AWID = 0 ;
//*********内部信号******************************reg [2:0] state , next_state ;reg wready_over ;reg [7:0] len ;assign m_axi_awid = AWID[3:0] ; // [3:0] //写地址ID,用来标志一组写信号 assign m_axi_awlen = LEN_NUM-1 ; // [7:0] //突发长度,给出突发传输的次数 assign m_axi_awsize = 3'b011 ; // [2:0] //突发大小,给出每次突发传输的字节数 assign m_axi_awburst = 2'b10 ; // [1:0] //突发类型 assign m_axi_awlock = 1'b0 ; // //总线锁信号,可提供操作的原子性 assign m_axi_awcache = 4'b0010 ; // [3:0] //内存类型,表明一次传输是怎样通过系统的 assign m_axi_awprot = 3'b000 ; // [2:0] //保护类型,表明一次传输的特权级及安全等级 assign m_axi_awqos = 4'b0000 ; // [3:0] //质量服务QoS assign m_axi_wstrb = 8'hff ;//状态机always @(*) beginstate = next_state ;end always @(posedge clk or negedge resetn) beginif(!resetn) beginwready_over<=0;endelse if(state==W_IDLEW || state==W_END )wready_over<=0;else if(m_axi_wready)wready_over<=1;endalways @(posedge clk or negedge resetn) beginif(!resetn) beginnext_state <= W_IDLEW ;len <=0 ;endelse case(state)W_IDLEW : if(enable_write) next_state <= W_DRIVEW ; else next_state<=W_IDLEW ;W_DRIVEW: if(m_axi_awready) beginnext_state <= W_HANDS ; len<=LEN_NUM-1 ; end else next_state<=W_DRIVEW ;W_HANDS : if(wready_over && len==0)next_state <= W_WAIT ; else if(wready_over ) next_state <= W_WSTBR ;else next_state<=W_HANDS ;W_WSTBR : if(len==1) next_state <= W_WAIT ; else begin next_state <= W_WSTBR ;len <=len-1 ;endW_WAIT : next_state<=W_END ; W_END : if(m_axi_bvalid)next_state <= W_IDLEW ; else next_state<=W_END ;default : next_state<=W_IDLEW ;endcase end// 组合逻辑输出always @(* ) begincase(state)W_IDLEW : beginm_axi_wlast = 0 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = 0 ;m_axi_wvalid = 0 ;m_axi_bready = 0 ;write_done = 0 ;write_data = 0 ;endW_DRIVEW: beginm_axi_wlast = 0 ;m_axi_awaddr = w_addr ;m_axi_awvalid = 1 ;m_axi_wdata = 0 ;m_axi_wvalid = 0 ;m_axi_bready = 0 ;write_done = 0 ;write_data = 0 ;endW_HANDS : beginm_axi_wlast = 0 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = 0 ;m_axi_wvalid = 0 ;m_axi_bready = 0 ;write_done = 0 ;write_data = 0 ;endW_WSTBR : beginm_axi_wlast = 0 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = w_data ;m_axi_wvalid = 1 ;m_axi_bready = 0 ;write_done = 0 ;write_data = 1 ;endW_WAIT : beginm_axi_wlast = 1 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = w_data ;m_axi_wvalid = 1 ;m_axi_bready = 0 ;write_done = 1 ;write_data = 1 ;endW_END : beginm_axi_wlast = 0 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = 0 ;m_axi_wvalid = 0 ;m_axi_bready = 1 ;write_done = 0 ;write_data = 0 ;enddefault : beginm_axi_wlast = 0 ;m_axi_awaddr = 0 ;m_axi_awvalid = 0 ;m_axi_wdata = 0 ;m_axi_wvalid = 0 ;m_axi_bready = 0 ;write_done = 0 ;write_data = 0 ;endendcaseend
endmodule
八、读时序状态机
九、读时序代码
module axi4_read(input resetn ,//axi复位 input clk , //axi时钟 input enable_read ,output read_data ,output read_done ,input [31:0] r_addr ,output reg [63:0] r_data ,//axi读通道写地址 output [3:0] m_axi_arid , //读地址ID,用来标志一组写信号output reg [31:0] m_axi_araddr , //读地址,给出一次写突发传输的读地址output [7:0] m_axi_arlen , //突发长度,给出突发传输的次数output [2:0] m_axi_arsize , //突发大小,给出每次突发传输的字节数output [1:0] m_axi_arburst , //突发类型output [1:0] m_axi_arlock , //总线锁信号,可提供操作的原子性output [3:0] m_axi_arcache , //内存类型,表明一次传输是怎样通过系统的 output [2:0] m_axi_arprot , //保护类型,表明一次传输的特权级及安全等级output [3:0] m_axi_arqos , //质量服务QOS output reg m_axi_arvalid , //有效信号,表明此通道的地址控制信号有效 input m_axi_arready , //表明“从”可以接收地址和对应的控制信号//axi读通道读数据 input [3:0] m_axi_rid , //读ID tag input [63:0] m_axi_rdata , //读数据 input [1:0] m_axi_rresp , //读响应,表明读传输的状态input m_axi_rlast , //表明读突发的最后一次传输input m_axi_rvalid , //表明此通道信号有效 output reg m_axi_rready //表明主机能够接收读数据和响应信息);
//localparam [2:0] R_IDLER = 3'b001 ;localparam [2:0] R_WAIT = 3'b011 ;localparam [2:0] R_BURST = 3'b010 ;localparam [2:0] R_END = 3'b110 ;parameter ARID = 0 ;parameter RD_LEN = 1 ;
//reg [2:0] state , next_state ;reg rvalid_over ;
// assign m_axi_arid = ARID[3:0] ;//地址id assign m_axi_arlen = RD_LEN-32'd1 ;//突发长度assign m_axi_arsize = 3'b011 ;//表示AXI总线每个数据宽度是8字节,64位 assign m_axi_arburst = 2'b01 ;//地址递增方式传输assign m_axi_arlock = 1'b0 ;assign m_axi_arcache = 4'b0010 ; assign m_axi_arprot = 3'b000 ;assign m_axi_arqos = 4'b0000 ;assign read_data = m_axi_rvalid ;assign read_done = m_axi_rlast ;
//axi读状态机always @(*) beginstate = next_state ;end//always @(posedge clk or negedge resetn) beginif(!resetn) beginrvalid_over <=0 ;end else if(state==R_IDLER) beginrvalid_over <=0 ;endelse if(m_axi_rvalid)beginrvalid_over <= 1 ;endendalways @(posedge clk or negedge resetn) beginif(!resetn)next_state <= R_IDLER;else case(state)R_IDLER : if(enable_read) next_state <= R_WAIT ;else next_state<=R_IDLER ; R_WAIT : if(m_axi_arready) next_state<=R_BURST ;else next_state<=R_WAIT ; R_BURST : if(m_axi_rlast) next_state<=R_END ;else next_state <= R_BURST ;R_END : if(rvalid_over) next_state<=R_IDLER;else next_state<=R_END ; default : next_state<=R_IDLER ;endcaseend//always @(*) begincase(state)R_IDLER : beginm_axi_araddr = 0 ; m_axi_arvalid = 0 ; m_axi_rready = 0 ; r_data = 0 ; end R_WAIT : beginm_axi_araddr = r_addr ; m_axi_arvalid = 1 ; m_axi_rready = 0 ; r_data = 0 ; end R_BURST : beginm_axi_araddr = 0 ; m_axi_arvalid = 0 ; m_axi_rready = 1 ; r_data = m_axi_rdata ; end R_END : beginm_axi_araddr = 0 ; m_axi_arvalid = 0 ; m_axi_rready = 1 ; r_data = 0 ; end default : beginm_axi_araddr = 0 ; m_axi_arvalid = 0 ; m_axi_rready = 0 ; r_data = 0 ; end endcaseendendmodule