《从电路设计的角度入门VerilogHDL》笔记
概述与特性
简介
VerilogHDL 不是编程语言,是硬件描述语言。学习 VerilogHDL 的过程中,我们应该从电路设计的角度去思考与 VerilogHDL 有关的问题而不是从如何编程的角度去思考。
书籍推荐:
轻松成为设计高手:VerilogHDL 使用精讲
MOOC 课程推荐:
芯动力——硬件加速设计方法
什么是 HDL?
HDL,全称是 Hardware Description Language,翻译过来是“硬件描述语言”。从名字可以看出进行 HDL 开发的过程不是设计的过程,而是描述事物的过程。对于 HDL 来说,我们是要将已经存在的电路用编程语言的方式描出来。因此,HDL 的开发过程是先设计硬件电路,然后使用 HDL 对于设计好的电路进行描述。
VerilogHDL 由 Cadence 发明,以全定制电路设计方法学的挑战者诞生。VerilogHDL 随着芯片规模进入数亿晶体管时代,近年来受到了 HLS、Chisel 等语言的挑战。但是目前 VerilogHDL 仍是描述数字电路和数字逻辑系统的主流语言。
VerilogHDL 设计流程
设计一个电路(RTL)
对设计的电路进行仿真和验证
进行逻辑综合
将综合好的电路进行布局布线
逻辑综合使得我们由 VerilogHDL 得到了具体的电路,布局布线则是得到了芯片上各个器件在版图上的坐标
布局布线后的网表可以去流片得到真正可以使用的芯片
VerilogHDL 的重要特性:
VerilogHDL 具备从 “抽象表达” 到 “门级连接” 的多层次表征的能力:既可以在较高层面进行电路行为级的描述,也可以在较低层面描述门级电路的连接关系。
因此说 VerilogHDL 的功能非常全面。
为了更加方便地描述超大规模集成电路,人们希望使用抽象程度更高的 HDL 来描述硬件。这是 HLS、Chisel 等语言的发展方向。
VerilogHDL 可以看作是一个大工具箱,可以将其中的工具分为两类:一类是真正用于生成硬件电路的可综合语句,另一类是构建测试环境的语句。
数字硬件电路的描述方法:
两类:
- 原理图:
- 早期方法
- 直观,便于理解
- HDL:
- 适合大型设计
- HDL 的优势体现在超大规模集成电路的设计中。HDL 的可维护性强且模块的复用非常方便
VerilogHDL 的工具简介:
使用场景 | 开源工具解决方案 | 商业工具解决方案 |
---|---|---|
代码编辑器 | VScode、Vim等 | Vivado、Quaruts |
仿真 | Iverilog、verilator、GTK-Wave | VCS、Modelsim、Vivado、Quaruts |
逻辑综合 | Yosys | Vivado、Quaruts |
VerilogHDL 的缺点:
- 例化繁琐,需要手动连线
- 大量中间信号需要写声明
- 模块参数能力弱
- 对于错误的检查能力弱
- 基础电路需要重复写,电路的复用程度低
- ...
编写方法
设计对象
我们以下图为例介绍:
一个完整的数字电路工程称为一个 Design(设计),Design 由多个模块构成
1 | module TOP ( A,B,C,D,CLK,OUT1 ); |
这种情况的出现是因为我们使用了 Yosys 无法正确识别的 cells:ENCODER、INV 和 REGFILE。因为这三个 Cells 是我们自己定义的,因此我们需要自己来规定这些 cells 的输入和输出。因此我们创建三个新的 module。
1 | module ENCODER ( AIN,BIN,CIN,DIN,Q0,Q1 ); |
1 | module REGFILE ( D0,D1,CLK,Q ); |
1 | module INV ( A,Z ); |
创建并保存文件后,我们重新进入 yosys,然后导入这三个 module:
1 | read_verilog ENCODER.v INV.v REGFILE.v |
然后我们得到如下电路图:
上述过程我们可以得知:
- 在 TOP 层面进行描述的时候,我们不需要知道调用的 module 的内部实现,得到有意义的电路图只需要知道其端口中哪些是输入哪些是输出即可
VerilogHDL 与 C 语言的区别:
与 C 语言相比,VerilogHDL 具备硬件设计的基本概念:
- 互联(connectivity):wire 类型变量可以描述各个模块之间的端口与网络的连接关系
- 并发(concurrency):可以有效的描述并行的硬件系统
- 时间(time):定义了绝对和相对的时间度量,可综合操作符具有物理延时
VerilogHDL 中的并发执行:
以下方代码块所示:
1 | module TOP; |
在 VerilogHDL 的 module 中,所有描述语句
- 连续赋值语句(assign)
- 行为语句块(always、initial)
- 模块实例化
都是并行发生的。
而 begin ... end 中的语句是顺序执行的。
- 门级建模:引用逻辑门实例并进行连接
- 优点:对于有数字逻辑基础的人来说非常直观
- 缺点:电路功能复杂时会变得非常繁琐且容易出错
- 数据流建模:根据数据在寄存器之间的流动和处理过程对电路进行描述
- 优点:不用专注于电路结构的细节,更加灵活
- 缺点:这个建模层次不便于用来确定硬件设计的整体结构和算法
- 连续赋值语句:assign 语句——数据流建模的基本语句
- 使用运算符对 wire 或者 reg 变量进行运算,然后对 wire 变量进行赋值
- 建议工程中仅仅使用 assign 语句进行连线
- 行为级描述:从算法角度,或者说从电路外部行为角度进行描述
- 结构化过程语句:所有的行为级描述都出现在这两种结构化过程语句中
- initial 语句:不可综合;用于仿真时进行初始化、信号监视、生成仿真波形;仿真期间仅执行一次
- always
语句:可综合;反映了电路上电后反复执行的特点,只能使用断电(
$finish
)和中断($stop
)来停止 - 结构化过程语句如果包含多个行为语句,需要使用
begin end
构成一个语句块
- 过程性赋值语句:阻塞赋值(=)和非阻塞赋值(<=)
- 更新对象是:reg、real、integer、time
- 与连续赋值语句(assign)的区别:过程性赋值语句只有在执行到的时候才会起作用,连续性赋值语句是任何时刻的任何变化都会起作用。
- 阻塞赋值(=):串行行为;建模组合逻辑的行为
- 非阻塞赋值(<=):并行行为;建模时序逻辑的行为
- 行为级描述中的时序控制:
- 基于延时的时序控制:在结构化过程语句中加入延时
- 基于事件的时序控制:事件指 reg 或者 wire 变量发生了变化,可以使用事件来选择是哪些结构化过程语句在执行
- 电平敏感的时序控制:wait 语句
- 行为语句:
- 条件语句:
if else
- 分支语句:
case
- 循环语句:
while
、for
、repeat
、forever
- 条件语句:
- 结构化过程语句:所有的行为级描述都出现在这两种结构化过程语句中
数字设计领域。RTL(寄存器传输级)通常是指数据流建模和行为级建模的结合