最近我开始学习PYNQ板和Vivado开发流程,与之前接触的Quartus开发流程不同,Vivado开发主要集中在IP核的设计和集成上,通过IP核的调用连接实现目标功能。在查阅资料的过程中,我发现大部分PYNQ的入门教程都使用HLS高级语言综合作为起步项目,而基于Verilog等RTL原语开发的教程较少。此外,一些教程已经过时,不再适用于当前的软件版本。因此,我写下这篇文章,记录我作为新手小白的学习经验。
本文教程适用于Vivado 2022.1,并在搭载v3.0.1镜像的PYNQ-Z1板上验证可用。
前期准备
关于PYNQ板的连接和启动,官网已有详细说明,这里不再赘述。
为在Vivado中导入PYNQ Z1开发板,需要先下载开发板信息文件,并将其放置在{Vivado Dir}\data\xhub\boards\XilinxBoardStore\boards\Xilinx
目录下。
如果使用2021.2或更早版本的Vivado,板信息文件则存放在{Vivado Dir}\data\boards
目录下。
创建IP模板
在Vivado工程中选择工具栏中的Tools->Create and Package New IP
,在弹出的窗口中使用Create a new AXI4 Peripheral
创建一个带有AXI4接口的IP核模板,并配置接口参数,这里以功能较为简单的AXI4 Lite接口作为演示,最后选择Edit IP
打开生成的IP核工程,如果选择了其他选项,可以从Project Manager中的IP Catalog找到该工程,右键选择Edit in IP Packager
打开该IP核。
模板工程中含有两个文件,其中project.v
文件中定义了AXI总线的接口并例化了一个支持AXI总线通信功能的模块,project_AXI.v
文件具体实现了AXI总线功能,为了快速入门,我们重点关注其实现用户逻辑功能的寄存器操作部分,其中,最核心的寄存器是四个带有slv
前缀的寄存器(寄存器数量由之前接口设置中的Number of Registers
决定)与输出数据的reg_data_out
,模板实现的默认逻辑为:当向地址X
写入数据时,数据会保存在对应的slv_regX
中,而从地址X
读出数据时,会读取到slv_regX
中的数据;因此我们只需要对这些寄存器进行操作就可以借由模板中的方法实现通信的功能。
|
|
作为从机,在写逻辑中,会根据地址将数据存入对应的slv_reg
寄存器,通过将switch case内slv_reg
改为其他寄存器,可以改变写入寄存器的位置,不过在模板中slv_reg
仅用于发送与接收,为避免错误,建议不要直接修改模板内容,而在其他时序逻辑中转存其值。另外注意这里的default语句理论上是不会运行的,因此更改此处的赋值左寄存器并不会将写入数据储存到新位置处。
|
|
而在读逻辑中,首先当地址位变动时,会将指定寄存器数据读入reg_data_out
中,并在接下来的读时序中将reg_data_out
内数据送出。因此,可以修改switch case内赋值语句右值来将我们需要的寄存器数据通过指定地址读出。
|
|
编写IP逻辑
这里我们简单实现一个计算两数平均值的模块,
|
|
同时,将读逻辑中的2'h2 : reg_data_out <= slv_reg2;
修改为2'h2 : reg_data_out <= average_reg;
使计算结果可以通过访问0b1000
地址读出。
编写完成,依次运行Synthesis、Implement,验证无误后,可以在Package IP
页的Review and Package
中选择Re-Package IP
重新生成IP核。
调用IP核
返回原工程,在Block Design中加入封装好的IP核和ZYNQ7 PS,自动连线,Vivado会帮我们添加时钟和AXI控制器。
保存Design,在Sources
中右键选择Create HDL Wrapper
让Vivado自动生成一个含有设计例化的顶层文件,综合实现生成bit流。
上板验证
为在开发板上调用该IP核,需要使用Vivado生成三个文件:
.bit
文件:该文件可视作可执行文件,在PYNQ板上通过Overlay
导入,生成在{Project Dir}\{Project}.runs\impl_1\{Top File}.bit
处;.hwh
文件:硬件描述文件,包含有对PYNQ各模块的配置,默认生成在{Project Dir}\{Project}.gen/sources_1/bd/{Block Design}/hw_handoff/{Block Design}.hwh
处;.tcl
文件(可选):早期版本的硬件描述文件,可读性较.hwh
文件可读性更高,需要在工具栏File->Export->Export Block Design
生成。
随后将.bit
文件与.hwh
文件改为同一名称,移动到PYNQ板内同一目录下,PYNQ默认将Overlay保存在/home/xilinx/pynq/overlays
目录下。
在早期版本中,需要将.bit
文件与同名.tcl
上传至PYNQ板,不需要.hwh
文件。
PYNQ板中,PS层与PL层的交互通过内存映射实现,因此我们需要知到挂载IP核对应的内存基址,在.tcl
文件中,找到内存映射部分,可以看到average_0/S00_AXI
对应的基址为0x43C00000
,掩码为0x0000FFFF
。
|
|
而在.hwh
文件中,可以找到对应模块配置内的PARAMATERS
部分,同样可以读出基址和地址范围:
|
|
最后,在jupyter notebook
中,通过Overlay
加载.bit
文件,通过MMIO
读写调用我们的IP功能,演示效果如下:
为方便调用,我们可以为其封装一个接口,如:
|
|