跳转至

综合与实现

我们将通过一个完整的项目带大家体验 Vivado 开发流程,在这个项目里,我们将使用开发板上的 LED 制作一个简易流水灯。

Image title

流水灯效果图
注意

由于实验平台更新,vivado中创建项目时,需要选择的芯片型号变更为 xc7a35tfgg484-1,相应的,fpga平台应选择ZYNQ,约束文件应使用fpgaol_zynq.xdc。请大家注意!

Image title
Image title


2.1 代码设计

要如何实现上面的效果呢?我们可以思考下面的问题:

  1. 如何让指定的 LED 灯亮起?

    很简单,只需要令 led 变量为我们期望的 8bits 数值即可。

  2. 如何实现流水的效果?

    在我们的设计里,亮起的 LED 灯以一定的速度向左平移,如果已经到了最左侧的 7 号灯则会循环回到最右侧的 0 号灯。我们可以使用一个信号 shift 作为标志:当 shift 信号发出时,就让亮起的 LED 灯向左移动一格。

    怎么实现循环移动的效果呢?或许我们可以这样做:让 led 信号的最高位挪到最低位,其余位顺次左移。这样就可以写出下面的代码:

    1
    2
    3
    if (shift) begin
        led <= {led[6:0], led[7]};
    end
    
    思考

    如果让 LED 灯一次向左循环移动两格,对应的代码是什么样子呢?

  3. 如何控制流水灯的速度?

    现在我们只剩下 shift 信号没有确定了。我们可以每间隔一定的时间就发出一次 shift 信号,改变时间间隔就可以实现不同速度的流水灯。

    『每间隔一定的时间就发出一次信号』?这个模块我们好像已经在这里设计过了!

考虑完这三个问题,流水灯模块的 Verilog 代码也就呼之欲出了。

LED.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
module LED (
    input                   clk,
    input                   btn,
    output reg [7:0]        led
);

reg [31:0] count_1hz;
wire rst;
parameter TIME_CNT = 50_000_000;

assign rst = btn;   // Use button for RESET

always @(posedge clk) begin
    if (rst)
        count_1hz <= 0;
    else if (count_1hz >= TIME_CNT)
        count_1hz <= 0;
    else
        count_1hz <= count_1hz + 1;
end

always @(posedge clk) begin
    if (rst)
        led <= 8'b0000_1111;
    else if (count_1hz == 1) begin
        led <= {led[6:0], led[7]};
    end
end
endmodule

这里我们令计数器的上限值为 \(5\times10^7\),是因为开发板上的时钟频率是 100MHz。这样计数器每间隔 0.5s 就会发出一次信号,对应流水灯也向左移动一格。

接下来,请打开 Vivado,创建一个新的项目,随后创建一个新的设计文件 LED.v,写入上面的 Verilog 代码。你可以选择 Open Elaborated Design,以查看流水灯的 RTL 电路图。这些操作的具体细节可以参考 Lab2 的教程,这里就不再展开介绍。

2.2 ★ 综合与实现

上一次实验中,我们已经介绍了如何使用 Vivado 进行 RTL 分析与仿真。接下来我们将进入综合与实现的环节。

Image title

单击左侧的 Run Synthesis 即可开始综合(Synthesis)。在这一步,我们可以找到更多 warnings、critical warnings 和 errors,例如逻辑环路(自己的输出直接接到自己的输入)、多驱动(一个变量由多个 always 块或多个输入修改)等。

综合过程中也可以查看电路图,但这时的电路图大部分以查找表的形式出现,其结构与规模都和 RTL 电路有着较大的不同,因此很难找出问题。此外,为了更优的电路性能,综合出的电路也有可能把某一模块的元件安置到另一个模块里,所以在使用综合出的电路图查找问题时要关注这些细节。

Image title

在实现(Implementation)之前,我们需要一个额外的约束文件,用来指示模块输入输出端口和开发板端口之间的对应关系。由于开发板型号、配置不同,因此对应的约束文件也不同。本课程使用的约束文件可以在这里下载。

得到约束文件后,将其放入项目文件夹中,并在 Vivado 中添加设计文件 Constraints。

Image title

使用文件时,将需要连接接口的注释符号 # 去掉,改为对应模块接口的名字即可。例如,我们这次使用的约束文件如下:

## FPGAOL ZYNQ XDC v2.1
## device xc7a35tfgg484-1

## CLOCK
set_property -dict { PACKAGE_PIN V18  IOSTANDARD LVCMOS33 } [get_ports {clk}]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]

## LED
set_property -dict { PACKAGE_PIN B15   IOSTANDARD LVCMOS33 } [get_ports {led[0]}]
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports {led[1]}]
set_property -dict { PACKAGE_PIN C13   IOSTANDARD LVCMOS33 } [get_ports {led[2]}]
set_property -dict { PACKAGE_PIN B13   IOSTANDARD LVCMOS33 } [get_ports {led[3]}]
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 } [get_ports {led[4]}]
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports {led[5]}]
set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS33 } [get_ports {led[6]}]
set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports {led[7]}]

