学习目标:高速、复杂协议或算法、神经网络加速
本学习是以赛灵思Xilinx的Vivado为开发
1.底层结构:
FPGA 主要有六部分组成:可编程输入输出单元(IO)、可编程逻辑单元(CLB)、完整的时钟管理、嵌入块状RAM、布线资源、内嵌的底层功能单元和内嵌专用硬件模块。其中最为主要的是可编程输出输出单元、可编程逻辑单元和布线资源。
2.0可编程逻辑单元(CLB)
可配置逻辑单元(Configurable Logic Block,CLB)在 FPGA 中最为丰富,由两个 SLICE 组成。由于 SLICE 有 SLICEL(L:Logic)和 SLICEM(M:Memory)之分,因此 CLB 可分为 CLBLL 和 CLBLM 两类。
SLICEL 和 SLICEM 内部都包含 4 个 6 输入查找表(Look-Up-Table,LUT6)、3 个数据选择器(MUX)、1 个进位链(Carry Chain)和 8 个触发器(Flip-Flop)
2.1.输入查找表(LUT6)
虽然 SLICEL 和 SLICEM 的结构组成一样,但两者更细化的结构上略有不同,区别在于 LUT6 上
不论是 SLICEL 还是 SLICEM,他们的 LUT6 都可以作为 ROM 使用,配置为 64x1(占用 1 个 LUT6,64 代表深度,1 代表宽度)、128x1(占用 2 个 LUT6)和 256(占用 4 个 LUT6)的 ROM。
另外既然 SLICEM 中的 M 代表 memory 的意思,所以增加了更多存储功能。可以配置为 RAM,尤其指分布式 RAM。其中 RAM 的写操作为同步,而读操作是异步的,即与时钟信号无关。如果要实现同步读操作,则要额外占用一个触发器,从而增加了意识时钟的延迟(Latency),但提升了系统的性能。
这就解释了为什么我们实现RAM同步读写的时候,读出输出要延迟一个 clk。一个 LUT6 可配置 64x1 的 RAM,当 RAM 的深度大于 64 时,会占用额外的 MUX(F7AMUX,F7BMUX,F8MUX,即一个 SLICE 中的那 3 个 MUX)。
SLICEM 中的 LUT 还可以配置为移位寄存器,每个 LUT6 可实现深度为 32 的移位寄存器,且同一个 SLICEM 中的 LUT6(4个)可级联实现 128 深度的移位寄存器。
2.2 选择器(MUX)
SLICE 中的三个 MUX(Multiplexer:F7AMUX,F7BMUX 和 F8MUX)可以和 LUT6 联合共同实现更大的MUX。事实上,一个 LUT6 可实现 4 选 1 的 MUX。
SLICE 中的 F7MUX(F7AMUX 和 F7BMUX)的输入数据来自于相邻的两个 LUT6 的 O6 端口。
一个 F7MUX 和相邻的两个 LUT6 可实现一个 8 选 1 的 MUX。因此,一个 SLICE 可实现 2 个 8 选 1 的 MUX。
4 个 LUT6、F7AMUX、F7BMUX 和 F8MUX 可实现一个 16 选 1 的 MUX。因此,一个 SLICE 可实现一个 16 选 1 的 MUX。
2.3 进位链(Carry Chain)
进位链用于实现加法和减法运行。就是结构图中,中间那个大的部分,可以看到它内部实际还包含 4 个 MUX 和 4 个 2 输入异或门(XOR)。
异或运算是加法运算中必不可少的运算。
2.4 触发器(Flip-Flop)
每个 SLICE 中有 8 个触发器。这 8 个触发器可分为两大类:4 个只能配置为边沿敏感的 D 触发器(Flip-Flop)和 4 个即可配置为边沿敏感的 D 触发器又可配置为电平敏感的锁存器(Flop & Latch)。当后者被用作锁存器的时候,前者将无法使用。
当这 8 个触发器都用作 D 触发器时,他们的控制端口包括使能端 CE、置位/复位端口 S/R 和时钟端口 CLK 是对应共享的,也就是就是说共用的。 {CE,S/R,CLK}称为触发器的控制集。显然,在具体的设计中,控制集种类越少越好,这样可以提高触发器的利用率。那么怎样减少控制集种类呢?我的理解是:
减少时钟种类,即频率越少越好;
统一规范的设计逻辑,如复位。
3.仿真
写好仿真文件时
找到 Run Simulation - Run Behavioral Simulation
行为模拟(Behavioral Simulation)是数字电路设计验证过程中的一个重要环节,它允许设计者在实际硬件实现之前,对设计进行逻辑功能和时序行为的验证。在FPGA设计中,Xilinx Vivado软件提供了仿真功能,主要包括行为仿真和时序仿真两种类型。
行为仿真,也称为功能仿真,主要关注设计的逻辑功能是否正确。在这个阶段,仿真器不考虑硬件的具体实现细节,如门延迟和布线延迟,只关注设计是否按照预期的逻辑行为工作。行为仿真是在设计流程的早期阶段进行的,通常在源文件或预合成设计上执行,用于验证代码的语法和功能正确性,以及在系统实际执行之前确定设计的效率。
进行行为仿真前,需要准备设计HDL源代码、测试激励代码(TestBench)以及可能需要的仿真模型或库。TestBench用于生成被测试单元(UUT)的输入信号,并验证输出信号。在Vivado IDE中,可以通过“Sources”窗口添加TestBench,并在“Flow Navigator”窗口中点击“Run Simulation”来运行仿真。
仿真过程中,可以使用Vivado的Scope、Waveform等窗口查看和分析仿真结果。可以通过添加信号到波形窗口,保存波形配置信息,并进行波形的缩放、测量等操作。此外,还可以调整仿真时间的设置,以更好地观察和分析信号的变化。
在行为仿真中,设计者可以对HDL源代码进行修改,并通过“Relaunch”功能重新加载并仿真,以便快速迭代和调试。时钟和复位信号通常在TestBench中生成,以模拟实际硬件的工作条件。仿真精度也可以根据需要进行调整,例如将仿真单位设置为1ns/1ps,以便更精确地观察信号的变化。
总的来说,行为仿真是FPGA设计中不可或缺的一部分,它帮助设计者在早期发现和修正设计中的错误,提高设计的可靠性和效率。通过Vivado软件提供的工具和功能,设计者可以方便地进行行为仿真,确保设计的逻辑功能正确,并为后续的时序仿真和硬件实现打下坚实的基础。
仿真结果:
4.跑综合
在FPGA设计流程中,"Run Synthesis"(运行综合)是一个关键步骤,它将设计从行为描述或RTL(寄存器传输级)描述转换成门级网表。这个过程涉及到多个阶段,包括优化、逻辑综合、门级优化等。以下是"Run Synthesis"的一些主要步骤和考虑因素:
1. **准备工作**:在运行综合之前,需要确保所有的HDL代码都已经编写完成,并且通过了基本的行为仿真验证。
2. **设置综合约束**:在综合之前,通常需要设置一些约束条件,比如时钟频率、I/O引脚分配、功耗优化等。这些约束可以通过XDC(Xilinx Design Constraints)文件或其他综合工具支持的格式来定义。
3. **启动综合**:在Vivado中,可以通过Flow Navigator中的“Synthesize”(综合)按钮来启动综合过程。Vivado会调用综合工具(如Xilinx的Vivado Synthesis Tool)来处理HDL代码,并生成门级网表。
4. **综合优化**:综合工具会对设计进行优化,以减少逻辑资源的使用、提高时钟频率、降低功耗等。这可能包括逻辑单元的合并、流水线的插入、缓冲器的优化等。
5. **查看综合结果**:综合完成后,可以查看综合报告,了解资源使用情况、时序分析结果、以及任何可能的警告或错误。这些信息对于后续的设计调试和优化至关重要。
6. **后综合仿真**:在综合之后,通常需要进行后综合仿真(Post-Synthesis Simulation),以验证综合后的门级网表是否仍然符合设计规格。
7. **时序分析**:综合过程中,时序分析是非常重要的一环。它确保设计在给定的时钟频率和条件下能够正常工作,没有时序违规。
8. **迭代优化**:如果综合结果不符合预期,可能需要回到设计阶段进行修改,然后重新进行综合和仿真,直到满足所有设计要求。
在Vivado中,"Run Synthesis"可以通过以下步骤进行:
- 打开Vivado项目。
- 在Flow Navigator中,选择“Synthesize”(综合)。
- 配置综合设置和约束。
- 点击“Run Synthesis”按钮开始综合过程。
- 综合完成后,查看综合报告和时序分析结果。
- 如有必要,根据报告进行设计调整,并重新综合。
综合是FPGA设计中的一个重要步骤,它直接影响到设计的性能、资源使用和最终的硬件实现。因此,综合过程中的优化和分析是非常关键的。
5.Run Implementation
在Xilinx Vivado中,"Run Implementation"(运行实现)是FPGA设计流程中的关键步骤,它包括布局布线(Place and Route)、优化(Optimization)和生成比特流(Bitstream Generation)等过程。以下是详细的步骤:
1. **布局布线(Place and Route)**:这个过程将综合后生成的门级网表映射到FPGA芯片的物理位置上,并进行连线。布局(Place)是指将逻辑门分配到FPGA内部的逻辑单元上,布线(Route)则是确定这些逻辑门之间的物理连接路径。这个过程需要考虑时序、资源和功耗等因素进行优化。
2. **优化(Optimization)**:在布局布线之后,Vivado会进行一系列的优化操作,以提高设计的性能和减少资源使用。这可能包括逻辑优化、缓冲插入、门控时钟等技术。
3. **生成比特流(Bitstream Generation)**:完成布局布线和优化后,Vivado会生成比特流文件,这是一个包含了FPGA配置数据的文件,可以被下载到FPGA设备中,使设计在硬件上运行。
4. **时序分析(Timing Analysis)**:在实现过程中,Vivado还会进行时序分析,确保设计满足所有时序约束,包括建立时间(Setup Time)和保持时间(Hold Time)。
5. **导出硬件(Export Hardware)**:最后,当实现过程完成后,可以通过“Export Hardware”功能生成比特流文件,准备将设计下载到FPGA硬件上。
在实际操作中,可以通过Vivado的图形用户界面来执行这些步骤,或者使用Tcl脚本来自动化这个过程。实现过程可能需要一些时间,具体取决于设计的复杂性和计算机的性能。
完成实现后,可以使用Vivado的“Open Hardware Manager”来下载比特流文件到FPGA硬件上,并进行实际的硬件测试和验证。
6.生成比特流文件
赛灵思Xilinx的开发板生成比特流文件,其实一开始让其生成比特流文件他就会自己进行
在Xilinx Vivado中生成比特流文件(bitstream)是将设计从RTL代码转换为可以在FPGA硬件上运行的配置文件的过程。以下是生成比特流文件的一般步骤:
1. **完成设计综合**:确保你的设计已经通过了综合,没有错误或警告。
2. **布局布线**:在Vivado中进行布局布线,确保设计在物理上是可行的。
3. **添加约束**:使用XDC文件或其他方法定义管脚约束,确保设计中的信号正确地映射到FPGA的物理管脚上。
4. **生成比特流**:
- 在Vivado的“Flow Navigator”中选择“Generate Bitstream”。
- 等待Vivado执行实现和生成比特流的步骤。
- 生成过程可能需要一些时间,具体取决于设计的复杂性和计算机性能。
5. **检查比特流**:生成完成后,可以在“Sources”面板中找到比特流文件(.bit文件),并双击查看详细信息。
6. **下载到硬件**:
- 使用USB下载器将FPGA板连接到计算机。
- 在Vivado中打开“Hardware Manager”。
- 选择“Open Target”->“Auto Connect”来连接到FPGA板。
- 选择“Program Device”,然后选择要下载的比特流文件(.bit文件)。
- 点击“Program”按钮,将比特流文件下载到FPGA板上。
7. **硬件验证**:下载完成后,可以在硬件上验证设计的功能。
请注意,如果在生成比特流文件之前没有正确设置约束,Vivado可能会报告错误,例如“Unconstrained Logical Port”。确保在生成比特流之前添加了所有必要的约束。
7.配置引脚电平
zynq-7010板子的引脚带电平都是LVCNMOS33
I/0 Planning
在出来的页面中点击 Group by Interface and Bus ,在 I/O Std 选择接口电平,我们使用的板 卡中普通 IO 口采用的 LVCMOS33 的电平标准,然后在 Package 中选择需要约束到的引脚,后 面代码中有接口对应的引脚在Xilinx Vivado中进行I/O规划(I/O planning)是FPGA设计流程中的一个重要步骤,它涉及到定义和分析FPGA与印刷电路板(PCB)之间的连接性,并为设备上的物理引脚分配各种互连信号。以下是进行I/O规划的一般步骤:
1. **打开Vivado项目**:启动Vivado软件并打开或创建一个新的工程。
2. **访问I/O Planning**:在Vivado的“Flow Navigator”中,选择“Open Implemented Design”来打开实现后的设计。然后选择“IO Planning”选项,进入I/O规划视图。
3. **定义和配置I/O端口**:你可以在I/O规划视图中查看和编辑设计的输入输出引脚。这包括为I/O端口分配物理引脚,设置I/O标准,如电压等级和信号速率,以及配置差分信号对。
4. **使用I/O规划工具**:Vivado提供了多种工具来帮助规划I/O,例如自动引脚放置、差分对配置和I/O标准设置。
5. **进行设计规则检查(DRC)**:在I/O规划过程中,运行DRC以验证当前设计是否符合指定的设计规则,并报告任何违规。
6. **生成PCB数据**:完成I/O规划后,可以生成XDC、CSV和IBIS文件,这些文件可以提供给PCB设计师用于信号完整性分析和PCB布局。
7. **实施设计**:在生成比特流文件之前,必须先实施设计。在实施过程中,Vivado工具会将设计元素放置到设备资源上,路由设计网络,并优化以降低功耗并满足时序要求。
8. **导出硬件**:在实施设计后,可以导出硬件,生成比特流文件,以便将设计下载到FPGA硬件上。
I/O规划是一个迭代过程,涉及到FPGA设计师和PCB设计师之间的信息交换。它从PCB设计师使用CSV文件导入的目标设备引脚配置开始,完成I/O和时钟规划流程后,可以将引脚配置以及设备模型用于信号完整性分析,使用CSV文件和I/O缓冲信息规范(IBIS)模型返回给PCB设计师。
8.基本知识
Xilinx 的触发器是高电平复位,而 Altera 的触发器时低电平复位
输入两个接口:
input wire clk //时序电路:最重要的是时序信号
input wire rstn//复位信号:rstn //定义rstn是低电平有效,rst是高电平有效
Output reg [3:0] led//输出4比特的led信号
输出只能是wire信号,输入可以是wire也可以是reg
always @(posedge clk or negedge rstn)
在Verilog硬件描述语言中,`always @(posedge clk or negedge rstn)` 是一个敏感列表,用于定义一个始终块(always block)的触发条件。这个始终块是一个同步复位的时序逻辑块,它在时钟信号 `clk` 的正边沿或复位信号 `rstn` 的负边沿时被触发。下面是这个语句的详细解释:
- `always`:关键字,用于定义一个始终块,这是Verilog中实现时序逻辑和组合逻辑的基本构造。
- `@(...)`:敏感列表,指定了触发始终块执行的信号事件。只有当敏感列表中的信号发生变化时,始终块内的逻辑才会被重新评估。
- `posedge clk`:表示在时钟信号 `clk` 的正边沿(从低到高)时触发始终块。
- `negedge rstn`:表示在复位信号 `rstn` 的负边沿(从高到低)时触发始终块。通常,`rstn` 是一个低有效的复位信号,这意味着当它为低时,系统会被复位。
在这个始终块内部,你可以放置触发器(如D触发器)或其他同步复位的逻辑。当 `clk` 的正边沿到来时,这些逻辑会按照设计更新状态。如果 `rstn` 信号变为低,那么在下一个 `clk` 的正边沿到来时,系统会被复位到初始状态。
以下是一个简单的例子,展示了如何使用这个始终块来创建一个带有同步复位的D触发器:
```verilog
module d_flip_flop(
input clk,
input rstn,
input d,
output reg q
);
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
q <= 1'b0; // 同步复位:当rstn为低时,q被置为0
end else begin
q <= d; // 时钟正边沿时,根据d的值更新q
end
end
endmodule
```
在这个例子中,`q` 是D触发器的输出,它会在每个 `clk` 的正边沿时捕获 `d` 信号的值,除非 `rstn` 信号是低的,在这种情况下,`q` 会被同步地复位为0。
在Verilog中,敏感列表用于指定触发`always`块执行的信号事件。除了`posedge clk`和`negedge rstn`之外,还有以下几种常用的敏感列表:
1. **组合逻辑敏感列表**:
- `always @*` 或 `always @(*)`:表示该`always`块是一个组合逻辑块,它会在块内任何信号发生变化时触发。这通常用于实现组合逻辑电路。
2. **时序逻辑敏感列表**:
- `always @(posedge clk)`:仅在时钟信号`clk`的正边沿触发,用于实现时序逻辑电路。
- `always @(negedge clk)`:仅在时钟信号`clk`的负边沿触发,用于实现时序逻辑电路。
3. **边沿触发敏感列表**:
- `always @(posedge signal)`:在任何指定信号的正边沿触发。
- `always @(negedge signal)`:在任何指定信号的负边沿触发。
4. **电平触发敏感列表**:
- `always @(signal)`:在任何指定信号的电平变化时触发,无论是上升沿还是下降沿。这种敏感列表通常用于组合逻辑,但在某些情况下也可以用于时序逻辑。
5. **多个信号的敏感列表**:
- `always @(posedge clk or posedge rstn)`:在`clk`的正边沿或`rstn`的正边沿触发。
- `always @(negedge clk or posedge rst)`:在`clk`的负边沿或`rst`的正边沿触发。
6. **特定信号组合的敏感列表**:
- `always @(a or b or c)`:在信号`a`、`b`或`c`中的任何一个发生变化时触发。
- `always @(posedge clk or a or b)`:在`clk`的正边沿或信号`a`、`b`中的任何一个发生变化时触发。
7. **非阻塞赋值敏感列表**:
- 在时序逻辑中,即使敏感列表只包含时钟信号,有时也会使用非阻塞赋值(`<=`)来确保在所有触发信号的同一时间点更新状态。
请注意,敏感列表的选择应根据设计的需要和信号的特性来确定。例如,对于时序逻辑,通常使用边沿触发敏感列表,而对于组合逻辑,则使用`@*`或`@(*)`。此外,敏感列表的选择还会影响仿真和综合工具的行为,因此在设计时应仔细考虑。