平台:vivado2017.4
芯片:kintex-7 xc7k325tffg900-2
学习AXI总线。上一篇学习了AXI BRAM 和AXI_Stream FIFO。这里使用仿真看看他们之间的通信,为了更加深入的理解AXI总线。
前面分析了,AXI_BRAM的信号,支持突发模式。最大一次突发传输s_axi_awlen位宽的数据。这里即256个数据。
第一部分实现由AXI_BRAM产生256个数据,将其读出后,写入AXI_FIFO缓存。
第二部分实现由AXI_FIFO产生256个数据后,将其读出,写入AXI_BRAM缓存。
目录
第一部分
代码实现
第一部分,AXI_BRAM产生数据,将其读出后在写入AXI_FIFO。
产生数据时写入数据时,BRAM作为数据的接收方,我们需要向其提供地址,数据,传输次数,字节大小,突发类型,以及握手valid信号。将数据读出写入AXI_FIFO时,我们作为数据的接收方,需要向AXI_BRAM提供READY信号。
第一步将读通道信号引出。
module bram_control_burst#(
parameter U_DLY = 1
)
(
input wire lb_clk ,
input wire lb_rst ,
input wire reg_axi_write ,
input wire reg_axi_read ,
//AXI_BRAM接口
output wire [3:0] s_axi_rid ,//读IDtag。RID的数值必须与ARID的数值匹配
output wire [31:0] s_axi_rdata ,//读数据
output wire [1:0] s_axi_rresp ,//读响应。这个信号指明读传输状态
output wire s_axi_rlast ,//读取最后一个数据
output wire s_axi_rvalid ,//读取有效'1'读数据有效
input wire s_axi_rready //读数据就绪'1'主机就绪
);
在AXI_BRAM里面设置突发长度len:
localparam len = 8'hFF;//突发256个数据
AXI_BRAM测准备就绪。
下面准备TOP层代码,TOP层例化,AXI_BRAM和AXI_FIFO。将AXI_BRAM读出的数据当做AXI_FIFO写入的数据。
分析一下。
对于AXI_FIFO来说,AXI_BRAM里面读出的数据向AXI_FIFO里面写入。则AXI_BRAM作为数据的发送方,为AXI_FIFO提供DATA,VALID,LAST信号。
核心部分连接代码如下:
assign s_axis_tlast = s_axi_rlast;//AXI_FIFO一次传输的最后一个数据
assign s_axi_rready = s_axis_tready;//AXI_BRAM的读就绪
assign s_axis_tvalid = s_axi_rvalid;//AXI_FIFO的读有效
assign s_axis_tdata = s_axi_rdata;//数据
如上,AXI_BRAM作为数据的发送方,将s_axi_rlast,s_axi_rvalid,s_axi_rdata作为AXI_FIFO的直接输入。
这里需要将AXI_BRAM的valid作为AXI_FIFO的valid输入。
需要将AXI_FIFO的ready,作为AXI_BRAM的ready信号输入。这样即保证了握手的过程。
AXI_FIFO读取部分,当写入的数据计数器大于256时,开启AXI_FIFO读。
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_tready <= 1'b0;
else if(m_axis_tvalid == 1'b1 && m_axis_rd_req == 2'b01)
m_axis_tready <= 1'b1;
else if(rd_cnt == 8'd256)
m_axis_tready <= 1'b0;
else
m_axis_tready <= m_axis_tready;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_rd_req <= 2'b0;
else if(axis_wr_data_count >= 11'd256)
m_axis_rd_req <= {m_axis_rd_req[0],1'b1};
else
m_axis_rd_req <= m_axis_rd_req;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
rd_cnt <= 8'd1;
else if(m_axis_tready == 1'b1 && m_axis_tvalid == 1'b1)//同时有效读取
rd_cnt <= rd_cnt + 8'd1;
else
rd_cnt <= rd_cnt;
end
仿真分析
接下来看看仿真。
首先AXI_BRAM自己产生数据并写入。
AXI_BRAM数据读出。
AXI_FIFO数据写入。
AXI_FIFO数据读出。
AXI_FIFO读取完毕。
插入代码。
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2021/8/9 10:04:53
// File Name : .v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module axi_top#(
parameter U_DLY = 1
)
(
input wire lb_clk ,
input wire lb_rst ,
input wire reg_axi_write ,
input wire reg_axi_read
);
//--------------------------------------
// localparam
//--------------------------------------
//--------------------------------------
// register
//--------------------------------------
//reg [7:0] wr_cnt ;
reg [7:0] rd_cnt ;
//reg [1:0] last_cnt ;
reg [1:0] m_axis_rd_req ;
//--------------------------------------
// wire
//--------------------------------------
//axis_fifo interface
//wire wr_rst_busy ;
//wire rd_rst_busy ;
//axis_wr_interface
wire s_axis_tvalid ;//输入数据有效
wire s_axis_tready ;//axis_fifo准备好接收数据
wire [31:0] s_axis_tdata ;//axis_fifo接收的数据
wire s_axis_tlast ;//指示当前突发的最后一个数据
//reg [3:0] s_axis_tuser ;//
//aixs_rd_interface
wire m_axis_tvalid ;//fifo(主机)读数据有效
reg m_axis_tready ;//rd_en
wire [31:0] m_axis_tdata ;//读出的数据
wire m_axis_tlast ;//读出的数据最后一位
//wire [3:0] m_axis_tuser ;//自定义信息
//读写数据计数器
wire [10:0] axis_wr_data_count ;
wire [10:0] axis_rd_data_count ;
//axs_bram interface
//AXI_BRAM接口
wire [3:0] s_axi_rid ;//读IDtag。RID的数值必须与ARID的数值匹配
wire [31:0] s_axi_rdata ;//读数据
wire [1:0] s_axi_rresp ;//读响应。这个信号指明读传输状态
wire s_axi_rlast ;//读取最后一个数据
wire s_axi_rvalid ;//读取有效'1'读数据有效
wire s_axi_rready ;//读数据就绪'1'主机就绪
//--------------------------------------
// assign
//--------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
axis_fifo_control u_axis_fifo_control(
.wr_clk (lb_clk ),
.rd_clk (lb_clk ),
.rst (lb_rst ),
.axis_wr_data_count (axis_wr_data_count ),
.axis_rd_data_count (axis_rd_data_count ),
//全局信号
.wr_rst_busy ( ),
.rd_rst_busy ( ),
//axis_wr_interface
.s_axis_tvalid (s_axis_tvalid ),
.s_axis_tready (s_axis_tready ),
.s_axis_tdata (s_axis_tdata ),
.s_axis_tlast (s_axis_tlast ),
.s_axis_tuser (4'b0000 ),
//axis_rd_interface
.m_axis_tvalid (m_axis_tvalid ),
.m_axis_tready (m_axis_tready ),
.m_axis_tdata (m_axis_tdata ),
.m_axis_tlast (m_axis_tlast ),
.m_axis_tuser (m_axis_tuser )
);
bram_control_burst u_bram_control_burst(
.lb_clk (lb_clk ),
.lb_rst (lb_rst ),
.reg_axi_write (reg_axi_write ),
.reg_axi_read (reg_axi_read ),
//AXI_BRAM_rd_data接口
.s_axi_rid (s_axi_rid ),
.s_axi_rdata (s_axi_rdata ),
.s_axi_rresp (s_axi_rresp ),
.s_axi_rlast (s_axi_rlast ),
.s_axi_rvalid (s_axi_rvalid ),
.s_axi_rready (s_axi_rready )
);
//------------------------------------------------------------
//------------------------------------------------------------
assign s_axis_tlast = s_axi_rlast;//AXI_FIFO一次传输的最后一个数据
assign s_axi_rready = s_axis_tready;//AXI_BRAM的读就绪
assign s_axis_tvalid = s_axi_rvalid;//AXI_FIFO的读有效
assign s_axis_tdata = s_axi_rdata;//数据
//------------------------------------------------------------
//------------------------------------------------------------
自测试,fifo产生数据,先写后读
FIFO写,先等待tready信号有效,表示FIFO里面可以写入数据
//
//always@(posedge lb_clk or posedge lb_rst)
//begin
// if(lb_rst == 1'b1)
// begin
// s_axis_tvalid <= 1'b0;
// s_axis_tuser <= 4'd0;
// end
// else if(wr_cnt <= 8'd99 )
// s_axis_tvalid <= 1'b1;
// else
// s_axis_tvalid <= 1'b0;
s_axis_tvalid <= 1'b1;
//end
//
//always@(posedge lb_clk or posedge lb_rst)
//begin
// if(lb_rst == 1'b1)
// s_axis_tlast <= 1'b0;
// else if(wr_cnt == 8'd99 && last_cnt == 2'b00)
// s_axis_tlast <= 1'b1;
// else
// s_axis_tlast <= 1'b0;
//end
//
//
//always@(posedge lb_clk or posedge lb_rst)
//begin
// if(lb_rst == 1'b1)
// last_cnt <= 2'b00;
// else if(wr_cnt == 8'd99)
// last_cnt <= {last_cnt[0],1'b1};
// else
// last_cnt <= 2'b00;
//end
//
//
//always@(posedge lb_clk or posedge lb_rst)
//begin
// if(lb_rst == 1'b1)
// begin
// wr_cnt <= 8'd1;
// s_axis_tdata <= 32'd1;
// end
// else if(s_axis_tvalid == 1'b1 && s_axis_tready == 1'b1)
// begin
// wr_cnt <= wr_cnt + 8'd1;
// s_axis_tdata <= s_axis_tdata + 32'd1;
// end
// else
// begin
// wr_cnt <= wr_cnt;
// s_axis_tdata <= s_axis_tdata;
// end
//end
//
//FIFO读,作为接收方(从机)可以等待主机VALID有效后在拉高READY,这里我们不这样
//做,我们准备读一次读100个数据有停止,要求一次读100个数据
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_tready <= 1'b0;
else if(m_axis_tvalid == 1'b1 && m_axis_rd_req == 2'b01)
m_axis_tready <= 1'b1;
else if(rd_cnt == 8'd256)
m_axis_tready <= 1'b0;
else
m_axis_tready <= m_axis_tready;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_rd_req <= 2'b0;
else if(axis_wr_data_count >= 11'd256)
m_axis_rd_req <= {m_axis_rd_req[0],1'b1};
else
m_axis_rd_req <= m_axis_rd_req;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
rd_cnt <= 8'd1;
else if(m_axis_tready == 1'b1 && m_axis_tvalid == 1'b1)//同时有效读取
rd_cnt <= rd_cnt + 8'd1;
else
rd_cnt <= rd_cnt;
end
//------------------------------------------------------------
//------------------------------------------------------------
endmodule
第二部分
代码实现
做从AXI_FIFO里面产生数据,读出后,写入AXI_BRAM内。
首先AXI_FIFO内部自己产生数据。产生数据量为256个数据。数据产生完成后,将数据读出。这时将读出的数据接入AXI_BRAM的写数据通道上。将AXI_FIFO的m_axis_tready信号直接接入AXI_BRAM的写有效S_AXI_WVALID。
assign S_AXI_WDATA = m_axis_tdata;
assign S_AXI_WVALID = m_axis_tready;
assign S_AXI_WLAST = m_axis_tlast && m_axis_tvalid && m_axis_tready;
assign S_AXI_WSTRB = 4'b1111;
同时为了保证在数据写入AXI_BRAM之前写地址通道先握手成功。先判断AXI_FIFO里面是否写入了256个数据,在数据量达到后,使用m_axis_rd_req信号作为,AXI_BRAM写地址有效信号。
具体的操作如下。顶层TOP实现。
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2021/8/9 10:04:53
// File Name : .v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module axi_top#(
parameter U_DLY = 1
)
(
input wire lb_clk ,
input wire lb_rst ,
input wire reg_axi_write ,
input wire reg_axi_read
);
//--------------------------------------
// localparam
//--------------------------------------
//--------------------------------------
// register
//--------------------------------------
reg [15:0] wr_cnt ;
reg [7:0] rd_cnt ;
reg [1:0] last_cnt ;
reg [3:0] m_axis_rd_req ;
//--------------------------------------
// wire
//--------------------------------------
//axis_fifo interface
//axis_wr_interface
reg s_axis_tvalid ;//输入数据有效
wire s_axis_tready ;//axis_fifo准备好接收数据
reg [31:0] s_axis_tdata ;//axis_fifo接收的数据
reg s_axis_tlast ;//指示当前突发的最后一个数据
//reg [3:0] s_axis_tuser ;//
//aixs_rd_interface
wire m_axis_tvalid ;//fifo(主机)读数据有效
reg m_axis_tready ;//rd_en
wire [31:0] m_axis_tdata ;//读出的数据
wire m_axis_tlast ;//读出的数据最后一位
//wire [3:0] m_axis_tuser ;//自定义信息
//读写数据计数器
wire [10:0] axis_wr_data_count ;
wire [10:0] axis_rd_data_count ;
//axs_bram interface
//AXI_BRAM接口写
wire [31:0] S_AXI_WDATA ;
wire [3:0] S_AXI_WSTRB ;
wire S_AXI_WLAST ;
wire S_AXI_WVALID ;
wire S_AXI_WREADY ;
//
//AXI_BRAM接口读
//
wire [3:0] s_axi_rid ;//读IDtag。RID的数值必须与ARID的数值匹配
wire [31:0] s_axi_rdata ;//读数据
wire [1:0] s_axi_rresp ;//读响应。这个信号指明读传输状态
wire s_axi_rlast ;//读取最后一个数据
wire s_axi_rvalid ;//读取有效'1'读数据有效
wire s_axi_rready ;//读数据就绪'1'主机就绪
//--------------------------------------
// assign
//--------------------------------------
assign S_AXI_WDATA = m_axis_tdata;
assign S_AXI_WVALID = m_axis_tready;
assign S_AXI_WLAST = m_axis_tlast && m_axis_tvalid && m_axis_tready;
assign S_AXI_WSTRB = 4'b1111;
//------------------------------------------------------------
//------------------------------------------------------------
axis_fifo_control u_axis_fifo_control(
.wr_clk (lb_clk ),
.rd_clk (lb_clk ),
.rst (lb_rst ),
.axis_wr_data_count (axis_wr_data_count ),
.axis_rd_data_count (axis_rd_data_count ),
//全局信号
.wr_rst_busy ( ),
.rd_rst_busy ( ),
//axis_wr_interface
.s_axis_tvalid (s_axis_tvalid ),
.s_axis_tready (s_axis_tready ),
.s_axis_tdata (s_axis_tdata ),
.s_axis_tlast (s_axis_tlast ),
.s_axis_tuser (4'b0000 ),
//axis_rd_interface
.m_axis_tvalid (m_axis_tvalid ),
.m_axis_tready (m_axis_tready ),
.m_axis_tdata (m_axis_tdata ),
.m_axis_tlast (m_axis_tlast ),
.m_axis_tuser ( )
);
bram_control_burst u_bram_control_burst(
.lb_clk (lb_clk ),
.lb_rst (lb_rst ),
.reg_axi_write (m_axis_rd_req == 4'b0001 ),
.reg_axi_read ( ),
.S_AXI_WDATA (S_AXI_WDATA ),
.S_AXI_WSTRB (S_AXI_WSTRB ),
.S_AXI_WLAST (S_AXI_WLAST ),
.S_AXI_WVALID (S_AXI_WVALID ),
.S_AXI_WREADY (S_AXI_WREADY ),
//AXI_BRAM_rd_data接口
.s_axi_rid (s_axi_rid ),
.s_axi_rdata (s_axi_rdata ),
.s_axi_rresp (s_axi_rresp ),
.s_axi_rlast (s_axi_rlast ),
.s_axi_rvalid (s_axi_rvalid ),
.s_axi_rready (s_axi_rready )
);
//------------------------------------------------------------
//------------------------------------------------------------
//自测试,fifo产生数据,先写后读
//FIFO写,先等待tready信号有效,表示FIFO里面可以写入数据
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
begin
s_axis_tvalid <= 1'b0;
// s_axis_tuser <= 4'd0;
end
else if(wr_cnt <= 16'd255 )
s_axis_tvalid <= 1'b1;
else
s_axis_tvalid <= 1'b0;
// s_axis_tvalid <= 1'b1;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
s_axis_tlast <= 1'b0;
else if(wr_cnt == 16'd255 && last_cnt == 2'b00)
s_axis_tlast <= 1'b1;
else
s_axis_tlast <= 1'b0;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
last_cnt <= 2'b00;
else if(wr_cnt == 16'd255)
last_cnt <= {last_cnt[0],1'b1};
else
last_cnt <= 2'b00;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
begin
wr_cnt <= 16'd1;
s_axis_tdata <= 32'd1;
end
else if(s_axis_tvalid == 1'b1 && s_axis_tready == 1'b1)
begin
wr_cnt <= wr_cnt + 16'd1;
s_axis_tdata <= s_axis_tdata + 32'd1;
end
else
begin
wr_cnt <= wr_cnt;
s_axis_tdata <= s_axis_tdata;
end
end
//
//FIFO读,作为接收方(从机)可以等待主机VALID有效后在拉高READY,这里我们不这样
//做,我们准备读一次读100个数据有停止,要求一次读100个数据
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_tready <= 1'b0;
// else if(m_axis_tvalid == 1'b1 && m_axis_rd_req == 2'b0111)
else if(m_axis_tvalid == 1'b1 && S_AXI_WREADY == 1'b1)
m_axis_tready <= 1'b1;
else if(rd_cnt == 8'd256)
m_axis_tready <= 1'b0;
else
m_axis_tready <= m_axis_tready;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
m_axis_rd_req <= 4'b0;
else if(axis_wr_data_count >= 11'd256)
m_axis_rd_req <= {m_axis_rd_req[2:0],1'b1};
else
m_axis_rd_req <= m_axis_rd_req;
end
always@(posedge lb_clk or posedge lb_rst)
begin
if(lb_rst == 1'b1)
rd_cnt <= 8'd1;
else if(m_axis_tready == 1'b1 && m_axis_tvalid == 1'b1)//同时有效读取
rd_cnt <= rd_cnt + 8'd1;
else
rd_cnt <= rd_cnt;
end
//------------------------------------------------------------
//------------------------------------------------------------
endmodule
底层AXI_BRAM代码修改如下。
对于写地址通道,通过组合逻辑预先设置好需要突发的数据地址数据长度,数据位宽,以及突发模式。
对于写数据通道,将从AXI_FIFO里面引出来的数据接入写数据通道,同时注意为了握手传输数据,需要将AXI_BRAM的s_axi_wready信号作为作为AXI_FIFO读ready。
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2021/8/2 14:06:24
// File Name : .v
// Module Name :
// Called By :
// Abstract :
// v1.0对AXI_BRAM单独读写模块。
// v1.1更新对AXI_BRAM的突发读写。设置突发长度。
// v1.2实现AXI IP之间的互联。比如实现将AXI_BRAM里面我们生成的数据发送到
// AXI_FIFO里面去。
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ps / 1 ps
module bram_control_burst#(
parameter U_DLY = 1
)
(
input wire lb_clk ,
input wire lb_rst ,
input wire reg_axi_write ,
input wire reg_axi_read ,
//AXI_BRAM写接口
input wire [31:0] S_AXI_WDATA ,
input wire [3:0] S_AXI_WSTRB ,
input wire S_AXI_WLAST ,
input wire S_AXI_WVALID ,
output wire S_AXI_WREADY ,
//AXI_BRAM接口
output wire [3:0] s_axi_rid ,//读IDtag。RID的数值必须与ARID的数值匹配
output wire [31:0] s_axi_rdata ,//读数据
output wire [1:0] s_axi_rresp ,//读响应。这个信号指明读传输状态
output wire s_axi_rlast ,//读取最后一个数据
output wire s_axi_rvalid ,//读取有效'1'读数据有效
input wire s_axi_rready //读数据就绪'1'主机就绪
);
//--------------------------------------
// localparam
//--------------------------------------
//--------------------------------------
// register
//--------------------------------------
//--------------------------------------
// wire
//--------------------------------------
//全局信号
wire rsta_busy ;
wire rstb_busy ;
wire s_aclk ;//时钟
wire s_aresetn ;//复位
//写地址通道
wire[3:0] s_axi_awid ;//写地址ID,这个信号是写地址信号组的IDtag
wire[31:0] s_axi_awaddr ;//写地址
wire[7:0] s_axi_awlen ;//突发次数
wire[2:0] s_axi_awsize ;//一次传输字节数。一个时钟节拍传输的数据的最大位。s_axi_awsize = 3'b000,传输1byte。s_axi_awsize = 3'b001,传输2byte。s_axi_awsize = 3'b010,传输4byte。s_axi_awsize = 3'b011,传输8byte。s_axi_awsize = 3'b100,传输16byte。s_axi_awsize = 3'b101,传输32byte。s_axi_awsize = 3'b110,传输64byte。s_axi_awsize = 3'b111,传输128byte。
wire[1:0] s_axi_awburst ;//突发类型
wire s_axi_awvalid ;//握手信号,写地址有效。'1'有效
wire s_axi_awready ;//握手。写地址准备好,'1'设备准备好
//写数据通道
wire[31:0] s_axi_wdata ;//写入数据
wire[3:0] s_axi_wstrb ;//写阀门,WSTRB[n]表示的区间为WDATA[(8*n) + 7:(8*n)];说明:s_axi_wstrb[0]表示s_axi_wdata[7:0]有效。依次类推。
wire s_axi_wlast ;//最后一个数据
wire s_axi_wvalid ;//写数据有效
wire s_axi_wready ;//写数据准备就绪
//写请求通道
wire [3:0] s_axi_bid ;//响应ID,这个数值必须与AWID的数值匹配。
wire [1:0] s_axi_bresp ;//写入响应,这个信号指明写事务的状态。可能有的响应:OKAY,EXOKAY,SLVERR,DECERR
wire s_axi_bvalid ;//写响应有效。'1'有效
wire s_axi_bready ;//接收响应就绪,该信号表示主机已经能够接受响应信息。'1'主机就绪
//读地址通道
wire[3:0] s_axi_arid ;//读地址ID
wire[31:0] s_axi_araddr ;//低地址
wire[7:0] s_axi_arlen ;//读地址突发长度
wire[2:0] s_axi_arsize ;//一次传输字节数
wire[1:0] s_axi_arburst ;//突发类型
wire s_axi_arvalid ;//握手信号,读地址有效。该信号一直保持,直到ARREADY为高。'1'地址和控制信号有效。
wire s_axi_arready ;//握手信号,读地址就绪,指明设备已经准备好接收数据了。'1'设备就绪。
//读数据通道
//wire [3:0] s_axi_rid ;//读IDtag。RID的数值必须与ARID的数值匹配
//wire [31:0] s_axi_rdata ;//读数据
//wire [1:0] s_axi_rresp ;//读响应。这个信号指明读传输状态
//wire s_axi_rlast ;//读取最后一个数据
//wire s_axi_rvalid ;//读取有效'1'读数据有效
//reg s_axi_rready ;//读数据就绪'1'主机就绪
//system signal
wire lb_rst_n ;
//--------------------------------------
// assign
//--------------------------------------
//system signal
assign lb_rst_n = ~lb_rst;
assign s_aclk = lb_clk;
assign s_aresetn = ~lb_rst;
//assign s_axi_wlast = (c_state == write && write_cnt == len) ? 1'b1 : 1'b0;
//写地址通道
assign s_axi_awid = 4'b0000;
assign s_axi_awaddr = 32'b0;
assign s_axi_awlen = len;
assign s_axi_awsize = 3'b010;
assign s_axi_awburst = 2'b01;
assign s_axi_awvalid = reg_axi_write;
//写数据通道
assign S_AXI_WREADY = s_axi_wready;
assign s_axi_wvalid = S_AXI_WVALID;
assign s_axi_wlast = S_AXI_WLAST;
assign s_axi_wstrb = S_AXI_WSTRB;
assign s_axi_wdata = S_AXI_WDATA;
//写响应
assign s_axi_bready = 1'b1;
//读地址通道
assign s_axi_arid = 4'b0;
assign s_axi_araddr = 32'b0;
assign s_axi_arlen = len;
assign s_axi_arsize = 3'b010;
assign s_axi_arburst= 2'b01;
assign s_axi_arvalid= reg_axi_write;
//读数据通道
//------------------------------------------------------------
//------------------------------------------------------------
blk_mem_gen_0 u_double_ram (
//全局信号
.rsta_busy (rsta_busy ),
.rstb_busy (rstb_busy ),
.s_aclk (s_aclk ),
.s_aresetn (s_aresetn ),
//写地址通道
.s_axi_awid (s_axi_awid ),//写地址ID
.s_axi_awaddr (s_axi_awaddr ),//写地址
.s_axi_awlen (s_axi_awlen ),//突发次数
.s_axi_awsize (s_axi_awsize ),//一次传输字节数
.s_axi_awburst (s_axi_awburst ),//突发类型
.s_axi_awvalid (s_axi_awvalid ),//握手有效
.s_axi_awready (s_axi_awready ),//握手准备好
//写数据通道
.s_axi_wdata (s_axi_wdata ),//写入数据
.s_axi_wstrb (s_axi_wstrb ),//表示写字节通道保存有效,在每8位的写数据总线上有1位被选通。
.s_axi_wlast (s_axi_wlast ),//最后一个数据
.s_axi_wvalid (s_axi_wvalid ),//写数据有效
.s_axi_wready (s_axi_wready ),//写数据准备就绪
//写请求通道
.s_axi_bid (s_axi_bid ),//
.s_axi_bresp (s_axi_bresp ),//写入响应
.s_axi_bvalid (s_axi_bvalid ),//写响应有效
.s_axi_bready (s_axi_bready ),//已准备好写入响应
//读地址通道
.s_axi_arid (s_axi_arid ),//读地址ID
.s_axi_araddr (s_axi_araddr ),//低地址
.s_axi_arlen (s_axi_arlen ),//读地址突发长度
.s_axi_arsize (s_axi_arsize ),//一次传输字节数
.s_axi_arburst (s_axi_arburst ),
.s_axi_arvalid (s_axi_arvalid ),
.s_axi_arready (s_axi_arready ),
//读数据通道
.s_axi_rid (s_axi_rid ),
.s_axi_rdata (s_axi_rdata ),
.s_axi_rresp (s_axi_rresp ),
.s_axi_rlast (s_axi_rlast ),
.s_axi_rvalid (s_axi_rvalid ),
.s_axi_rready (s_axi_rready )
);
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
//------------------------------------------------------------
endmodule
仿真分析
AXI_FIFO写入数据。
AXI_FIFO将数据读出。
AXI_BRAM数据写入。
越使用,就越发现AXI总线的好用之处。再接再厉。