Zynq开发实践(FPGA之第一个vivado工程)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
数字电路设计,如果仅仅是写写代码,做做verilog仿真,那么其实是不需要转移到fpga上面的。这就好比是算法工程师,他做好了算法,写好了matlab仿真之后,如果仅仅是为了发论文,这个时候其实目的已经达到了。但是我们最终是需要用verilog做产品的,也就是所有的电路都要port到fpga上的,这个时候就要想办法创建fpga工程,下载程序了。
1、从ise到vivado、vitis
我们使用的芯片是zynq,主要是7010和7020。最早xilinx fpga编译的工具叫ise,它只能做fpga的开发,现在加了arm之后,ise变成了vivado,最新的软件叫vitis。相比较原来的软件,vivado不仅安装大小大了很多,功能也多了不少,它既可以做fpga的开发,还可以做arm的开发、hls的开发。如果不涉及到linux系统的开发,vivado windows版本其实可以覆盖所有的开发内容。
2、vivado的开发步骤
目前为止,我们使用vivado还是先做fpga方面的开发。一个fpga工程在构建之前,最好已经做好了仿真方面的测试。比如我们之前做的iverilog+vvp+gtkwave就是仿真测试。如果通想过不停编译fpga工程来进行在线测试,效率是非常低的。
一般vivado的开发步骤分成这三个步骤,首先是综合,也就是把verilog语言转变成各种网表。其次是实现布局布线,也就是把这些网表映射到fpga的硬件资源上面,中间会涉及到各种条件的约束。最后就是bitstream的生成。有了这个bitstream,就可以下载到具体的fpga上面,检测一下执行效果了。
3、vivado最重要的优点就是软硬协同开发
之前用ise开发fpga,大部分就是纯数字的电路开发。但是vivado的开发思路有了很大的转变。就拿zynq来说,由于有硬核arm和mio多功能接口,大部分外设、协议开发的工作其实都可以arm+软件来完成。这个时候fpga部分就可以做一些算法加速、硬件扩展的工作。因为此时fpga做成的ip就可以为cpu所调用,这样整个系统又灵活、效率又高。ps,也就是arm部分可以专注于业务和流程,而pl,也就是fpga专注于性能和接口拓展,两者紧密合作,做自己擅长的工作即可。以前虽然也这么做,但是两者是通过分列式元器件实现的,现在是合二为一了。
4、先fpga,再block design,最后sdk开发
很多ip其实是vivado自带的,比如pll、rom、ram、fifo、ddr contrller、dma这些。但是很多行业特定的算法,都是没有的,这部分就要自己写。所以我们做好fpga开发之后,一般就会套一个axi接口,这样就可以为cpu所调用。
所谓的block design,就是从数字电路层面构建一个系统。里面有arm cpu,有reset系统,有axi总线,有dma,还有各种各样的外设ip、算法ip,最后把它们串联成系统,构建一个超级fpga工程。这样的设计既有系统性,还有灵活性。
最后就是sdk开发,最初的时候可以专注于裸机开发,或者是rtos开发。如ps自带的mio接口,使用的也是固化ip,类似于gpio、uart、iic、sd、eth部分,这部分完全不需要pl的参与,就和mcu开发是一样的。如果是ps端口不够,就可以用pl拓展端口,或者直接把pl的算法ip导入进来,做好驱动,做好dma数据收发,这样ip就可以为我们所用了。
5、第一个vivado工程
明确了未来的方向,目前为止我们还是以fpga为主。fpga本身也是可以单独进行arm开发,或者是单独进行fpga开发,只不过arm+fpga融合是效率最高的方式。如果是纯fpga开发,只需要注意三点就可以了,第一点就是开始的时候,一定要注意好芯片类型的选择。比如假设soc类型是7020clg400-2,结果后续端口选择了其他soc的pin脚,很容易出现warning,或者直接bitstream生成失败。
第二点,就是准备好verilog代码。这部分代码最好是之前仿真测试好的,这里直接copy粘贴过来即可。不要指望全部下载到fpga进行调试,这个效率是非常慢的。一般第一个verilog都是点灯程序,那么可以仿真测试好,再copy过来即可。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/09/11 22:07:11
// Design Name:
// Module Name: led
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////module led(input clk,input rst,output reg[3:0] led);reg[15:0] counter;always@(posedge clk or negedge rst)if(!rst)counter <= 16'h0;else if(counter == 16'h7fff)counter <= 16'h0;elsecounter <= counter + 1;always@(posedge clk or negedge rst)if(!rst)led <= 4'b0001;else if(counter == 16'h7fff)led <= {led[2:0], led[3]};endmodule
第三,就是xdc约束文件。有了verilog还不够,我们还需要告诉fpga,哪部分是输入,哪部分是输出,clk是哪一个,只有这样才能进行全部的工作。xdc可以和verilog一样,一开始的时候就全部写好,直接Generate bitstream即可。
set_property PACKAGE_PIN H17 [get_ports {led[3]}]
set_property PACKAGE_PIN B20 [get_ports {led[2]}]
set_property PACKAGE_PIN C20 [get_ports {led[1]}]
set_property PACKAGE_PIN G14 [get_ports {led[0]}]
set_property PACKAGE_PIN H16 [get_ports clk]
set_property PACKAGE_PIN R19 [get_ports rst]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports rst]
create_clock -period 20.000 -name clk -waveform {0.000 10.000} [get_ports clk]
其实不光是vivado,其他厂家的eda基本上也是这么一个流程。只是过程可能会多一个仿真,比如modelsim的仿真,只是我们自己使用了iverilog,所以这一步就可以跳过去了。等到bitfile生成好了,就可以继续准备后面的验证测试了。