写数据
一:地址发送阶段
在写数据过程中,主机的地址连接在s_axi_awaddr总线上,同时将s_axi_awvalid信号拉高,表示主机的有效地址信息已经在信道上等待从机完成接收。同时等待从机发出的接受响应,当从机发送的s_axi_awready有效(拉高)时表示从机允许接收地址信息。从接口只在s_axi_awvaild和s_axi_awready同时有效时才能完成地址信息的接收,即完成主接口的写地址发送
。 **awvalid
**写地址有效是主机发出的,主机来定义写入的数据是否是有效
**awready
**地址接收有效是从机发出的,从机来定义是否可以为有效接收
二:数据写入阶段
主接口发送完地址信息后,准备写入数据,将待写入的数据置于s_axi_wdata总线上(s_axi_wstrb
表示写入选通吸信号,默认为11,表示写入数据均可用),并将s_axi_wvalid置为有效(拉高),表示数据已经在信道上等待从机发出的写入响应信号,进而写入从接口。从接口将s_axi_wready信号拉高,表示从接口可以被写入数据了。**当s_axi_wavaild和s_axi_wready信号同时为1后,表示完成了数据写入**
三:响应接收阶段【响应信号表示接收数据是否为有效数据,但完成响应被主机知晓,也需要有响应的有效信号】
主接口完成数据写入后,主机
把 s_axi_bready信号拉高(给从机一个我可以接收响应了 的信号),等待从机接口的响应信号。从接口的响应信号s_axi_bresp[1:0]用2‘b00表示数据信道的数据写入成功,即OKEY
,从机接口发出的s_axi_bresp响应信号 的有效信号s_axi_bvaild为1时才表示响应有效。
主机的s_axi_bready=1,从机的s_axi_bresp[1:0]=2‘b00,s_axi_bvaild=1,同时满足表示主机接口确认从接口完成了数据的写入。
以上过程的结束表示一次完整的基于AXI4_Lite接口的写寄存器过程。
读数据
一:地址发送:
**主机
将要读入的地址输入到s_axi_araddr总线上,同时将**s_axi_arvalid**
信号拉高。表示主机的地址已经在信道上等待从接口完成接收,同时等待从
接口发出s_axi_arready
**信号,当从接口发出的s_axi_arready信号有效时,表示从接口允许接收地址信息。**从接口只在s_axi_arvaild信号和s_axi_arready同时有效时才能完成信息接收,即完成主接口的读地址发送。**
二:数据接收:
**主机**
发送完地址请求后,发送接收数据请求信号,将**s_axi_rready**
信号拉高,表示主机可以接收数据了。从接口接收到主接口的准备ready信号后给出响应,在s_axi_rdata总线上发送主机请求的数据,同时把**s_axi_rvaild信号拉高**
,表示s_axi_rdata数据有效,主机根据s_axi_rvaild信号 有效 接收数据,完成数据的读过程。
以上即为AXI4-Lite的读写时序。
assign S_AXI_BRESP = 2'b00;
assign S_AXI_RRESP = 2'b00;
读写的有效响应信号均有从机发出【从机告诉主机】,00表示为无误
代码分析
写寄存器
是否可以写入寄存器取决于四个信号
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
- [ ] 因为本实现中写地址通道和写数据通道是严格一对一的关系,
**所以 wready 的信号的产生和 awready 信号在同一个周期中进行**
,判断 wvalid 与 awvalid 同时为高 。 - [ ] 如果实现的是支持突发传输的 AXI-Full 协议,那么写数据将和写地址就失去了这种一一对应的关系。(一次地址传输对应多次数据传输)
所以**wready 和 awready
** 同时有效,使得数据传输使能slv_reg_wren 有效,在下一个时钟周期的上升沿发生数据写入
在下一个时钟周期上升沿,axi_bvalid 开始有效,然后等待主机发来S_AXI_BREADY
axi_awready 在一个 S_AXI_ACLK 时钟周期内被置位
**always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awready <= 1'b0;
aw_en <= 1'b1;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
begin
axi_awready <= 1'b1;
aw_en <= 1'b0;
end
else if (S_AXI_BREADY && axi_bvalid)
begin
aw_en <= 1'b1;
axi_awready <= 1'b0;
end
else
begin
axi_awready <= 1'b0;
end
end
end**
与此同时 axi_awaddr 实现地址写入 ,地址来源于 S_AXI_AWADDR
**always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awaddr <= 0;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
begin
// Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end
end
end
————————————————————————————————————————————————————————————————————————————————————————**
axi_wready //axi_wready is asserted for one S_AXI_ACLK clock cycle when both
//S_AXI_AWVALID and S_AXI_WVALID are asserted.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_wready <= 1'b0;
end
else
begin
if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
begin
// slave is ready to accept write data when
// there is a valid write address and write data
// on the write address and data bus. This design
// expects no outstanding transactions.
axi_wready <= 1'b1;
end
else
begin
axi_wready <= 1'b0;
end
end
end
**————————————————————————————————————————————————————————————————————————————————————————**
在完成传输,即写数据/地址通道完成握手后的下一周期,从机置起 bvalid 信号,
并在 bresp 信号上给出 'OK' 信号。在响应通道完成握手后,置低 bvalid 完成响应操作。
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_bvalid <= 0;
axi_bresp <= 2'b0;
end
else
begin
if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
begin
// indicates a valid write response is available
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0; // 'OKAY' response
end // work error responses in future
else
begin
if (S_AXI_BREADY && axi_bvalid)
//check if bready is asserted while bvalid is high)
//(there is a possibility that bready is always asserted high)
begin
axi_bvalid <= 1'b0;
end
end
end
end
读寄存器
assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
always @(*)
begin
// Address decoding for reading registers
case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
2'h0 : reg_data_out <= slv_reg0;
2'h1 : reg_data_out <= slv_reg1;
2'h2 : reg_data_out <= slv_reg2;
2'h3 : reg_data_out <= slv_reg3;
default : reg_data_out <= 0;
endcase
end
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rvalid <= 0;
axi_rresp <= 0;
end
else
begin
if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)//在slv_reg_rden 读使能有效时
begin//告知完读取的地址,axi_rvalid 有效,一直保持到主机发出S_AXI_RREADY
// Valid read data is available at the read data bus
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0; // 'OKAY' response
end
else if (axi_rvalid && S_AXI_RREADY)
begin
// Read data is accepted by the master
axi_rvalid <= 1'b0;
end
end
end
// Output register or memory read data
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rdata <= 0;
end
else
begin
// When there is a valid read address (S_AXI_ARVALID) with
// acceptance of read address by the slave (axi_arready),
// output the read dada
if (slv_reg_rden)
begin
axi_rdata <= reg_data_out; // register read data
end
end
end**