type
date
status
slug
summary
tags
category
password
icon
Verilog HDL, 当下最流行的硬件描述语言之一。一般用于RTL级建模及行为级验证。
Verilog变量类型
两大变量类型:
- 线网型: 表示电路间的物理连接;
- 寄存器型: Verilog中的一个抽象的存储数据单元。
需要遵守的规则:
- 凡是在always和initial语句中赋值的变量,一定是寄存器变量;
- 在assign中赋值的一定是线网型变量。
线网类型
- wire、tri: 表示电路间连线,tri主要用于多驱动源建模;
- wor、trior: 表示该连线具有“线或”功能;
- wand、triand: 表示该连线具有“线与”功能;
- trireg: 表示该连线具有总线保持功能;
- tri1、tri0: 表示当无驱动时,连线状态为1(tri1)和0(tri0);
- supply1、supply2: 分别表示电源和地信号。
NOTICE:以上类型,除trireg未初始化时为“X”外,其余的未初始化值为“Z”。
寄存器类型
- reg: 是最常用的寄存器类型,可以是一位或多位,或者是二维数组(存储器);
- integer: 整型数据,存储一个至少32位的整数;
- time: 时间类型,存储一个至少64位的时间值;
- real、realtime: 实数和实数时间寄存器。
存储器声明举例:
与一维的reg变量不同的是,存储器中的存储单元不能再做位选择或部分选择,但每个单元可以单独整体赋值。
integer变量通常用于高层次建模,也常用在for语句的索引中,例如:
此外,time变量用于存储和处理系统时间,real和realtime用来存储实数和实数时间。
驱动和赋值(driving and assigning)
- 线网是被驱动的,该值不被保持,在任意一个仿真步进上都需要重新计算;
- 寄存器是被赋值的,且该值在仿真过程中被保持,直到下一个赋值出现。
参数(parameter)
参数是一种常量,通常出现在module内部。它常常被用作定义状态机的状态、数据位宽和延时大小等。
例如:
参数的值可以在编译时改变,因此它经常被用于一些参数可调的模块当中,让用户在实例化模块时,根据需要配置参数。
parameter比`define编译指令更加灵活。
Verilog中的并发与顺序
为了描述硬件的并发性,Verilog语言的module中,所有的描述语句之间都是并行发生的。任何功能描述语言,在Verilog的module中的顺序都不重要。
但是,在语句块(always 和 initial)内部,则可以存在两种语句组:
- begin…end: 顺序语句组;
- fork…join: 并行语句组;
操作数、操作符和表达式
操作符

操作符的优先级

连接、复制运算符
操作数
在verilog语言中,操作数可以是如下几种:
- 常数
- 参数
- 线网
- 寄存器
- 向量的位选择
- 向量的部分选择
- 存储器单元
- 系统函数或用户自定义函数调用的返回值。
在Verilog中,无符号数用以下3种形式存在:
- 线网变量;
- 一般寄存器变量;
- 基数格式表示形式的整数常数。
而有符号:
- 整型寄存器变量;
- 十进制形式的整型常量。
系统任务和系统函数
在Verilog语言中,预先定义了一些任务和函数,用于完成一些特殊的功能,它们被称为系统任务和系统函数。Verilog能提供的系统任务和系统函数类型如下:
- 显示任务(display task):
$display
。
- 文件输入/输出任务(file I/O task):
$fopen
用于打开一个文件,并返回一个整数的文件指针,然后$fdisplay
就可以实用整个文件指针向文件中写入信息,写完后,实用$fclose
关闭文件。
- 时间标度任务(timescale task);
- 模拟控制任务(simulation control task);
- 时序验证任务(timing check task);
- PLA建模任务(PLA modeling task);
- 随机建模任务(stochastic modeling task);
- 实数变换函数(conversion function for real);
- 概率分布函数(probabilistic distribution function)。
- ………
描述方式
Verilog语言中三种最基本的描述方式:
- 数据流描述
- 行为描述
- 结构化描述
数据流描述
最基本的数据流描述语句:
assign
对延时进行建模
例如:
在一些电路模型中,延时分为最大、典型和最小三种情况,延时信号可以采用
min:type:max
来表示。多驱动源线网
对wire进行多驱动会出现错误,导致wire变量变为x。
三态总线功能
实用tri。
行为描述
initial或always过程快(procedual block)
initial和always语句都是在0仿真时间开始执行。
举例:
过程块中的语句
- 非阻塞过程赋值;
- 阻塞过程赋值;
- 连续过程赋值;
- 高级编程语句。
时序控制
在行为描述中的时序控制:
- 时间语句(“@”): 多个条件语句可以用“,”或“or”隔开,表示任意一个发生皆可;
- 延时语句(“#”);
- 等待语句: 用法为
wait (expression);
//多数综合工具不支持
过程赋值语句
所谓过程赋值语句,就是在initial和always语句块中的赋值语句。赋值对象只能是寄存器变量类型。右边的表达式可以使任意操作符的表达式。
- 阻塞赋值:
=
,建议在对组合逻辑建模时使用。
- 非阻塞赋值:
<=
,通常利用非阻塞赋值的特点来对时序逻辑进行建模。
过程连续赋值语句
- assign & deassign: 在过程语句块中对寄存器变量强制赋值和放开;
- force & release: 在过程语句块中对寄存器或线网进行强制赋值和放开。
语句组
- begin…end
- fork…join
语句组的标识符
语句组可以有标识符,也可以没有。当一个语句组有标识符时,在语句组内部可以定义局部变量,而不会传递到语句组的外部。不过,整个变量时静态变量,它的值在整个仿真运行周期中时不变的,但是不会与其他语句组中同一个名称的变量发生冲突。
高级编程语句
编程语句只能出现在initial和always的过程块中,共分三大类:
- if…else;
- case;
- 循环语句: forever、repeat、while、for
if..else
在进行组合逻辑建模时注意不要引入Latch电路:
What is Latch?
在描述时序逻辑建模时,通常利用if语句的隐式条件对带时钟使能的D触发器建模:
case
与if..else语句不同的是,在case语句中,所有被判断的粉质条件都具有一样的优先级。同时,也要考虑到Latch意外产生的情况,不需要break;
派生语句: casez、casex
格式如下:
循环语句
- forever: 永远循环
- repeat: 执行固定次数
- while: 当表达式为真时执行
- for: 从初始值开始,如果表达式为真就执行
结构化描述
- 实例化门原语;
- 实例化用户自定义原语(UDP);
- 实例化模块(module)。
模块实例化的端口连接规则
模块内部端口属性:
- input: 在模块内部默认是一个线网类型;
- output: 在模块内部是一个寄存器或者线网类型;
- inout: 在模块内部默认是一个线网类型,是双向信号,一般定义为tri;
当整个模块被实例化时,与之相连的信号类型如下:
- 与模块input端口相连: 线网或寄存器;
- 与模块output端口相连:一定是驱动到一个线网;
- 与模块inout端口相连:输入时从一个线网驱动来,输出时驱动到一个线网。
举例:
参数化模块
参数的定义
module中的参数一般是定义其中常量的工具。
实际上,在Verilog语言中,在实例化模块时,用户可以修改模块中的参数,用来实现不同的特性。这个定制过程通过“新参数直接带入”或“参数重定义”完成。
参数的定制
参数的用户定制有两种方法:
- 通过defparam关键字对模块中的参数重新定义;
- 参数直接在实例化模块时带入。
参数用法补充
参数的声明既可以放到模块头上也可以放在模块内部
一旦有模块参数被写在模块头部,则出现在模块内部的模块参数被视为本地参数(不能被重写)。
模块参数重写方式
本地参数重写关键字
localparam
参数疑问?
- 参数能够用在数据长度表示吗?PARA’b1;
- 参数能用在{}字符中吗?
- 不同长度的数据能够相加吗?
CRC计算与校验电路实例(行为级建模与RTL级建模对比)
CRC10功能示意图:

CRC10校验,行为级
当从行为建模的角度来考虑CRC10的实现方式,由于不同考虑代码的硬件实现面积和性能等参数,可以将12 * 32位的数据一次性移入CRC10寄存器中。
以上实例中,不会考虑代码的硬件实现结果,而是采用最方便、最简洁的方式实现CR10的计算。
CRC10计算电路,RTL级
上述实例采用了两层索引方式,将12*32位数据通识一如了CRC10寄存器中,并不考虑实现该电路需要多少时钟周期。但是如果需要设计电路,也就是设计RTL代码,就需要考虑需要多少个时钟周期,实现的寄存器和寄存器之间有多少逻辑级数。
如果将12*32位数据在一个时钟周期内一次移入CRC10寄存器,组合逻辑数显然过高,因此可以分为12个时钟周期移入CRC10寄存器,每个时钟周期处理32位,这样就可以保证CRC10电路的性能。
RTL概念与常用RTL建模
- RTL级语言的重要特性:可综合的表述层次;
- 对时钟这一个概念的认识过于浅薄了———2023.12.1
- 综合:指将HDL语言、原理图等设计输入翻译成由与、或、非门等基本逻辑单元组成的门级连接,输出门级网表文件;
典型RTL设计的三个部分
- 时钟域描述:描述设计所使用的所有时钟,时钟之间的主从与派生关系,时钟域之间的转换;
- 时序逻辑描述(寄存器描述):根据时钟沿的变换,描述寄存器之间的数据传输方式;
- 组合逻辑描述:描述电平敏感信号的逻辑组合方式与逻辑功能;
RTL描述中 时序逻辑 和 组合逻辑 的连接关系和拓扑结构决定了设计的性能。
RTL级代码的设计步骤
- 功能定义与模块划分;
- 定义所有模块的接口;
- 设计时钟域;(这一块十分陌生)
- 考虑设计的关键路径:关键路径是指设计中时序要求最难以满足的路径。设计的时序要求主要体现在频率、建立时间、保持时间等时序指标上;
- 顶层设计;
- FSM设计;
- 时序逻辑设计:首先根据时钟域规划好寄存器组,然后描述各个寄存器组之间的数据传输方式;
- 组合逻辑设计;
常用RTL级建模
- 非阻塞赋值、阻塞赋值、连续赋值;
- 寄存器电路建模;
- 组合逻辑建模;
- 组合逻辑建模;
- 存储器建模;
- 简单的时钟分频电路;
- 串并转换建模;
同步复位的优缺点:
优点:
- 同步复位利于基于周期机制的仿真器进行仿真;
- 使用同步复位可以设计100%的同步时序电路,利于时序分析,其综合结果的频率往往较高;
- 同步复位仅在适中的有效沿生效,可以有效避免因复位电路毛刺造成的亚稳态和错误。在进行复位和释放复位信号时,都是仅当时钟沿采到复位信号电平变化时才进行相关操作,如果复位信号树的组合逻辑出现了某种毛刺,此时时钟沿采样到毛刺的概率非常低,通过时钟沿采样,可以十分有效地过滤复位电路组合逻辑产生的毛刺,增强电路稳定性;
缺点:
- 同步复位的最大问题在于必须保证复位信号的有效时间足够长,从而才能保证所有触发器都能够有效地复位。
异步复位的优缺点:
优点:
- 由于多数目标器件(如FPGA和CPLD)和ASIC库的触发器都包含异步复位端口,异步复位会节约逻辑资源;
- 异步复位设计简单;
- 度与大多数FPGA,都有专用的全局异步复位资源(GSR),使用GSR资源,异步复位到达所有寄存器的偏斜最小;
缺点:
- 异步复位的作用和释放与时钟沿没有直接关系,在异步复位生效时问题并不明显,但是当异步复位释放时,如果异步复位信号释放时间和时钟的有效沿到达时间几乎一致,则容易造成触发器输出为亚稳态,造成逻辑错误;
- 如果异步复位树的组合逻辑产生了毛刺,则毛刺的有效沿会使触发器误复位,造成严重的逻辑错误;
推荐使用的复位电路设计方式
- 推荐的复位电路设计方式是异步复位,同步释放。这种方式可以有效地继承异步复位设计简单的优势,并克服异步复位的上述风险与缺陷;
- 在FPGA/CPLD等可编程逻辑器件中,使用异步复位,同步释放可以节约器件资源,并获得稳定可靠地复位效果,是推荐的复位设计方式。
举例:
先利用clk对rst_进行一次取样,在利用reset_reg进行复位,实现了异步复位同步化;
case & if…else建模
- case语句是“平行的”结构,每个case分支的条件判断和执行都是并行的,没有“优先级”;
- if…else if…else if…语句可以建模无优先级的判断结构,if…if…if…结构可以建模具有优先级的判断结构;
- 建立优先级结构会消耗组合逻辑资源;
可综合的Verilog语法子集
常用RTL语法结构列举如下:
- 模块声明:module…endmodule
- 端口声明:input、output、inout
- 信号类型:wire、reg、tri等,integer通常用于for语句中的索引
- 参数定义:parameter
- 运算操作符
- 比较判断
- 连续赋值:assign、?:
- always模块
- 语法分隔符:begin…end
- 任务定义:tast…endtask
- 循环语句:for
学习疑问
- 什么是毛刺现象?为什么同步逻辑能够避免毛刺现象的影响?
- 异步逻辑为什么与同步逻辑相比并不可靠?其设计为什么要比同步逻辑要简单?
RTL设计与编码指导
一般性指导原则
面积和速度的平衡与互换原则
- 从理论上来讲,如果一个设计的时间余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计消耗的芯片面积;
- 反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么一般可以通过将数据流串/并转换,并行复制多个操作模块,对整个设计采取“乒乓操作”和“串/并转换”的思想进行处理,在芯片输出模块处在进行“并/串转换”处理。
硬件原则
HDL语言便于描述的3大硬件特性:
- 互连;
- 并发;
- 时间;
HDL语言设计与其他软件语言不同,其本质是为了描述真实的硬件电路,因此,在进行编码时,必须要对所涉及的硬件电路胸有成竹,再用适当的HDL语言进行表达。
在系统上复用模块节省的面积远比在代码上小打小闹来的实惠多。
系统原则
系统原则要求设计者将目标器件看做一个系统,对系统中的每个单元进行有效地
同步设计原则和多时钟处理
异步时序设计与同步时序设计
异步电路与同步电路的异同
。。。
同步时序设计
同步时序设计的基本原则是使用时钟沿触发所有的操作。如果所有寄存器的时序要求(Setup、Hold时间等指标)都能够满足,则同步时序设计与异步时序设计相比,在不同的PVT(工艺、电压、温度)条件下能获得更佳的系统稳定性与可靠性。
同步设计中,稳定可靠的数据采样必须遵从以下两个基本条件:
- 在有效时钟沿到达前,数据输入至少已经稳定了采样寄存器的Setup时间之久,这条原则简称满足Setup时间原则;
- 在有效时钟沿到达后,数据输入至少还将稳定保持采样寄存器的Hold时间之久,这条原则建成满足Hold时间原则;
同步时序设计有以下几个注意事项:
- 异步时钟域的数据转换;
- 组合逻辑电路的设计方法;
- 同步时序电路的时钟设计;
- 同步时序电路的延迟。
亚稳态
- 作者:Tdotd
- 链接:https://www.tdotd.top//article/verilog-learn
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。