上周我们介绍到了AXI4从机的写过程,今天我们继续来实现一下AXI4从机的读过程。相关Verilog代码及环境相比上一篇文章有优化,公众号后台回复AXI4即可获取最新内容。
本篇文章结构如下所示,由于AXI4从机的读过程与上一篇中写过程具有较大的相似性,为了节约大家的时间就将其安排在了第二部分,已经了解过的朋友可以直接跳过看仿真验证的结果~
一、从机的内部寄存器设计
二、AXI4读从机的实现
三、仿真验证
从机的内部寄存器设计
支持AXI4总线的从机大致可以分为两种类型,一种是内存类型的从机(memory slave),一种是外设类型的从机(peripheral slave)。但是说到底,这两种类型的从机就是一个地址空间下的寄存器阵列,本质上没有区别。区别只在于内存类型的从机工作的内容就是将写入的数据存储,再按照地址索引读出,而外设类型的从机寄存器与外设本身的动作有关。
看下面的例子,外设从机中一个32位的寄存器存储三个flag信号,{29’d0,flag2,flag1,flag0},读取寄存器中的值读取到的是从机的状态,不论向这个寄存器写任何数据,读取到的始终是从机的状态。
那么此时写寄存器还可以使用吗?当然是可以的,但也不是必要的。
如果规定不能写寄存器,我们可以在CPU想要写该地址的寄存器时反馈错误的resp信号,将该寄存器配置为只读状态;
如果需要对寄存器进行写操作,我们也可以向其写入特定的值达到向从机发送指令的效果。
例如我们规定向寄存器中对应位写1则将对应的flag清零,当我们写入32’h0000_0002时,从机会接收到一个信号,从而将flag1重新置为0,此时读取这个寄存器读取到的flag1的值就会被置0。
本设计构造的是一个简单的存储式从机,至于外设式从机大家可以后台私信我提提想法,如果项目规模不大且有比较好的模板意义的话我会在实现之后分享给大家。
上篇文章已经说过,本次设计中的地址位宽为8位,也就是说整个存储空间有256bytes,设寄存器大小为32bits(4bytes),则整体有256/4=64个寄存器。我们先来实现一下有64个寄存器的RAM。为了整体模块易于维护,RAM模块单独出来作为一个子模块。
module RAM #(
parameter DATAWIDTH = 32,
parameter ADDRWIDTH = 6
)
(
input clk,
input wr_en,
input [ADDRWIDTH-1 : 0] wr_addr,
input [DATAWIDTH-1 : 0] wr_data,
input rd_en,
input [ADDRWIDTH-1 : 0] rd_addr,
output reg [DATAWIDTH-1 :0] rd_data
);
reg [DATAWIDTH-1 : 0] mem [0 : (1<<ADDRWIDTH)-1];
// write data to memory
always@(posedge clk)begin
if(wr_en)
mem[wr_addr] <= wr_data;
end
// read data from memory
always@(posedge clk)