本文主要演示针对PYNQ移植的 Vivado 硬件工程搭建。
因为我暂时对PYNQ的理解不是很深入,所以仅先增加基础的功能 像是UART 和 NET网络功能,先想办法在最短的时间内验证硬件是否可以跑通PYNQ,等熟悉后再后续完善例如HDMI,USB等功能。 大家也可以在此基础上自行研究。
另外由于PYNQ 的 系统和PL是可以相互独立的,所以后续像是增加EMIO等功能,对整个PYNQ 不需要重新进行编译了。
硬件系统构建(Vivado工程)
vivado 主要需要增加 ZYNQ CORE , EMIO UART, EMIO ETH, USB,SD的功能。
工程创建
1)打开Vivado 新建一个项目, 新建一个VIVADO 工程,打开软件 选中Create Project, 如下图所示
![](http://www.hellofpga.com/wp-content/uploads/2021/07/Create-Project.png)
2)点击NEXT ,在出现的第二个对话框“Project name”中输入工程名;在“Project location”中选择保存路径;勾选“Create project subdirectory”(默认),最后点击“Next” 备注,所有的路径均不能出现中文名称
3)点击 RTL PROJECT 选项,点击NEXT
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image.png)
4) 第四步Add Sources 选项直接留空,NEXT
5)第五步Add Constraints 选项直接留空,NEXT
6)选择芯片型号 XC7Z020CLG484-1
![](http://www.hellofpga.com/wp-content/uploads/2023/04/image-3-1024x846.png)
7)确认所选信息 点击“Finish”,完成vivado的工程创建
之后 工程就新建好了, vivado 进入到开发界面
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-172-1024x738.png)
Block Design 部分创建
此处需要创建一个ZYNQ CORE ,并在ZYNQ CORE中设置DDR ,网络,USB 以及UART等参数
UART此处用 EMIO方式连接
1)创建一个BLOCK设计
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-173.png)
2)搜索并添加ZYNQ7 Processing System,添加ZYNQ7 PROCESSING SYSTEM模块
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-174.png)
软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
![](http://www.hellofpga.com/wp-content/uploads/2022/11/image-175.png)
3)依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K256M16RE-125,数据位宽选择16bit 最后点击“OK”,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2023/01/image-70.png)
因为工程暂时用不到 AXI功能,所以可以先禁用AXI功能
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-131.png)
4) 这里把ENET0通过EMIO引出来 ,并且选中MDIO功能
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-125.png)
之后点选OK 来保存ZYNQ的配置
5)由于 ZYNQ的PS 调用EMIO方式 默认输出是GMII,而我们的网络部分芯片 RTL8211是 输出RGMII的,所以这里我们需要增加一个 GMII和RGMII转换的IP模块 (Gmii to Rgmii)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-126.png)
打开 GMII TO RGMII模块 设置更改成下面
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-127.png)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-128.png)
6) 又因为GMII TO RGMII 是高电平复位 ,但是ZYNQ 是输出低电平复位的,所以这里需要增加一个反相器(搜索utility, 在检索出来的选项里 选择 utility vector logic)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-129.png)
在设置页里改成 not(反相器)将位宽改成1
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-130.png)
7) 按下图方式连接好各个模块(复位 时钟 网络)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-132.png)
8)并通过右键 然后选择Make external 的方式引出RGMII 和MDIO_PHY功能引脚
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-133.png)
9)由于我们的板上网络部分的时钟25M单独有晶振控制了,所以这里不需要额外引出25M时钟
10)这里还要对Z7的模块进行一个修改,因为gmii to rgmii 模块的clkin 在手册上写要求是200mhz,所以我们这里需要对ZYNQ核的输出时钟频率进行修改
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-135.png)
重新双击ZYNQ的核,将FCLK_CLK0的频率改成200
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-136.png)
11)添加UART功能(用于Petalinux 的命令行输出)
由原理图可知, 主板的UART功能接在 ZYNQ PL端的 L17脚和M17脚了,即 ZYNQ的TX是 连接L17,ZYNQ的RX是连接M17 (备注 V1.0板子上的丝印 TX 和 RX标反了,以原理图为准)
![](http://www.hellofpga.com/wp-content/uploads/2023/04/image-44-1024x181.png)
使能UART 0 并在IO选项里选择EMIO方式
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-118.png)
12)添加使能SD功能,用于linux 系统的TF卡启动用
![](http://www.hellofpga.com/wp-content/uploads/2023/08/image-59.png)
13) 添加USB 功能
(备注 SL版本的硬件不带USB 的功能,这里为了和SP资料可以共用,所以默认都添加USB选项,并不会有影响)
勾选USB 0功能
![](http://www.hellofpga.com/wp-content/uploads/2023/08/image-60.png)
因为我们的USB Phy的复位部分是接在MIO46管脚上的,所以这里还需要使能ZYNQ的MIO功能,并且在下方的USB 0 RESET选项里勾选 MIO46 复位方式选择低电平复位。 (因为我们没有用到I2C功能,所以I2C复位的选项去除)
![](http://www.hellofpga.com/wp-content/uploads/2023/03/image-2-1024x342.png)
13) 所有的都完成后点选 Run Block Automation,完成后续自动布线
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-137.png)
![](http://www.hellofpga.com/wp-content/uploads/2023/01/image-83.png)
14)引出UART 信号,因为我们增加了EMIO 的UART,所以这里需要将UART的引脚引出 ,右键选择ZYNQ模块的UART_0,然后选择Make External
![](http://www.hellofpga.com/wp-content/uploads/2023/04/image-32.png)
15)创建硬件描述,source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示(这一步的作用相当于将图纸转换成对应的硬件描述语言的功能)
![](http://www.hellofpga.com/wp-content/uploads/2022/10/image-138.png)
16)编写好代码后 对代码进行编译
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-10.png)
18)添加约束文件 对管脚 和 电平进行约束, 尤其要注意 最下面的时序约束部分 一定要添加,不然大概率无法ping通
set_property PACKAGE_PIN G21 [get_ports MDIO_PHY_0_mdc] set_property PACKAGE_PIN H22 [get_ports MDIO_PHY_0_mdio_io] set_property PACKAGE_PIN A22 [get_ports {RGMII_0_rd[0]}] set_property PACKAGE_PIN A18 [get_ports {RGMII_0_rd[1]}] set_property PACKAGE_PIN A19 [get_ports {RGMII_0_rd[2]}] set_property PACKAGE_PIN B20 [get_ports {RGMII_0_rd[3]}] set_property PACKAGE_PIN A21 [get_ports RGMII_0_rx_ctl] set_property PACKAGE_PIN B19 [get_ports RGMII_0_rxc] set_property PACKAGE_PIN E21 [get_ports {RGMII_0_td[0]}] set_property PACKAGE_PIN F21 [get_ports {RGMII_0_td[1]}] set_property PACKAGE_PIN F22 [get_ports {RGMII_0_td[2]}] set_property PACKAGE_PIN G20 [get_ports {RGMII_0_td[3]}] set_property PACKAGE_PIN G22 [get_ports RGMII_0_tx_ctl] set_property PACKAGE_PIN D21 [get_ports RGMII_0_txc] set_property PACKAGE_PIN M17 [get_ports UART_0_0_rxd] set_property PACKAGE_PIN L17 [get_ports UART_0_0_txd] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdc] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_PHY_0_mdio_io] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_rd[3]}] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rx_ctl] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_rxc] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {RGMII_0_td[3]}] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_tx_ctl] set_property IOSTANDARD LVCMOS33 [get_ports RGMII_0_txc] set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_rxd] set_property IOSTANDARD LVCMOS33 [get_ports UART_0_0_txd] set_property SLEW FAST [get_ports {RGMII_0_td[0]}] set_property SLEW FAST [get_ports {RGMII_0_td[1]}] set_property SLEW FAST [get_ports {RGMII_0_td[2]}] set_property SLEW FAST [get_ports {RGMII_0_td[3]}] set_property SLEW FAST [get_ports RGMII_0_tx_ctl] set_property SLEW FAST [get_ports RGMII_0_txc] create_clock -period 8.000 -name RGMII_0_rxc -waveform {0.000 4.000} [get_ports RGMII_0_rxc] set_clock_groups -logically_exclusive -group [get_clocks -include_generated_clocks {gmii_clk_25m_out gmii_clk_2_5m_out}] -group [get_clocks -include_generated_clocks gmii_clk_125m_out]
17. 修改之后 点击 Generate Bitstream 进行综合以及生成Bit 文件
![](http://www.hellofpga.com/wp-content/uploads/2021/07/image-18.png)
等待布线综合完成
11)File→Export→Export hardware…在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-20.png)
![](http://www.hellofpga.com/wp-content/uploads/2021/08/image-24.png)
在文件夹下找出我们的bit 和hdf 文件
1) 在下列路径中找到我们的bit 文件,备注,一般在 下列路径中 <project_name>.runs\impl_1<project_name>_wrapper.bit
也可能在impl_2 impl_3中 自己根据自己的目录查看 其中<project_name>为你在Vivado中所命名的工程名
![](http://www.hellofpga.com/wp-content/uploads/2023/08/image-61-1024x319.png)
2) 在下列路径中找到我们的hdf文件,备注,一般在 下列路径中
<project_name>.sdk<project_name>_wrapper.hdf
其中<project_name>为你在Vivado中所命名的工程名
![](http://www.hellofpga.com/wp-content/uploads/2023/08/image-62-1024x222.png)
复制上述两个文件出来 ,修改两个文件的文件名为base.bit 以及system.hdf,其中bit流文件用于FPGA配置,hdf文件用于对已建立的Soc系统进行描述
我是在工程文件夹下又创建了个 TEMP文件夹 用来存放这两个文件 供后续使用
![](http://www.hellofpga.com/wp-content/uploads/2023/08/image-63.png)
至此,根据我们板子的PYNQ 准备工作 Vivado 硬件工程搭建已经完成 。
以下是本节调整的Vivado 工程,其中TEMP文件夹里是对应的 bit 和 hdf文件。
pynq 在板子上,如下路径,创建一个eth0 文本文件:
root@pynq:/etc/network/interfaces.d# more eth0
内容:如下两行,就能自动获取IP了。
auto eth0
iface eth0 inet dhcp
auto eth0
eth0 inet dhcp
auto eth0
iface eth0 inet dhcp