数字集成电路设计入门
--从 HDL到版图于敦山北大微电子学系课程内容 (一 )
介绍 Verilog HDL,内容包括:
– Verilog应用
– Verilog语言的构成元素
– 结构级描述及仿真
– 行为级描述及仿真
– 延时的特点及说明
– 介绍 Verilog testbench
激励和控制和描述
结果的产生及验证
– 任务 task及函数 function
– 用户定义的基本单元 (primitive)
– 可综合的 Verilog描述风格课程内容 (二 )
介绍 Cadence Verilog仿真器,内容包括:
– 设计的编译及仿真
– 源库 (source libraries)的使用
– 用 Verilog-XL命令行界面进行调试
– 用 NC Verilog Tcl界面进行调试
– 图形用户界面 (GUI)调试
– 延时的计算及反标注 (annotation)
– 性能仿真描述
– 如何使用 NC Verilog仿真器进行编译及仿真
– 如何将设计环境传送给 NC Verilog
– 周期 (cycle)仿真课程内容 (三 )
逻辑综合的介绍
– 简介
– 设计对象
– 静态时序分析 (STA)
– design analyzer环境
– 可综合的 HDL编码风格
可综合的 Verilog HDL
– Verilog HDL中的一些窍门
– Designware库
– 综合划分
实验 (1)
课程内容 (四 )
设计约束( Constraint)
– 设置设计环境
– 设置设计约束
设计优化
– 设计编译
– FSM的优化
产生并分析报告
实验 (2)
课程内容 (五 )
自动布局布线工具 (Silicon Ensemble)简介课程安排
共 54学时 (18)
讲课,27学时
– Verilog (5)
– Synthesis (3)
– Place &Route (1)
实验,24学时
– Verilog (5)
– Synthesis (2)
– Place &Route (1)
考试,3学时参考书目
Cadence Verilog Language and Simulation
Verilog-XL Simulation with Synthesis
Envisia Ambit Synthesis
,硬件描述语言 Verilog,清华大学出版社,Thomas
&Moorby,刘明业等译,2001.8
第二章 Verilog 应用
学习内容
– 使用 HDL设计的先进性
– Verilog的主要用途
– Verilog的历史
– 如何从抽象级 (levels of abstraction)理解
电路设计
Verilog描述术语定义 (terms and definitions)
硬件描述语言 HDL:描述电路硬件及时序的一种编程语言
仿真器,读入 HDL并进行解释及执行的一种软件
抽象级,描述风格的详细程度,如行为级和门级
ASIC:专用集成电路 (Application Specific Integrated Circuit)
ASIC Vender:芯片制造商,开发并提供单元库
自下而上的设计流程,一种先构建底层单元,然后由底层单元构造更大的系统的设计方法 。
自顶向下的设计流程,一种设计方法,先用高抽象级构造系统,
然后再设计下层单元
RTL级,寄存器传输级 (Register Transfer Level),用于设计的可综合的一种抽象级
Tcl,Tool command Language,向交互程序输入命令的描述语言什么是硬件描述语言 HDL
具有特殊结构能够对硬件逻辑电路的功能进行描述的一种高级编程语言
这种特殊结构能够:
– 描述电路的连接
– 描述电路的功能
– 在不同抽象级上描述电路
– 描述电路的时序
– 表达具有并行性
HDL主要有两种,Verilog和 VHDL
– Verilog起源于 C语言,因此非常类似于 C语言,容易掌握
– VHDL起源于 ADA语言,格式严谨,不易学习。
– VHDL出现较晚,但标准化早。 IEEE 1706-1985标准。
为什么使用 HDL
使用 HDL描述设计具有下列优点:
– 设计在高层次进行,与具体实现无关
– 设计开发更加容易
– 早在设计期间就能发现问题
– 能够自动的将高级描述映射到具体工艺实现
– 在具体实现时才做出某些决定
HDL具有更大的灵活性
– 可重用
– 可以选择工具及生产厂
HDL能够利用先进的软件
– 更快的输入
– 易于管理
Verilog的历史
Verilog HDL是在 1983年由 GDA(GateWay Design Automation)公司的
Phil Moorby所创。 Phi Moorby后来成为 Verilog-XL的主要设计者和
Cadence公司的第一个合伙人。
在 1984~1985年间,Moorby设计出了第一个 Verilog-XL的仿真器。
1986年,Moorby提出了用于快速门级仿真的 XL算法。
1990年,Cadence公司收购了 GDA公司
1991年,Cadence公司公开发表 Verilog语言,成立了 OVI(Open
Verilog International)组织来负责 Verilog HDL语言的发展。
1995年制定了 Verilog HDL的 IEEE标准,即 IEEE1364。
Verilog的用途
Verilog的主要应用包括:
– ASIC和 FPGA工程师编写可综合的 RTL代码
– 高抽象级系统仿真进行系统结构开发
– 测试工程师用于编写各种层次的测试程序
– 用于 ASIC和 FPGA单元或更高层次的模块的模型开发抽象级 (Levels of Abstraction)
Verilog既是一种行为描述的语言也是一种结构描述语言。 Verilog模型可以是实际电路的不同级别的抽象。
这些抽象的级别包括:
系统说明
-设计文档 /算法描述
RTL/功能级
-Verilog
门级 /结构级
-Verilog
版图 /物理级
-几何图形行为综合综合前仿真逻辑综合综合后仿真版图抽象级 (Levels of Abstraction)
在抽象级上需要进行折衷系统说明
-设计文档 /算术描述
RTL/功能级
-Verilog
门级 /结构级
-Verilog
版图 /物理级
-几何图形详细程度低高输入 /仿真速度高低抽象级 (Levels of Abstraction)
Verilog可以在三种抽象级上进行描述
行为级
– 用功能块之间的数据流对系统进行描述
– 在需要时在函数块之间进行调度赋值。
RTL级 /功能级
– 用功能块内部或功能块之间的数据流和控制信号描述系统
– 基于一个已定义的时钟的周期来定义系统模型
结构级 /门级
– 用基本单元 (primitive)或低层元件 (component)的连接来描述系统以得到更高的精确性,特别是时序方面。
– 在综合时用特定工艺和低层元件将 RTL描述映射到门级网表抽象级 (Levels of Abstraction)
设计工程师在不同的设计阶段采用不同的抽象级
– 首先在行为级描述各功能块,以降低描述难度,提高仿真速度。
– 在综合前将各功能模块进行 RTL级描述。
– 用于综合的库中的大多数单元采用结构级描述。在本教程中的结构级描述部分将对结构级 (门级 )描述进行更详细的说明。
Verilog还有一定的晶体管级描述能力及算法级描述能力行为级和 RTL级
MUX的行为可以描述为:只要信号 a或 b或 sel发生变化,如果 sel
为 0则选择 a输出;否则选择 b输出。
module muxtwo (out,a,b,
sel);
input a,b,sel;
output out; reg out;
always @( sel or a or b)
if (! sel) out = a;
else out = b;
endmodule
这个行为级 RTL描述不处理 X和 Z状态输入,并且没有延时。
在行为级模型中,逻辑功能描述采用高级语言结构,如 @,while,wait,if,case。
Testbench(test fixture)通常采用行为级描述。所有行为级结构在 testbench描述中都可以采用。
RTL模型中数据流都是基于时钟的。任何时钟元件在时钟沿处的行为都要精确描述。 RTL级描述是行为级 Verilog的子集。
结构级描述
结构级 Verilog适合开发小规模元件,如 ASIC和 FPGA的单元
– Verilog内部带有描述基本逻辑功能的基本单元 (primitive),如 and门。
– 用户可以定义自己的基本单元 UDP(User Defined Privitives)
– 综合产生的结果网表通常是结构级的。用户可以用结构级描述粘接
(glue)逻辑。
下面是 MUX的结构级描述,采用 Verilog基本单元 (门 )描述。描述中含有传输延时。
module twomux (out,a,b,sl);
input a,b,sl;
output out;
not u1 (nsl,sl );
and #1 u2 (sela,a,nsl);
and #1 u3 (selb,b,sl);
or #2 u4 (out,sela,selb);
endmodule
综合不支持 !
仅需一种语言
Verilog的一个主要特点是可应用于各种抽象级。建模时可采用门级和 RTL级混合描述,在开发 testfixture时可以采用行为级描述。
复习
什么是 Verilog?
Verilog是公开的吗?
设计时什么时候采用 Verilog RTL级描述?
Verilog适合做什么样的设计?
解答:
Verilog是用于硬件描述的具有时间概念的并行编程语言
Verilog是一种公开语言,由 OVI负责组织,有 IEEE1394标准
RTL描述用于综合,或用于必须精确到每个时钟周期的模型的建模。
Verilog适用于各种抽象级模型的开发及验证第三章 Cadence仿真器
学习内容
– 逻辑仿真算法
– 如何启动 Verilog-XL和 NC Verilog仿真器
– 如何显示波形仿真算法
主要有三种仿真算法
– 基于时间的 (SPICE仿真器 )
– 基于事件的 (Verilog-XL和 NC Verilog仿真器 )
– 基于周期的 (cycle)
仿真算法
基于时间的算法用于处理连续的时间及变量
– 在每一个时间点对所有电路元件进行计算
– 效率低。在一个时间点只有约 2~10%的电路活动
基于事件的算法处理离散的时间、状态和变量
– 只有电路状态发生变化时才进行处理,只模拟哪些可能引起电路状态改变的元件。仿真器响应输入引脚上的事件,并将值在电路中向前传播。
– 是应用最为广泛的仿真算法
– 效率高。,evaluate when necessary”
基于周期的仿真以时钟周期为处理单位 (与时间无关 )
– 只在时钟边沿进行计算,不管时钟周期内的时序
– 使用两值逻辑 (1,0)
– 只关心电路功能而不关心时序,对于大型设计,效率高
– 仅适用于同步电路。
基于事件仿真的时轮 (time wheel)
仿真器在编译数据结构时建立一个事件队列。
只有当前时间片中所有事件都处理完成后,时间才能向前。
仿真从时间 0开始,而且时轮只能向前推进。只有时间 0的事件处理完后才能进入下一时片。
在同一个时间片内发生的事件在硬件上是并行的
理论上时间片可以无限。但实际上受硬件及软件的限制。
一个时间片的事件可引起新的事件,
在当前时片或以后时间片
timeslice
Cadence Verilog仿真器
Verilog-XL和 NC Verilog仿真器都是基于事件算法的仿真器。仿真器读入 Verilog HDL描述并进行仿真以反映实际硬件的行为。
Verilog-XL和 NC Verilog仿真器遵循 IEEE 1364
Verilog规范制定的基于事件的调度语义
仿真器可用于
– 确定想法的可行性
– 用不同的方法解决设计问题
– 功能验证
– 确定设计错误仿真过程
Verilog仿真分下列步骤:
– 编译
读入设计描述,处理编译指导 (compiler directive),建立一个数据结构定义设计的层次结构
这一步有时分为两步,compilation,elaboration
– 初始化
参数初始化;没有驱动的 Net缺省值为 Z;其它节点初始值为 X。这些值延着设计层次传播。
– 仿真
刚开始时间为 0时,仿真器将 initial和 always中的语句执行一次,遇到有时序控制时停止。这些赋值可产生在时间
0或其后时间的事件。
随着时间推进,被调度事件的执行引起更多的调度事件,
直至仿真结束。
Versus 交互式编译仿真器
Verilog-XL是一个交互式仿真器,过程如下:
1,读入 Verilog描述,进行语义语法检查,处理编译指导
(compiler directive)
2,在内存中将设计编译为中间格式,将所有模块和实例组装成层次结构 (设计数据结构 )。源代码中的每个元件都被重新表示并能在产生的数据结构 找到。
3,决定仿真的时间精度,在内存中构造一个事件队列的时间数据结构 (时轮 ) 。
4,读入、调度并根据事件执行每一个语句
Verilog-XL采用多种加速算法提高各种抽象级的仿真速度。
每次重新启动 Verilog-XL,将重复上述步骤。
当进入交互模式时,可以输入 Verilog HDL语句并加到设计的数据结构中。
Versus 交互式编译仿真
Verilog-XL仿真器是与 Verilog HDL同时开发的,因此它成为 Verilog HDL仿真器的事实上的标准。
Verilog-XL采用了多种加速算法,对每种抽象级描述都能很好的仿真。这些加速算法包括 Turbo算法,
XL算法及 Switch-XL算法。在后面的教程中将对这些算法进行更为详尽的介绍。
NC Verilog-全编译仿真
NC Verilog是全编译仿真器,它直接将 Verilog代码编译为机器码执行。其过程为:
– ncvlog编译 Verilog源文件,按照编译指导 (compile directive)
检查语义及语法,产生中间数据。
– ncelab按照设计指示构造设计的数据结构,产生可执行代码。
除非对优化进行限制,否则源代码中的元件 (element)可能被优化丢失。产生中间数据。
– ncsim启动仿真核。核调入设计的数据结构,构造事件序列
(时轮),调度并执行事件的机器码。有些事件可能消失 (从不执行 )除非限制优化过程。
编译后的所有代码的执行使用同一个核。
当重新启动仿真时,要对修改过的模块重新编译。省略这个手工过程的方法是直接对设计进行仿真,这将自动地对修改过的模块进行重新编译。
当采用交互模式时,可以使用 Tcl命令和针对 NC Verilog的 Tcl扩展命令。
NC Verilog全编译仿真
NC Verilog是最近才开发的,但其对描述的仿真与 Verilog-XL完全相同
NC Verilog仿真器用同一个核 (kernel)对所有抽象级进行混合仿真,
也就是说用户可以采用各种不同抽象级混合设计。但在门级仿真的效率差一些。
NC Verilog仿真器对源代码采用增量编译方式,减少了编译时间。
在交互模式下,可以使用 Tcl命令及其针对 NC Verilog的扩展命令来修改设计和控制仿真。这将在后面进行详细描述。
对 Verilog语言的支持
Verilog-XL和 NC Verilog计划支持 Verilog语言全集。
用户可依据下列标准进行设计:
IEEE1364-1995 Verilog语言参考手册
OVI 2.0 Verilog语言参考手册,但不支持:
Attributes,Verilog描述中对象的属性。
函数中 output或 inout变元 (argument),OVI2.0允许函数中 output
和 inout变元值能够返回。
启动 Verilog-XL
在命令窗口启动 Verilog-XL:
verilog [verilog-xl_options] design_files
没有 option启动的例子
verilog mux.v test.v
使用 – c选项只对设计进行语法和连接检查
verilog – c mux.v test.v
使用 -f选项指定一个包含命令行参数的文件
verilog –f run.f
run.f文件的内容
Verilog-XL将所有终端输出保存到名为 verilog.log的文件
mux.v
test.v
-c
启动 NC Verilog
虽然 NC Verilog仿真过程包括三个分立的步骤 (ncvlog,
ncelab,ncsim),但仿真时不需要三个命令,可以用带有命令行参数的 ncverilog命令启动 NC Verilog:
ncverilog [ncverilog_options] verilog-xl_arguments
Examples:
ncverilog mux.v test.v
ncverilog –c mux.v test.v
ncverilog –f run.f
run.f文件的内容
NC Verilog将所有终端输出保存到名为 ncverilog.log的文件
mux.v
test.v
-c
NC Verilog有什么不同?
除 +gui,-q和 -s这些只影响运行时间的参数外,其它任何命令行参数的改变将使设计重新编译,elaborate及仿真。
如果更新了源文件及仿真时用到的 SDF文件,则与它们相关的文件将重新编译,设计也将重新 elaborate和仿真。
NC Verilog为编译的元件及其它文件建立一个库结构。增量编译依赖于源文件,SDF文件和命令行参数。
ncverilog还有其它一些命令行参数,如
在调试时有完全的读、写及连接操作,用
+access + argument
ncverilog –f run.f + access+RWC
要得到源文件行操作能力,用 +linedebug
ncverilog -f run.f +linedebug
强制重编译所有设计单元,使用 +noupdate
NC Verilog有什么不同?
使用 +access选项可以设置对所有对象的缺省操作。
对象的缺省设置是无操作。用 +access+<args>打开操作,
+access-<args>关掉操作。 args可以是 R,W,C的任何组合。使用 +linedebug可以打开 R,W,C,同时可对源文件行进行操作,如在行上设置一断点。
使用 +noupdate强制重编译整个设计。缺省时只重新编译修改过的文件。只有当库可能被破坏时才这样做。
+gui选项启动图形界面; -q选项抑制标识信息; -s选项使仿真器在时间 0时停止,进入交互模式。
波形显示工具 —SignalScan
> signalscan & 或 signalscan 数据库文件名 &
波形显示工具 —SignalScan
Title Bar:显示这是 SignalScan窗口并以数字编号。若启动几个 SignalScan窗口它们将顺序编号。
Menu Bar:通过菜单可以执行所有基本命令。
Tool Bar中的按钮有,copy,cut,paste,undo,delete,zoom,
create marker,expand buses,launch the Design Brower等等。用户可以自定义。
在命令行输入 signalscan启动。 SignalScan窗口包括:
注:必须用 Design Brower在波形窗口中添加信号。
Groups Pane列出用户建立的波形组
Waveforms Region显示加入信号的波形
Names Pane在波形的左边显示信号名。这些信号名可以拖拽,
在 pane中双击右键可以移动插入的 marker
Time-Display Region显示两个指针的时间值及其时间差
SHM:波形数据库波形显示工具从数据库,如 SHM数据库中读取数据。使用下面的系统任务可以对 SHM数据库进行操作:
系统任务 描述
$shm_open(―waves.shm‖); 打开一个仿真数据库。同时只能打开一个库写入。
$shm_probe(); 选择信号,当它们的值变化时写入仿真库
$shm_close;
$shm_save;
关闭仿真库将仿真数据库写到磁盘例子:
initial
begin
$shm_open(“lab.shm”);
$shm_probe();
end
SHM:波形数据库仿真历史管理器 (Simulation History Manager,SHM)
数据库记录用户的设计在仿真时数据信号的变化。只记录用户要观察 (probe)的信号。
用户可以用 $shm_系统任务打开一个 SHM数据库,设置信号探针并将结果保存到数据库中。这些系统任务的功能除 $shm_probe外都非常直观。对 $shm_probe将在下面详细讨论。
用户必须在仿真前 (时间 0前 )设置探针信号才能看到信号在仿真过程中全部变化。
用 $shm_probe设置信号探针在 $shm_probe中使用 scope/node对作为参数。参数可以使用缺省值或两个参数都设置。例如:
$shm_probe( ); 观测当前范围 (scope)所有端口
$shm_probe(―A‖); 观测当前范围所有节点
$shm_probe(alu,adder); 观测实例 alu和 adder的所有端口
$shm_probe(―S‖,top.alu,―AC‖); 观测:
(1),当前范围及其以下所有端口,除库单元
(2),top.alu模块及其以下所有节点,包括库单元用 $shm_probe设置信号探针
$shm_probe的语法:
$shm_probe(scope0,node0,scope1,node1,...);
每个 node都是基于前面 scope的说明 (层次化的)
scope参数缺省值为当前范围 (scope)。 node参数缺省值为指定范围的所有输入、输出及输入输出。
node说明 保存到数据库存的信号
―A‖
―S‖
―C‖
―AS‖
―AC‖
指定范围的所有节点 (包括端口 (port))
指定范围及其以下所有端口,不包括库单元内部指定范围及其以下所有端口,包括库单元内部指定范围及其以下所有节点 (包括端口 ),不包括库单元内部指定范围及其以下所有节点 (包括端口 ),包括库单元内部相关工具
Affirma NC VHDL仿真器
Envisia Ambit综合工具
Verilog-XL故障仿真器,用于评价用户测试向量的有效性
SignalScan-TX图形界面调试工具包
Affirma equivalence checker完成门级设计之间或门级与 RTL级之间的静态功能验证
Affirma model checker形式验证工具,将 Verilog或 VHDL描述与设计说明进行验证
Affirma model packager,用户的 Verilog,VHDL或 C语言可执行模型分发时进行编译及分发许可证
Affirma Advanced Analysis Environment includes CoverScan,a
code profiler,and HAL,a lint checker
与 Cadence Verilog仿真器相关的工具有:
总结
逻辑仿真
运行 Verilog-XL和 NC Verilog仿真器
探测及显示波形本章学习内容复习
1,基于事件的仿真器是如何做到并行的?
2,时间 t的事件能否调度同一时间 t的事件?
3,NC Verilog仿真器不支持 IEEE 1364 Verilog LRM的什么元件?
1,通过调度在一个给定的时间片内发生的所有事件来得到并行性。实际上仿真器串行处理给定时间片内的事件,
但理论上它们都是在同一时间片内发生的。
2,任何时间片的事件能够调度在同一时间片或其以后产生的事件。
3,NC Verilog希望支持 IEEE 1364 LRM规范全集。目前主要还不支持实例阵列 (array of instances)。请参见产品发布手册。
第四章 设计举例
1,进一步学习 Verilog的结构描述和行为描述
2,Verilog混合(抽象)级仿真学习目标:
语言的主要特点
module(模块 )
module能够表示:
– 物理块,如 IC或 ASIC单元
– 逻辑块,如一个 CPU设计的 ALU部分
– 整个系统
每一个模块的描述从关键词 module开始,有一个 名称 (如
SN74LS74,DFF,ALU等等),由关键词 endmodule结束。
module是层次化设计的基本构件逻辑描述放在
module内部语言的主要特点 —模块端口 (module ports)
端口在模块名字后的括号中列出端口可以说明为
input,output及
inout
端口等价于硬件的引脚 (pin)
注意模块的名称 DFF,端口列表及说明
模块通过端口与外部通信语言的主要特点模块实例化 (module instances)
module DFF (d,clk,clr,q,qb);
....
endmodule
module REG4( d,clk,clr,q,qb);
output [3,0] q,qb;
input [3,0] d;
input clk,clr;
DFF d0 (d[ 0],clk,clr,q[ 0],qb[ 0]);
DFF d1 (d[ 1],clk,clr,q[ 1],qb[ 1]);
DFF d2 (d[ 2],clk,clr,q[ 2],qb[ 2]);
DFF d3 (d[ 3],clk,clr,q[ 3],qb[ 3]);
endmodule
语言的主要特点
可以将模块的实例通过端口连接起来构成一个大的系统或元件。
在上面的例子中,REG4有模块 DFF的四个实例。注意,每个实例都有自己的名字 (d0,d1,d2,d3)。实例名是每个对象唯一的标记,通过这个标记可以查看每个实例的内部。
实例中端口的次序与模块定义的次序相同。
模块实例化与调用程序不同。每个实例都是模块的一个完全的拷贝,相互独立、并行。
模块实例化 (module instances)
一个完整的简单例子 test fixture
被测试器件 DUT是一个二选一多路器。测试装置 (test fixture)提供测试激励及验证机制。
Test fixture使用行为级描述,DUT采用门级描述。下面将给出
Test fixture的描述,DUT的描述及如何进行混合仿真。
DUT 被测器件 (device under test)
module MUX2_1 (out,a,b,
sel);
// Port declarations
output out;
input a,b,sel;
wire out,a,b,sel;
wire sel_,a1,b1;
// The netlist
not (sel_,sel);
and (a1,a,sel_);
and (b1,b,sel);
or (out,a1,b1);
endmodule
注释行已定义的
Verilog基本单元的实例
a,b,sel是输入端口,out是输出端口。所有信号通过这些端口从模块输入 /输出。
另一个模块可以通过模块名及端口说明使用多路器。实例化多路器时不需要知道其实现细节。这正是自上而下设计方法的一个重要特点。
模块的实现可以是行为级也可以是门级,但并不影响高层次模块对它的使用。
多路器由关键词 module和
endmodule
开始及结束。
Test Fixture template
module testfixture;
// Data type declaration
// Instantiate modules
// Apply stimulus
// Display results
endmodule
为什么没有端口?
由于 testfixture是最顶层模块,不会被其它模块实例化。
因此不需要有端口。
Test Fixture — 如何说明实例
module testfixture;
// Data type declaration
// Instantiate modules
MUX2_1 mux (out,a,b,
sel);
// Apply stimulus
// Display results
endmodule
多路器实例化语句
MUX的实例化语句包括:
模块名字:与引用模块相同
实例名字:任意,但要符合标记命名规则
端口列表:与引用模块的次序相同
Test Fixture —过程 (procedural block)
所有过程在时间 0执行一次过程之间是并行执行的
过程语句有两种:
– initial,只执行一次
– always,循环执行
Test Fixture —过程 (procedural block)
通常采用过程语句进行行为级描述。 test fixture的激励信号在一个过程语句中描述。
过程语句的活动与执行是有差别的
– 所有过程在时间 0处于活动状态,并根据用户定义的条件等待执行;
– 所有过程并行执行,以描述硬件内在的并行性;
Test fixture 激励描述
module testfixture;
// Data type declaration
reg a,b,sel;
wire out;
// MUX instance
MUX2_1 mux (out,a,b,
sel);
// Apply stimulus
initial
begin
a = 0; b = 1; sel = 0;
#5 b = 0;
#5 b = 1; sel = 1;
#5 a = 1;
#5 $finish;
end
// Display results
endmodule
Time Values
a b sel
0 0 1 0
5 0 0 0
10 0 1 1
15 1 1 1
例子中,a,b,sel说明为 reg类数据。
reg类数据是寄存器类数据信号,在重新赋值前一直保持当前数据。
#5 用于指示等待 5个时间单位。
$finish是结束仿真的系统任务。
Test Fixture 响应产生
$time 系统函数,给出当前仿真时间
$monitor 系统任务,若参数列表中的参数值发生变化,
则在时间单位末显示参数值。
$monitor ([“format_specifiers”,] <arguments>);
例如:
$monitor($time,o,in1,in2);
$monitor($time,,out,,a,,b,,sel);
$monitor($time,“%b %h %d %o”,sig1,sig2,sig3,
sig4);
Verilog提供了一些系统任务和系统函数,包括:
注意不能有空格
Test Fixture 响应产生
$time是一个系统函数,返回当前返回仿真时间。时间用 64位整数表示。
$monitor 在 时间单位 末,若参数列表中的参数值发生变化则显示所列参数的值。由 $time引起的变化不会显示。
$monitor系统任务支持不同的数基。缺省数基是十进制。支持的数基还有二进制、八进制、十进制。
完整的 Test Fixture
module testfixture;
// Data type declaration
reg a,b,sel;
wire out;
// MUX instance
MUX2_1 mux (out,a,b,sel);
// Apply stimulus
initial begin
a = 0; b = 1; sel = 0;
#5 b = 0; #5 b = 1; sel = 1;
#5 a = 1;
#5 $finish;
end
// Display results
initial
$monitor($time,," out=%b a=%b b=%b sel=%b",out,a,b,
sel);
endmodule
0 out= 0 a= 0 b= 1 sel=
0
5 out= 0 a= 0 b= 0 sel=
0
10 out= 1 a= 0 b= 1 sel=
1
15 out= 1 a= 1 b= 1 sel=
1
结果输出时间单位末的概念
`timescale 1ns/1ns
module testfixture;
// Data type declaration
reg a,b,sel;
wire out;
// MUX instance
MUX2_1 mux (out,a,b,sel);
// Apply stimulus
initial begin
a = 0; b = 1; sel = 0;
#5.7 b = 0; #5 b = 1; sel = 1;
#5 a = 1; #5 $finish;
end
// Display results
initial
$monitor($time,," out=%b a=%b b=%b sel=%b",out,a,b,
sel);
endmodule
0 out= 0 a= 0 b= 1 sel=
0
6 out= 0 a= 0 b= 0 sel=
0
11 out= 1 a= 0 b= 1 sel=
1
16 out= 1 a= 1 b= 1 sel=
1
结果输出
VCD数据库
Verilog提供一系列系统任务用于记录信号值变化保存到标准的 VCD(Value Change Dump)格式数据库中。大多数波形显示工具支持 VCD格式。
系统任务 功能
$dumpfile("file,dump");
$dumpvars();
$dumpflush;
$dumpoff;
$dumpon;
$dumplimit(<file_ size>);
$dumpall;
打开一个 VCD数据库用于记录选择要记录的信号将 VCD数据保存到磁盘停止记录重新开始记录限制 VCD文件的大小 (以字节为单位)
记录所有指定的信号值
VCD数据库
用户可以用 $dump*系统任务打开一个数据库,保存信号并控制信号的保存。除 $dumpvars外,其它任务的作用都比较直观。
$dumpvars将在后面详细描述 。
必须首先使用 $dumpfile系统任务,并且在一次仿真中只能打开一个 VCD数据库。
在仿真前 (时间 0前 )必须先指定要观测的波形,这样才能看到信号完整的变化过程。
仿真时定期的将数据保存到磁盘是一个好的习惯,万一系统出现问题数据也不会全部丢失。
VCD数据库不记录仿真结束时的数据。因此如果希望看到最后一次数据变化后的波形,必须在结束仿真前使用 $dumpall。
VCD数据库是仿真过程中数据信号变化的记录。它只记录用户指定的信号。
$dumpvars
$dumpvars[(< levels>,<scope>*)];
scope可以是层次中的信号,实例或模块。
仿真时所有信号必须在同一时间下使用 $dumpvars。
就是说可以使用多条 $dumpvars语句,但必须从 同一时间 开始。如:
initial begin
$dumpfile (“verilog,dump”);
$dumpvars (0,testfixture.a);
#1 $dumpvars (0,testfixture.b);
end
$dumpvars语法:
此语句将引起一个警告信息并被忽略
$dumpvars
$dumpvars; // Dump所有层次的信号
$dumpvars (1,top); // Dump top模块中的所有信号
$dumpvars (2,top,u1); // Dump实例 top,u1及其下 一 层的信号
$dumpvars (0,top,u2,top,u1,u13,q); // Dump top.u2及其以下所有信号,以及信号 top,u1,u13,q。
$dumpvars (3,top,u2,top,u1); // Dump top,u1和 top,u2及其下两层中的所有信号。
用下面的代码可以代替前面 test fixture的 $monitor命令,
initial
begin
$dumpfile (“verilog,dump”);
$dumpvars (0,testfixture);
end
要给 $dumpvars提供层次 (levels)及范围 (scope)参数,例如复习
1,Verilog的基本构建模块是什么?是如何构成一个系统的?
2,module怎样与其它模块通信?
3,仿真时两个性质不同的模块是什么?
4,在 test fixture中两类不同的过程语句是什么?它们有什么不同?
5,用什么方法能以文本格式显示仿真结果?
1,module是基本构建单元。在 module中实例化另一个 module可以构成一个复杂的层次化系统。
2,module之间通过端口的连接进行互相通信
3,两个模块是设计模块和激励模块。设计模块又称为 DUT,激励模块又称为 testbench或 test fixture。测试模块用于设计模块验证
4,在 testbench中用到的两类过程语句是 initial和 always。其不同处是 initial只执行一次,而 always循环执行。
5,$monitor语句以文本格式显示仿真结果第五章 Verilog的词汇约定 (Lexical convention)
1,理解 Verilog中使用的词汇约定
2,认识语言专用标记 (tokens)
3,学习 timescale
学习内容:
术语及定义
1,空白符:空格,tabs及换行
2,Identifier,标志符,Verilog中对象 (如模块或端口 )的名字
3,Lexical,语言中的字或词汇,或与其相关。由其文法( grammar)或语法 (syntax)区分。
4,LSB:最低有效位 (Lease significant bit)
5,MSB:最高有效位 (Most significant bit)
空白符和注释
module MUX2_1 (out,a,b,sel);
// Port declarations
output out;
input sel,// control input
b,/* data inputs */ a;
/*
The netlist logic selects input,a” when
sel = 0 and it selects,b” when sel = 1.
*/
not (sel_,sel);
and (a1,a,sel_),(b1,b,sel); // What does this
line do?
or (out,a1,b1);
endmodule
格式自由使用空白符提高可读性及代码组织。 Verilog忽略空白符除非用于分开其它的语言标记。
多行注释,在 /* */内单行注释到行末结束整数常量和实数常量
整数的大小可以定义也可以不定义。整数表示为:
<size>’<base><value>
其中 size,大小,由十进制数表示的位数 (bit)表示。缺省为 32位
base,数基,可为 2(b),8(o),10(d),16(h)进制。缺省为 10进制
value,是所选数基内任意有效数字,包括 X,Z。
实数常量可以用十进制或科学表示法表示。
Verilog中,常量 (literals)可是整数也可以是实数
12 unsized decimal (zero-extended to 32 bits)
'H83a unsized hexadecimal (zero- extended to 32 bits)
8'b1100_ 0001 8-bit binary
64'hff01 64-bit hexadecimal (zero- extended to 64 bits)
9'O17 9-bit octal
32'bz01x Z-extended to 32 bits
3’b1010_ 1101 3-bit number,truncated to 3’b101
6.3 decimal notation
32e- 4 scientific notation for 0.0032
4.1E3 scientific notation for 4100
整数常量和实数常量
整数的大小可以定义也可以不定义。整数表示为:
– 数字中( _)忽略,便于查看
– 没有定义大小 (size)整数缺省为 32位
– 缺省数基为十进制
– 数基 (base)和数字 (16进制 )中的字母无大小写之分
– 当数值 value大于指定的大小时,截去高位。如 2’b1101表示的是 2’b01
实数常量
– 实数可用科学表示法或十进制表示
– 科学表示法表示方式:
<尾数 ><e或 E><指数 >,表示,尾数 × 10指数字符串( string)
字符串要在一行中用双引号括起来,也就是不能跨行。
字符串中可以使用一些 C语言转义 (escape)符,如 \t
\n
可以使用一些 C语言格式符 (如 %b)在仿真时产生格式化输出:
” This is a normal string”
”This string has a \t tab and ends with a new
line\n”
”This string formats a value,val = %b”
Verilog中,字符串大多用于显示信息的命令中。 Verilog没有字符串数据类型字符串( string)
转义符及格式符将在验证支持部分讨论格式符
%h %o %d %b %c %s %v %m %t
hex oct dec bin ACSII string strength module time
转义符
\t \n \\ \‖ \<1-3 digit octal number>
tab 换行 反斜杠 双引号 ASCII representation of above
格式符 %0d表示没有前导 0的十进制数标识符 (identifiers)
标识符是用户在描述时给 Verilog对象起的名字
标识符必须以字母 (a-z,A-Z)或 ( _ )开头,后面可以是字母、数字,( $ )或
( _ )。
最长可以是 1023个字符
标识符区分大小写,sel和 SEL是不同的标识符
模块、端口和实例的名字都是标识符
module MUX2_1 (out,a,b,sel);
output out;
input a,b,sel;
not not1 (sel_,sel);
and and1 (a1,a,sel_);
and and2 (b1,b,sel);
or or1 (out,a1,b1);
endmodule
Verilog标识符标识符 (identifiers)
有效标识符举例:
shift_reg_a
busa_index
_bus3
无效标识符举例:
34net // 开头不是字母或,_”
a*b_net // 包含了非字母或数字,,$”,_”
n@238 //包含了非字母或数字,,$”,_”
Verilog区分大小写,所有 Verilog关键词使用小写字母。
转义标识符 ( Escaped identifiers)
可以包含任何可打印字符
反斜杠及空白符不是标识符的一部分
module \2:1MUX (out,a,b,sel);
output out;
input a,b,sel;
not not1(\~sel,sel);
and and1( a1,a,\~sel );
and and2( b1,b,sel);
or or1( out,a1,b1);
endmodule
使用转义符可能会产生一些问题,并且不是所有工具都支持。
有时用转义符完成一些转换,如产生逻辑图的 Verilog网表。综合工具输出综合网表时也使用转义符。 不建议使用转义符。
转义标识符由反斜杠,\‖开始,空白符结束
Escaped Identifiers
转义标识符 ( Escaped identifiers)
转义标识符允许用户在标识符中使用非法字符。如:
\~#@sel
\busa+ index
\{A,B}
top.\ 3inst,net1 // 在层次化名字中转义符转义标识符必须以空格结束语言专用标记 ( tokens)
系统任务及函数
$<identifier>
$符号指示这是系统任务和函数
系统函数有很多,如:
– 返回当前仿真时间 $time
– 显示 /监视信号值 ($display,$monitor)
– 停止仿真 $stop
– 结束仿真 $finish
$monitor($time,“a = %b,b = %h”,a,b);
当信号 a或 b的值发生变化时,系统任务 $monitor显示当前仿真时间,信号 a值 (二进制格式 ),信号 b值( 16进制格式)。
语言专用标记 ( tokens)
延时说明
,#”用于说明过程 (procedural)语句和门的实例的延时,但不能用于模块的实例化。
module MUX2_ 1 (out,a,b,sel) ;
output out ;
input a,b,sel ;
not #1 not1( sel_,sel);
and #2 and1( a1,a,sel_);
and #2 and2( b1,b,sel);
or #1 or1( out,a1,b1);
endmodule
门延时有很多类名字:门延时 (gate delay),传输延时
(propagation delay),固有延时 (intrinsic delay),对象内在延时
(intra-object delay)
编译指导 (Compiler Directives)
( `)符号说明一个编译指导
这些编译指导使仿真编译器进行一些特殊的操作
编译指导一直保持有效直到被覆盖或解除
`resetall 复位所有的编译指导为缺省值,应该在其它编译指导之前使用文本替换 (substitution) - `define
编译指导 `define提供了一种简单的文本替换的功能
`define <macro_name> <macro_text>
在编译时 <macro_text>替换 <macro_name>。可提高描述的可读性。
`define not_delay #1
`define and_delay #2
`define or_delay #1
module MUX2_1 (out,a,b,sel);
output out;
input a,b,sel;
not `not_delay not1( sel_,
sel);
and `and_delay and1( a1,a,
sel_);
and `and_delay and2( b1,b,
sel);
or `or_delay or1( out,a1,
b1);
定义 not_delay
使用 not_delay
文本替换 (substitution)
解除定义的宏,使用
`undef macro_name
使用编译指导 `define,可以
– 提高描述的可读性
– 定义全局设计参数,如延时和矢量的位数。这些参数可以定义在同一位置。这样,当要修改设计配置时,只需要在一个地方修改。
– 定义 Verilog命令的简写形式
`define vectors_ file "/usr1/chrisz/library/vectors"
`define results_ file "/ usr1/chrisz/library/results"
可以将 `define放在一个文件中,与其它文件一起编译。
文本包含 (inclusion) - `include
编译指导 `include在当前内容中插入一个文件格式,`include,<file_name>”
如 `include "global.v"
`include "parts/count,v"
`include "../../library/mux,v”
`include可用于:
– include保存在文件中的全局的或经常用到的一些定义,如文本宏
– 在模块内部 include一些任务( tasks),提高代码的可维护性。
可以是相对路径或绝对路径
Timescale
`timescale 说明时间单位及精度格式,`timescale <time_unit> / <time_precision>
如,`timescale 1 ns / 100 ps
time_unit,延时或时间的测量单位
time_precision,延时值超出精度要先舍入后使用
`timescale必须在模块之前出现
`timescale 1 ns / 10 ps
// All time units are in multiples of 1 nanosecond
module MUX2_1 (out,a,b,sel);
output out;
input a,b,sel;
not #1 not1( sel_,sel);
and #2 and1( a1,a,sel_);
and #2 and2( b1,b,sel);
or #1 or1( out,a1,b1);
endmodule
Timescale
time_precision不能大于 time_unit
time_precision和 time_unit的表示方法,integer unit_string
– integer,可以是 1,10,100
– unit_string,可以是 s(second),ms(millisecond),us(microsecond),
ns(nanosecond),ps(picosecond),fs(femtosecond)
– 以上 integer和 unit_string可任意组合
precision的时间单位应尽量与设计的实际精度相同。
– precision是仿真器的仿真时间步。
– 若 time_unit与 precision_unit差别很大将严重影响仿真速度。
– 如说明一个 `timescale 1s / 1ps,则仿真器在 1秒内要扫描其事件序列 1012次;而 `timescale 1s/1ms则只需扫描 103次。
如果没有 timescale说明将使用缺省值,一般是 ns。
Timescale
所有 timescale中的最小值决定仿真时的最小时间单位。
这是因为仿真器必须对整个设计进行精确仿真在下面的例子中,仿真时间单位( STU)为 100fs
`timescale 1ns/ 10ps
module1 (.,,);
not #1.23 (.,,) // 1.23ns or 12300 STUs
.,,
endmodule
`timescale 100ns/ 1ns
module2 (.,,);
not #1.23 (.,,) // 123ns or 1230000 STUs
.,,
endmodule
`timescale 1ps/ 100fs
module3 (.,,);
not #1.23 (.,,) // 1.23ps or 12 STUs (rounded off)
.,,
endmodule
复习
1,Verilog中的空白符总是忽略的吗?
2,在源代码中插入注释有哪两种方法?
3,整数常数的尺寸如何指定?缺省的尺寸及数基是多少?
4,设置的编译指导如何解除?
5,编译指导影响全局吗?
6,在仿真时为什么要用接近实际的最大 timescale精度?
1,是的。空白符用于隔开标识符及关键词,多余的忽略
2,//用于单行注释,/* */用于多行注释
3,整数常量的尺寸由 10进制数表示的位数确定。缺省为 32位,缺省的数基为十进制。
4,使用 `resetall解除
5,编译指导是全局的。编译时遇到编译指导后开始有效,直至复位或被覆盖,可能影响多个文件。
6,使用尽可能大的精度。精度越小,仿真时间步越小,仿真时间越长。使用适当的精度,既达到必要的精度,又不会仿真太慢。