HDL 基础
按传统方法可将硬件抽象级的模型类型分为以下五种:
- 系统级(System level),用语言提供的高级结构实现系统运行的模型
- 算法级(Algorithm level),用语言提供的高级结构实现算法运行的模型
- RTL 级(Register transfer level),描述数据在寄存器之间流动和如何处理、控制这些数据流动的模型
- 门级(Gate level),描述逻辑门以及逻辑门之间连接的模型,与逻辑电路有确切的连接关系
- 开关级(Switch level),描述器件中三极管和存储节点以及它们之间连接的模型。 与具体的物理电路有对应关系, 工艺库元件和宏部件设计人员必须掌握
TestBench
HDL 设计中的 TestBench 和软件开发中的单元测试类似。Verilog 的测试平台并不对硬件建模,它只是一个程序,模拟器通过执行这个程序,将输入加到一个硬件模型的输入端,并观察其输出,这个硬件模型通常被称为 “待测单元”(UUT, Unit Under Test)
TestBench 相关概念可以参考 FPGA designs with Verilog 第九章 9. Testbenches
Tools
欲善其事,先利其器。商业版 HDL 工具,例如 Vivado、Modelsim 等,无论是安装还是 License 申请都比较麻烦。初学 HDL 时使用开源工具是不错的选择。下面罗列了一些开源工具,其他内容可以参考这里
-
Verilog 编译与检查:Iverilog / verible / verible /
sudo apt install iverilog
/
-
仿真:GTKWave(波形查看)/ vcdrom / dwfv、Logisim(数字电路仿真)、Digital
- dwfv 可以在终端显示波形,如果解析错误则无法正确显示。可以考虑先用
dwfv sample.vcd --stats
查错
- dwfv 可以在终端显示波形,如果解析错误则无法正确显示。可以考虑先用
-
HDL 综合:Yosys /
-
电路可视化:netlistsvg、digitaljs 、TerosHDL。推荐使用 Digitaljs_online ,可以可视化 verilog,也可以进行简单的仿真
如果喜欢折腾且有 ASIC 设计知识,可以考虑使用商业综合工具学习 HDL,比如 Synopsys 的 Design Compiler 或者 Cadence 的 Genus
IVerilog & GTKWave & VCDrom
IVerilog & GTKWave & VCDrom 都是开源软件,同时支持 Win & Linux,刚入门 Verilog 时可以使用这两个工具实现 Verilog 的仿真。使用方法可以参考Icarus Verilog + GTKWave Guide和其他网络资料,下面只给出一些常用的命令
# -o 指定可执行文件名称;-Wall 与 GCC 命令类似;-Winfloop 检测内循环
iverilog -Wall -o my_out.vvp one.v two.v
vvp my_out.vvp # 执行并生成 vcd 文件
gtkwave xxx.vcd # 使用 gtkwave 显示 vcd 波形
GTKWave 波形展示效果如下:
如果只是想简单的模拟 HDL,可以使用 HDLBits 或者 EDA Playground 网站,HDLBits 可以在网页上提交代码并显示仿真波形
VCDrom 是开源的浏览器端 vcd 波形显示工具,VCDrom 波形示例可以参考这里。浏览器打开其官网后可以在浏览器中打开本地 vcd 文件并显示波形。VCDrom 支持快捷键,Mac 下使用 Option 替换 Alt 可以实现快速波形操作与显示
还有其他类型的波形显示工具,例如 surfer,可以按照自己所使用的平台可习惯选择合适的工具
YosysHQ
YosysHQ 提供了一整套可用的数字芯片设计工具,细节请参考 github:https://github.com/YosysHQ。使用 Yosys 可以查看 Veilog 的综合结果。安装 yosys 或者 OSS CAD Suite 后通过执行下面的命令可以查看 HDL 的综合结果。首先创建 test.v 文件并写入如下内容
module top(a, b, c, d, e, f, x, y);
input [1:0] a, b, c, d, e, f;
output [1:0] x = {a[0], a[1]};
output [11:0] y;
assign {y[11:4], y[1:0], y[3:2]} = {a, b, -{c, d}, ~{e, f}};
endmodule
yosys 支持 tcl 脚本,编写 yosys 脚本文件(gen_syn_graph.tcl
)如下:
set v_file test.v
set mod_name sample_module
yosys -import # import all yosys commands directly as tcl commands to the tcl shell
yosys read_verilog ${v_file}
yosys hierarchy -top ${mod_name}
#yosys synth_xilinx -top ${mod_name} # synthesis for Xilinx FPGAs
yosys proc
yosys opt
yosys show -prefix ./${mod_name} -viewer echo
exec dot -Tpng ${mod_name}.dot -o ${mod_name}.png
执行上面的脚本文件(yosys gen_syn_graph.tcl
),综合结果如下。默认情况下 yosys 使用内部定义的 Internal cell library 绘制 RTL 的逻辑关系(AND, OR, NOT, XOR, D-TypeFlip-flops, etc)。下图部分单元(cell)的功能可以通过单元的名称来确定,细节可以参考官网 internal cell library 中的介绍。圆角矩形表示两侧单元之间总线的连接关系(<MSB_LEFT>:<LSB_LEFT> -<MSB_RIGHT>:<LSB_RIGHT>
),细节可参考官网:Break-out boxes for signal vectors
yosys 命令参考手册可参考这里:https://yosyshq.net/yosys/files/yosys_manual.pdf / Command line reference /
可视化
digitaljs 支持 VSCode 且有在线版本,上面 Verilog 使用 digitaljs 可视化的效果如下
netlistsvg 的使用细节可以参考官网,下面给出上面 verilog 的可视化效果
git clone https://github.com/nturley/netlistsvg # 尽量使用最新版本的 netlistsvg
cd netlistsvg
npm install # install dependencies
sudo npm install -g . # install netlistsvg to system
# sudo npm uninstall -g netlistsvg # uninstall from system
yosys -p "prep -top top; write_json output.json" test.v # yosys 生成 JSON 格式的综合结果
netlistsvg output.json # -o output_file
TerosHDL 可视化
Vivado
Vivado 是赛灵思(Xilinx)公司出品的 PS/PL 集成开发环境。Vivado 支持 Verilog、VHDL 等常见 PL 语言并且内嵌综合器、仿真器等工具。Vivado HLS 可以直接使用 C、C++ 或 System C 来对 Xilinx 系列的 FPGA 进行编程,从而提高抽象的层级,大大减少了使用传统 RTL描述进行 FPGA 开发所需的时间
Vivado 支持 Win 和 Linux 平台,使用 Vivado 可以非常方便的学习 PS/PL 编程。在 Vivado 中使用上文代码可以很方便的得到 RTL 逻辑综合后的门级电路和实现后的查找表电路(查找表是 FPGA 的基本单元,逻辑电路需要转换为查找表 LUT 才能写入 FPGA)
vivado 创建工程的过程可以参考一些博客;或者《搭建你的数字积木》第一章;不同开发版附带的教程也有相关内容。示例代码可以参考:https://github.com/xupsh/Digital-Design-Lab /
HDL 开发流程
HDL 设计方法主要有行为描述、结构描述两种。行为描述由输入/输出的相应关系来描述,只有电路的功能性述, 没有结构描述,也没有具体的硬件示意图。结构描述由低等级的元件或基本单元的连接关系来描述,主要关注电路的功能和结构。它设计具体的硬件,便于后续综合
添加约束文件
工程中输入源代码之后,需要给设计添加管脚和时序约束:
- 管脚约束是将设计文件的输入输出信号设置到器件的某个管脚,而且包括设置此管脚的电平标准、电流标准、上下拉特性等
- 时序约束在高速数字电路设计中非常重要,其作用是为了提高设计的工作频率和获得正确的时序分析报告。 在综合、映射和布局布线阶段附加约束,可以使时序分析工具以用户的时序约束为标准,尽量满足约束要求,同时产生实际时序和用户约束时序之间的差异,并形成报告
综合与实现
综合就是针对输人设计以及约束条件,按照一定的优化算法进行优化处理,获得一个能满足预期功能的电路设计方案。在 FPGA 设计时,综合工具将这些输入文件(HDL)翻译成由 FPGA 内部逻辑资源按照某种连接方式组成的逻辑连接
实现就是通过翻译、映射、布局布线等过程来完成设计的固化。首先将综合生成的网表(Netlist)文件,通过翻译变成所选器件的内部资源和硬件单元;然后找到对应的硬件关系,将设计与这些硬件资源关系一一对应起来;最后进行布局布线,这样设计基本上就可以完全固化到 FPGA 当中了
工艺映射
工艺映射是指将不依赖于任何工艺的门级网表转换为由特定 FPGA 逻辑单元所表示的网表的过程。这里所说的逻辑单元依赖于特定的 FPGA 架构,是由査找表或 MUX 等逻辑电路实现的 FPGA 上的最小逻辑单位。工艺映射是从 HDL 开始的逻辑转换的最后一步,因此对最终电路实现的质量( 面积、 速度、 功耗等 ) 至关重要。非常有代表性的映射算法是 FlowMap,简介如下
- 分解:门级网标实际上都是以布尔网络的形式来表示的。先将布尔网络的各个节点不断分解,直至输人数小于査找表的输人数
- 覆盖:基于过程 I 所得到的布尔网络,使用某种基准对输入进行切分,使用 k-LUT 覆盖多个节点
逻辑打包
主流 FPGA 的逻辑块都具有多个査找表,因此将査找表高效地打包到逻辑块的过程是不可或缺的。逻辑打包主要有两个要点: 第一, 逻辑块内部布线( 局部布线 )和逻辑块外部布线( 布线通道中的布线 )的延迟相差很大;第二,如果逻辑块中有查找表空闲,资源使用率就会降低( 增加逻辑块的使用量 ), 因此要尽量在每个逻辑块内填装更多逻辑。多伦多大学 Jonathan Rose 教授的研究团队开发的早期的打包工具 VPack
布局布线
布局布线是 FPGA 设计流程的最后一个步骤—在物理上确定逻辑块的位置和信号连接路径。一般来说首先会确定逻辑块的布局,然后再 对逻辑块间的连接进行布线。多数 FPGA 的逻辑块都呈二维阵列状排列,因此逻辑块布局问题可以视为标准的二次分配问题。然而,此类问题也被公认为是 NP 问题,通常只能使用 SA (Simulated Annealing ) 等算法获取近似解
布线过程中主要使用两种布线方法:全局布线和详细布线。全局布线阶段主要决定线网的布线路径,例如通过哪些通道形成连接。详细布线则基于全局布线所得的信息,确定路径具体使用了哪些布线资源、通过了哪些开关等。学术界常用的布线算法是 VPR(Versatile Place and Route)
编译文件下载
只有编译文件才能配置 FPGA,因此在完成综合与实现后,还需要将生成的网表文件转换成可配置 FPGA 的文件
其他
-
硬件算法:流水线 / 并行计算 / 脉动算法(systolic algorithm) / 数据流机 / 流处理 / 细胞自动机 / 硬件排序算法 / 模式匹配 / 其他
-
低功耗设计:低功耗设计工具和算法在解决常规问题的基础上还要考虑如何才能降低功耗,例如 Emap、P-T-VPack、P-VPR 等工具和算法
HDL 综合简介
赋值
硬件中有三种基本的保持器:连线、触发器(边缘触发的存储器件)和锁存器(电平敏感的存储元件)。Verilog HDL 中的变量既可以是网线(wire)数据类型的,也可以是寄存器(reg)数据类型的。 综合时,会把网线类型的变量映射成硬件中的连线,而寄存器变量则要根据其被賦值的上下文环境来确定是映射成连线还是映射成存储元件(触发器或锁存器),所以 reg 变量综合后可能是 wire
持续赋值语句(assign a=b;
)表示用陚值语句右端表达式所推导出的逻辑来驱动该赋值语句左端的网线,而持续赋值的对象总是受组合逻辑驱动的网线。过程赋值语句(阻塞、非阻塞)表示用赋值语句右端表达式所推导出的逻辑来驱动该赋值语句左端的变量。可综合的过程赋值语句只能出现在 always 语句中。赋值语句的阻塞和非阻塞性质不会造成从赋值语句本身生成的组合逻辑电路有任何不同,但是会影响以后对赋值结果的使用。建议,对组合逻辑进行建模使用阻塞式赋值,而对时序逻辑进行建模使用非阻塞式賦值。过程赋值的对象会被综合成连线、触发器或锁存器,这取决于赋值语句在 VerilogHDL 模型中的上下文环境。对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值
对于阻塞式赋值,执行顺序块中下一条语句之前就已完成对左端对象的賦值(如果在 always 语句中仅有一条语句,则阻塞式賦值和非阻塞式賦值之间没有差别)。对于非阻塞式复制,对左端对象的赋值被安排在该仿真周期结束时(即陚值并不立即生效)、执行下一条语句之前
运算符
逻辑算符能直接映射成硬件中的基本逻辑门。寄存器类型被解释成无符号数,整数类型被解释成二进制补码形式的有符号数,解释时都把最右端的位作为最低有效位。网线类型被解释为无符号数
能够综合的关系算符有: > 、 < 、 < = 、 >=、==、!= 。 关系算符的建模与算术箅符相似。对于关系算符,综合会产生不同的结果,这取决于被比较的究竟是无符号数还是有符号数。如果比较的是寄存器类型或者网线类型的变量,则综合出无符号关系算符
Verilog HDL 综合系统支持左移(“ « ”) 和右移(“ » ” )算符。 移位腾出的各位都补 0。算符右边的运算量表示移位的位数,它既可以是常量,也可以是变量。 在这两种情况下,产生的都是组合逻辑。如果位移童是常量,则只需重新连线就行了。如果位移量是变量,则会综合出通用移位器
if/case 等语句中推导出锁存器的一般规则是,如果变量未在 always 语句所有可能的执行过程中被赋值(比如变量未能在 if 语句的所有分支中都被复制),就推导出锁存器
Verilog 有 4 种循环语句(while、repeat、for 和 forever)。for 循环语句是典型的能用于综合的循环语句。for 循环的综合是通过展开循环来实现的
always@(Address)
for (J=3 ; J>=0 ; J=J-1)
if (Address $==J$ )
Line[J]=1;
else
Line[J]=0;
上述代码循环展开后如下:
if(Address == 3) Line[3] = 1; else Line[3]= 0;
if(Address == 2) Line[2] = 1; else Line[2]= 0;
if(Address == 1) Line[1] = 1; else Line[1]= 0;
if(Address == 0) Line[0] = 1; else Line[0]= 0;
门级建模
模型中可以使用逻辑门实例化语句得到逻辑门基本元件的实例。 能够综合的逻辑门基本元件有: and、 nand、 or、 nor、 not、 xor、 xnor、 buf 、 bufifO、 bufifl、 notif0 和 notif1 门级基本元件的综合应依据其行为来生成相应的逻辑,最终把它映射到目标工艺上