学校语言文字网站建设,优惠券小程序源码,网站建设项目可行性分析报告,全国工商网站查询企业信息本系列我想深入探寻 AXI4 总线。不过事情总是这样#xff0c;不能我说想深入就深入。当前我对 AXI总线的理解尚谈不上深入。但我希望通过一系列文章#xff0c;让读者能和我一起深入探寻 AXI4。在本系列先前的文章中#xff0c;我们首先通过协议 specification 了解协议的接…本系列我想深入探寻 AXI4 总线。不过事情总是这样不能我说想深入就深入。当前我对 AXI总线的理解尚谈不上深入。但我希望通过一系列文章让读者能和我一起深入探寻 AXI4。在本系列先前的文章中我们首先通过协议 specification 了解协议的接口与机制并通过操作一个 AXI 接口的 RAM IP 进行了一番实战。从协议机制上来说协议的制定者权衡协议的使用场景主从机接口性能等各方面的需求与限制以及实现的难度制定了这些规则。从笔者个人的经验来说对于一个协议把手册打印出来 - 翻烂 - 没人比我更懂这个协议了误翻烂可不是了解一个协议最有效的手段最重要的还是针对协议的实践。通过操作 AXI 接口的 IP 可以熟悉协议的接口。而通过实现一个协议的接口模块可以更深入地了解协议。本文将借助 Xilinx 提供的 AXI 接口代码实现一个 AXI-lite 接口模块了解协议接口机制的实现。Vivado 提供的接口代码在 Vivado 中使用 IP 编辑器创建一个 AXI 接口的 IP就可以获取到 Xilinx 在创建模板中提供的接口代码这里简单地纪录下创建过程。首先在 Tools 中选择 创建打包新 IP 菜单选择建立一个 AXI4 外设。在接口界面添加 AXI 接口。这里的接口可选作为主机或者从机的 AXI-FullAXI-Lite 或者 AXI-Stream 协议本文选择 32 位 AXI-Lite 从机作为例子。位宽按照协议规定可以在 32 位和 64 位之间进行选择。在创建完 IP 核后.....没错就是什么都不会发生。如果要编辑 IP 核或者像本文要做的那样查看 IP 的 RTL 代码那么在 IP catalog 选项中找到刚刚新建的 IP 核一般在 User Repository 选项下可以找到。右键-在 IP Packager 中编辑。使用 IP Packager 编辑会打开一个新的基于 创建的 IP 核的 Vivado 工程在这个工程中可以修改 IP 的信息参数接口以及 RTL 代码。在 source 中有一个 IP 核的顶层模块以及其下的 AXI-Lite 接口模块这就是我们要学习的接口实现 demo 了。AXI-Lite 接口模块信号列表Xilinx 提供的代码是非常好的学习材料编码规范并提供了详细的注释。首先可以学习的是参数化的设计在 IP 核代码中很多的参数经常需要变化比如在 GUI 界面中修改数据宽度等等这就需要完善的参数化设计。在声明端口之前可以使用#( )声明模块中的参数变量这里起到两个作用一是声明了参数ab二是赋予它们的默认值。注意一个以上参数的声明方式不同参数之间用 , 分隔这和声明端口的语法是一致的。但每个参数之前的 parameter 是不可以共用的。module my_module
#(
parameter a 1,
parameter b 2
)
(
端口声明
)在实例化模块时可以指定传入模块参数的值如下方实例化 my_module 模块命名为 m 在 #( ) 中向模块的参数传入数值模块中的参数 a,b 得到新的数值 10,20 。如果没有传值操作那么模块中参数 a,b 使用默认值 1,2。(这里注意实例名 m 的位置)//实例化 my_module
my_module
#(
.a(10),
.b(20)
)
m//实例名
(
端口连接
)在 AXI-Lite 模块中定义了两个参数数据总线的宽度以及地址总线的宽度。在后续的端口宽度定义中使用了这些参数。关于地址总线宽度为什么这里会是 4 将在后文中具体讨论。AXI-Lite 相比完整的 AXI 协议侧重于配置与状态信号传输不支持突发传输并在裁剪了用于内存访问的控制信号后大幅减少了端口数量便于集成。端口列表如下在代码中对每个端口的作用也有注释说明。AXI-Lite 接口信号列表CSR 寄存器所以系统中集成 AXI-Lite 接口模块的作用一般是什么在一个 SoC 系统中处理器需要配置大量的外设配置寄存器并从外设的状态寄存器中读取外设的状态进行初始化完成的判断等操作。AXI-Lite 总线就在 Configure Status Report 阶段作为主机和外设之间的桥梁。 AXI 接口模块会将来自主机一般是处理器的 AXI 数据锁存到寄存器中将数值转为为逻辑电平信号输出给外设模块。将来自外设的电平信号也锁存到寄存器中在主机发出读取请求时将状态寄存器的数值以 AXI 读数据的形式发给主机。 AXI 接口模块在系统中起到配置寄存器的配置输入和状态寄存器的状态上报这两方面的作用。reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;自然而然寄存器就是接口模块中的重要组成部分。在本模块中设定有 4 个寄存器每个寄存器位宽 32 位。寄存器的数量和位宽决定了地址总线的宽度。在计算机系统中地址以字节为单位4 个寄存器共有 16 个字节所以地址总线的宽度为Waddr log2(16) 4 bit总线操作中片选读写寄存器是以寄存器而不是字节为单位所以在通过地址判断所要读写的寄存器时只需要判断地址的高 2 bit片选出 4 个寄存器。在选择了寄存器之后也可以借助 WSTRB 字段控制对寄存器中的指定字节进行写操作这部分会在后文解析协议实现时详细讨论。WSTRB 信号只是指示从机屏蔽指定字节实际上这部分数据也是传输的协议规定传输必须以 32/64 位进行配置与状态寄存器可以分为只读只写可读可写三类。本文先讨论比较简单的只读只写情况即将整个32 bit 宽的寄存器从读/写功能上划分为两类所有 bit 对于主机而言全部为只读或者全部为只写。如何实现只写/只读寄存器假设寄存器 0 是一个只写寄存器寄存器 1 是一个只读寄存器首先在接口模块上定义输入输出端口,进行寄存器和电平信号的转换。在输出端口上输出内部存储器的内容或者将外部输入的逻辑电平赋予内部寄存器。总线接口实现逻辑会在主线产生读写请求时接口模块会将只写寄存器用总线数据更新或者将只读寄存器的数据更新到总线上实现寄存器信息的更新。output [31:0] reg0_out;
input [31:0] reg1_in;
assign reg0_out slv_reg0;
always (posedge clk)slv_reg1 reg1_in;接口时序实现AXI-Lite 协议同完整的 AXI 协议一样有 5 个独立的通道但由于不支持长度超过 1 的突发传输。Lite 协议中地址控制信息通道和数据通道严格满足一对一的关系。比如写地址通道写入地址以及控制信息后写数据通道只在下一有效时钟沿进行一次数据传输。地址信号传输完成信号作为下一时刻写数据的使能信号。下图表示了地址和数据流向代码也反映了这一时序关系。数据流向图AXI-Lite 协议上并没有特别定义传输的信号时序时序与 AXI-Full 协议 Burst 长度为 1 的情况相同。我们首先关注地址通道的逻辑读写地址通道的逻辑类似这里以稍复杂些的写地址通道为例。上述代码块通过控制 awready 信号完成了一次地址通道传输。逻辑检测 awvalidwvalid信号的电平当主机在写地址以及写数据通道上就绪时从机置高 awready 信号完成一次地址传输。与上 ~awready 是因为传输只需要在一次时钟上升沿 validready 信号同时置高即可在下一个周期从机需要负责将 awready 信号置低主机一般也会将 awvalid 信号置低不过这和从机就不相干了。在置高 awready 信号的条件中与上了 aw_en 变量这是为了使从机有控制地址通道传输的能力。在整个写传输周期中即地址-数据-写回复信号传输持续期间如果主机又发起了一次新的写传输请求置高 awvalidwvalid信号,那么此时 aw_en 信号为低从机将不会响应直至从机完成写回复结束本次传输后才回去响应下一次传输。AXI 写通道从机的守则根据上述协议中守则从机可以等待 AWVALID 或者 WVALID也可以等两者都就绪后再置起 AWREADY那么本实现中等待的就是两者都置起。也就是说虽然数据在地址后一周期传输但是在地址传输时数据已经就绪。在从机置起 awready 信号完成地址通道传输的同时从机也会从写地址上锁存当前的写地址。锁存的写地址会用于其后一个周期时刻来判断待写入的寄存器。有趣的是锁存地址的过程块可以合并到上述产生 awready 的过程块中去两者的使能条件相同。但从 Verilog 的哲学来说合则节省代码行数分则使逻辑功能划分更清楚。反正代码已经很多行了如果分开写能够更好体验逻辑功能那就分开写吧。接下来是写数据通道的时序产生同写地址通道类似从机的写数据通道中的 wready 信号也根据主机的 wvalid 信号产生。当 wvalid 为高则置高 wready 一个周期。因为本实现中写地址通道和写数据通道是严格一对一的关系所以 wready 的信号的产生和 awready 信号在同一个周期中进行判断 wvalid 与 awvalid 同时为高 。如果实现的是支持突发传输的 AXI-Full 协议那么写数据将和写地址就失去了这种一一对应的关系。一次地址传输对应多次数据传输本实现中最为重量级的一个部分是写数据的接收。首先判断读取写数据的使能条件。如前文所说写地址传输的后一个时刻为写数据传输写地址的完成的信号即作为写数据的使能信号。当写使能有效后逻辑首先根据写地址判断主机所要操作的寄存器。这里对写地址进行切片axi_awaddr[ADDR_LSBOPT_MEM_ADDR_BITS:ADDR_LSB]ADDR_LSB 与寄存器地址宽度相关32 位时为 2 64 位时为 3 。选择寄存器时不需要考虑地址的 [ADDR_LSB-1 : 0] 部分。 寄存器宽度为 32 位时每个寄存器 4 个字节选择寄存器时不需要判断地址低两位因为这是单个寄存器内部的字节地址。OPT_MEM_ADDR_BITS 与寄存器的数量有关2^(OPT_MEM_ADDR_BITS1) 寄存器数量。So地址线的位宽 ADDR_LSBOPT_MEM_ADDR_BITS 1以 4 个 32 位寄存器为例地址线的宽度 log2(4*4) 4 ,即 2 1 1、#注在根据地址选择寄存器时当然也可以对整个地址宽度进行判断但这样会造成资源的浪费。在完成寄存器的选择后将总线上已经就绪的写数据写入寄存器。如果不使用 STRB 信号对某些字节进行屏蔽那么这样就完事了: slv_reg0 S_AXI_WDATA;STRB 信号的作用是屏蔽一些字节的写入比如某个寄存器只有 8 bit或者 16 bit但寄存器的写入必须以 32 bit 为单位。完整写入 32 bit 势必会影响临近的其他寄存器此时可以使用 STRB 信号指定要写入的字节位置为 1屏蔽字节位置写 0 。代码中使用 for 循环以字节为单位判断 STRB 信号为 1则进行写入否则保持原寄存器值不变。完成一次写操作的最后一步是由从机在写回复通道上对此次传输进行评价...啊不 响应。在完成传输即写数据/地址通道完成握手后的下一周期从机置起 bvalid 信号并在 bresp 信号上给出 OK 信号。在响应通道完成握手后置低 bvalid 完成响应操作。这里我们的从机要么不给要就回复 OK,那么就不会有错误的情况发生么我的理解是在这个模块中和主机在芯片内部通信就隔几个寄存器几个 um 的距离一般不会出现传输错误的情况。再者说出现了错误我们从机也不知道啊。无辜.jpg笔者个人唯二遇到 AXI 回复错误的情况分别发生在 interconnect 和 DataMover IP 上。一是在 DataMover 上向 IP 写了错误的 CMDIP 回复 Internal error二是 interconnect 和从机的连接有问题interconnect 无法转发请求回复 decode error;这些错误回复在开发阶段对 Debug 是很有帮助的但生产环境中主机一般不会对这些错误回复进行处理。主机可能是这样一种佛系思想小错误不影响功能错了也就错了不管 Fatal 错误啊我 dump 了所以也不管好了后续的文章可能会对 response 做进一步分析。读通道逻辑和写通道类似本文就不再做进一步展开读者可以自行阅读代码。这里有一个建议即使笔者在完成了这篇文章的写作后再通过仿真也解决了一些疑惑。所以这里建议读者还是要亲自仿真一下获得第一手感性认识。在设计中集成接口模块在开发完成了一个寄存器总线接口模块后假装都是我们自己写的我们有两种方式将其集成到顶层设计中。以 IP 的形式打开我们先前提到的 IP Packager在 IP 的工程中集成用户其余的模块。完成集成仿真验证后就完成了整个功能 IP 的开发。这种方式适合将成熟的代码与接口进行集成。这种方式修改代码后需要更新 IP会有些繁琐。另一种适合在开发的过程中集成接口的方式是复制 IP 生成的接口模块代码到自己的工程中例化为一个模块使用。这样比较适合开发中的经常需要修改的顶层设计。结语本文我们通过学习 Xilinx 在 IP 接口中提供的 AXI-Lite 接口实现的模板有 AXI 的实现有了更深入的了解其实从 AXI-Lite 的角度来说很简单哈这一部分也是 AXI 协议的基础部分。在后续的文章中我们将对 AXI 协议的实现做更深入的了解。