## SWITCH
#set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS33 } [get_ports {sw[0]}]
#set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS33 } [get_ports {sw[1]}]
#set_property -dict { PACKAGE_PIN D17   IOSTANDARD LVCMOS33 } [get_ports {sw[2]}]
#set_property -dict { PACKAGE_PIN C17   IOSTANDARD LVCMOS33 } [get_ports {sw[3]}]
#set_property -dict { PACKAGE_PIN C18   IOSTANDARD LVCMOS33 } [get_ports {sw[4]}]
#set_property -dict { PACKAGE_PIN C19   IOSTANDARD LVCMOS33 } [get_ports {sw[5]}]
#set_property -dict { PACKAGE_PIN E19   IOSTANDARD LVCMOS33 } [get_ports {sw[6]}]
#set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports {sw[7]}]

## BUTTON
set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports {btn}]

## SEG DATA 
#set_property -dict { PACKAGE_PIN F18   IOSTANDARD LVCMOS33 } [get_ports {d[0]}]
#set_property -dict { PACKAGE_PIN E18   IOSTANDARD LVCMOS33 } [get_ports {d[1]}]
#set_property -dict { PACKAGE_PIN B20   IOSTANDARD LVCMOS33 } [get_ports {d[2]}]
#set_property -dict { PACKAGE_PIN A20   IOSTANDARD LVCMOS33 } [get_ports {d[3]}]

## SEG AN
#set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS33 } [get_ports {an[0]}]
#set_property -dict { PACKAGE_PIN A19   IOSTANDARD LVCMOS33 } [get_ports {an[1]}]
#set_property -dict { PACKAGE_PIN F19   IOSTANDARD LVCMOS33 } [get_ports {an[2]}]

## UART
#set_property -dict { PACKAGE_PIN F15  IOSTANDARD LVCMOS33 } [get_ports {rxd}]
#set_property -dict { PACKAGE_PIN F13  IOSTANDARD LVCMOS33 } [get_ports {txd}]

## FRAMEBUFFER
#set_property -dict {PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports {sck}]
#set_property -dict {PACKAGE_PIN C14 IOSTANDARD LVCMOS33} [get_ports {mosi}]
#set_property -dict {PACKAGE_PIN C15 IOSTANDARD LVCMOS33} [get_ports {miso}]
提醒
  1. 不要在约束文件中自行添加空格。这可能会导致语法问题。
  2. 约束文件中的接口名一定要和设计文件中的端口名一致,比如上述约束文件中的'led'对应设计文件中的'output reg [7:0] led',否则综合时vivado会有如下报错。
    Image title

完成添加后,单击 Run Implementation 即可开始实现。此时可能会出现更多更难以解决的问题,比如时序不满足(逻辑电路过长)等。但同时我们也可以看到更多资源使用(utilization)、功耗(power)、时序(timing)等方面的信息。

2.3 ★ 在 FPGAOL 上运行

到这里,我们开发的过程就基本结束了,接下来需要在 FPGAOL 平台上进行验证。

点击左侧最下方的 Generate Bitstream 即可生成比特流文件。在生成比特流文件之前,你可以不进行仿真、综合与实现的步骤(假定你的设计没有问题),Vivado 工具会自动完成综合、实现、布局布线等过程,并最终生成比特流文件。

生成比特流文件的过程一般较为漫长,且取决于所用设备的性能。助教在自己电脑上生成一次比特流耗时大约在三分钟,如果使用 VLAB 平台则可能是五分钟。你可以在开始生成前选择本次生成所使用的核心数,进而加速生成过程。

Image title

注意

如果你使用的是 Vlab 虚拟机上的 Vivado,可能会出现因为内存不足而无法生成 bit 流的问题。如果出现了这种情况,请改用 2019.1 版本的 Vivado 完成实验。

生成的文件一般存放在 工程目录/工程名.runs/impl_1/ 目录下,为 顶层模块名.bit我们建议大家每次生成后将比特流文件重命名后拷贝到特定的目录,因为下次综合时会清除掉原先的比特流文件;并且,将一次实验的所有比特流文件放在同一个文件夹里,可以省去检查时的寻找时间。完成后,点击 Cancel 按钮关闭弹出的对话框。

得到比特流文件后,在申请的在线开发板中单击 Select File,将文件上传至服务器。上传完成后点击 Program! 就可以在线进行测试了。

Image title

Tips:物理开发板用户

如果你是开发板用户,可以在 Generate Bitstream 下面点击 Open HardWare Manager,将开发板连接上电脑,点击 auto connect,连接完成后点击 Program device 即可烧板。

Image title


休息一会儿!

本部分内容到此结束,你理解了多少呢?

现在,你可以将自己的代码烧写成 bit 流并在 FPGAOL 平台上运行了。当然,你也可以自行为模块添加更多更为有趣的功能。

评论

Authors: CSYrk, 刘丰毅