数字集成电路设计入门 --从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)仿真
课程内容(三) 逻辑综合的介绍 可综合的Verilog HDL 实验 (1) 简介 设计对象 静态时序分析 (STA) design analyzer环境 可综合的HDL编码风格 可综合的Verilog HDL Verilog HDL中的一些窍门 Designware库 综合划分 实验 (1)
课程内容(四) 设计约束( Constraint) 设计优化 产生并分析报告 实验 (2) 设置设计环境 设置设计约束 设计编译 FSM的优化 产生并分析报告 实验 (2)
课程内容(五) 自动布局布线工具(Silicon Ensemble)简介
课程安排 共54学时 (18) 讲课,27学时 实验,24学时 考试,3学时 Verilog (5) Synthesis (3) 共54学时 (18) 讲课,27学时 Verilog (5) Synthesis (3) Place &Route (1) 实验,24学时 Synthesis (2) 考试,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能够利用先进的软件 设计在高层次进行,与具体实现无关 设计开发更加容易 早在设计期间就能发现问题 能够自动的将高级描述映射到具体工艺实现 在具体实现时才做出某些决定 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 门级/结构级 版图/物理级 -几何图形
抽象级(Levels of Abstraction) 在抽象级上需要进行折衷 系统说明 -设计文档/算术描述 RTL/功能级 -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是一种公开语言, 由OVI负责组织,有IEEE1394标准 RTL描述用于综合,或用于必须精确到每个时钟周期的模型的建模。 Verilog适用于各种抽象级模型的开发及验证
第三章 Cadence仿真器 学习内容 逻辑仿真算法 如何启动Verilog-XL和NC Verilog仿真器 如何显示波形
仿真算法 主要有三种仿真算法 基于时间的(SPICE仿真器) 基于事件的(Verilog-XL和NC Verilog仿真器) 基于周期的(cycle)
仿真算法 基于时间的算法用于处理连续的时间及变量 基于事件的算法处理离散的时间、状态和变量 基于周期的仿真以时钟周期为处理单位(与时间无关) 在每一个时间点对所有电路元件进行计算 效率低。在一个时间点只有约2~10%的电路活动 基于事件的算法处理离散的时间、状态和变量 只有电路状态发生变化时才进行处理,只模拟哪些可能引起电路状态改变的元件。仿真器响应输入引脚上的事件,并将值在电路中向前传播。 是应用最为广泛的仿真算法 效率高。“evaluate when necessary” 基于周期的仿真以时钟周期为处理单位(与时间无关) 只在时钟边沿进行计算,不管时钟周期内的时序 使用两值逻辑 (1, 0) 只关心电路功能而不关心时序,对于大型设计,效率高 仅适用于同步电路。
基于事件仿真的时轮(time wheel) 一个时间片的事件可引起新的事件,在当前时片或以后 时间片 timeslice 仿真器在编译数据结构时建立一个事件队列。 只有当前时间片中所有事件都处理完成后,时间才能向前。 仿真从时间0开始,而且时轮只能向前推进。只有时间0的事件处理完后才能进入下一时片。 在同一个时间片内发生的事件在硬件上是并行的 理论上时间片可以无限。但实际上受硬件及软件的限制。
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是一个交互式仿真器,过程如下: 读入Verilog描述,进行语义语法检查,处理编译指导(compiler directive) 在内存中将设计编译为中间格式,将所有模块和实例组装成层次结构(设计数据结构)。源代码中的每个元件都被重新表示并能在产生的数据结构 找到。 决定仿真的时间精度,在内存中构造一个事件队列的时间数据结构(时轮) 。 读入、调度并根据事件执行每一个语句 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有什么不同? NC Verilog为编译的元件及其它文件建立一个库结构。增量编译依赖于源文件、SDF文件和命令行参数。 除+gui、-q和-s这些只影响运行时间的参数外,其它任何命令行参数的改变将使设计重新编译、elaborate及仿真。 如果更新了源文件及仿真时用到的SDF文件,则与它们相关的文件将重新编译,设计也将重新elaborate和仿真。 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 在命令行输入signalscan启动。SignalScan窗口包括: Title Bar:显示这是SignalScan窗口并以数字编号。若启动几个SignalScan窗口它们将顺序编号。 Menu Bar:通过菜单可以执行所有基本命令。 Tool Bar中的按钮有:copy, cut, paste, undo, delete, zoom, create marker, expand buses, launch the Design Brower等等。用户可以自定义。 注:必须用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(“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)) 指定范围及其以下所有端口,不包括库单元内部 指定范围及其以下所有端口,包括库单元内部 指定范围及其以下所有节点(包括端口),不包括库单元内部 指定范围及其以下所有节点(包括端口),包括库单元内部
相关工具 与Cadence Verilog仿真器相关的工具有: 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
总结 本章学习内容 逻辑仿真 运行Verilog-XL和NC Verilog仿真器 探测及显示波形
复习 基于事件的仿真器是如何做到并行的? 时间t的事件能否调度同一时间t的事件? NC Verilog仿真器不支持IEEE 1364 Verilog LRM的什么元件? 通过调度在一个给定的时间片内发生的所有事件来得到并行性。实际上仿真器串行处理给定时间片内的事件,但理论上它们都是在同一时间片内发生的。 任何时间片的事件能够调度在同一时间片或其以后产生的事件。 NC Verilog希望支持IEEE 1364 LRM规范全集。目前主要还不支持实例阵列(array of instances)。请参见产品发布手册。
第四章 设计举例 学习目标: 进一步学习Verilog的结构描述和行为描述 Verilog混合(抽象)级仿真
语言的主要特点 module(模块) module是层次化设计的基本构件 逻辑描述放在module内部 module能够表示: 物理块,如IC或ASIC单元 逻辑块,如一个CPU设计的ALU部分 整个系统 每一个模块的描述从关键词module开始,有一个名称(如SN74LS74,DFF,ALU等等),由关键词endmodule结束。
语言的主要特点—模块端口(module ports) 端口等价于硬件的引脚(pin) 端口在模块名字后的括号中列出 端口可以说明为input, output及inout 注意模块的名称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]);
语言的主要特点 模块实例化(module instances) 可以将模块的实例通过端口连接起来构成一个大的系统或元件。 在上面的例子中,REG4有模块DFF的四个实例。注意,每个实例都有自己的名字(d0, d1, d2, d3)。实例名是每个对象唯一的标记,通过这个标记可以查看每个实例的内部。 实例中端口的次序与模块定义的次序相同。 模块实例化与调用程序不同。每个实例都是模块的一个完全的拷贝,相互独立、并行。
一个完整的简单例子 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 注释行 多路器由关键词module和endmodule开始及结束。 a, b, sel是输入端口,out是输出端口。所有信号通过这些端口从模块输入/输出。 另一个模块可以通过模块名及端口说明使用多路器。实例化多路器时不需要知道其实现细节。这正是自上而下设计方法的一个重要特点。模块的实现可以是行为级也可以是门级,但并不影响高层次模块对它的使用。 已定义的 Verilog基本单元的实例
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) 过程语句有两种: initial :只执行一次 always :循环执行 所有过程在时间0执行一次 过程之间是并行执行的
Test Fixture —过程(procedural block) 过程语句的活动与执行是有差别的 所有过程在时间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 响应产生 Verilog提供了一些系统任务和系统函数,包括: $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); 注意不能有空格
Test Fixture 响应产生 $time是一个系统函数,返回当前返回仿真时间。时间用64位整数表示。 $monitor 在时间单位末,若参数列表中的参数值发生变化则显示所列参数的值。由$time引起的变化不会显示。 $monitor系统任务支持不同的数基。缺省数基是十进制。支持的数基还有二进制、八进制、十进制。
完整的Test Fixture 结果输出 0 out= 0 a= 0 b= 1 sel= 0 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
时间单位末的概念 结果输出 0 out= 0 a= 0 b= 1 sel= 0 6 out= 0 a= 0 b= 0 sel= 0 `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数据库 VCD数据库是仿真过程中数据信号变化的记录。它只记录用户指定的信号。 用户可以用$dump*系统任务打开一个数据库,保存信号并控制信号的保存。除$dumpvars外,其它任务的作用都比较直观。 $dumpvars将在后面详细描述。 必须首先使用$dumpfile系统任务,并且在一次仿真中只能打开一个VCD数据库。 在仿真前(时间0前)必须先指定要观测的波形,这样才能看到信号完整的变化过程。 仿真时定期的将数据保存到磁盘是一个好的习惯,万一系统出现问题数据也不会全部丢失。 VCD数据库不记录仿真结束时的数据。因此如果希望看到最后一次数据变化后的波形,必须在结束仿真前使用$dumpall。
$dumpvars $dumpvars语法: $dumpvars[(< levels>, <scope>*)]; initial begin $dumpfile (“verilog. dump”); $dumpvars (0, testfixture.a); #1 $dumpvars (0, testfixture.b); end 此语句将引起一个警告信息并被忽略
$dumpvars 要给$dumpvars提供层次(levels)及范围(scope)参数,例如 $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
复习 Verilog的基本构建模块是什么?是如何构成一个系统的? module怎样与其它模块通信? 仿真时两个性质不同的模块是什么? 在test fixture中两类不同的过程语句是什么?它们有什么不同? 用什么方法能以文本格式显示仿真结果? module是基本构建单元。在module中实例化另一个module可以构成一个复杂的层次化系统。 module之间通过端口的连接进行互相通信 两个模块是设计模块和激励模块。设计模块又称为DUT,激励模块又称为testbench或test fixture。测试模块用于设计模块验证 在testbench中用到的两类过程语句是initial和always。其不同处是initial只执行一次,而always循环执行。 $monitor语句以文本格式显示仿真结果
第五章 Verilog的词汇约定(Lexical convention) 学习内容: 理解Verilog中使用的词汇约定 认识语言专用标记(tokens) 学习timescale
术语及定义 空白符:空格、tabs及换行 Identifier: 标志符,Verilog中对象(如模块或端 口)的名字 Lexical: 语言中的字或词汇,或与其相关。由其 文法(grammar)或语法(syntax)区分。 LSB:最低有效位(Lease significant bit) 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忽略空白符除非用于分开其它的语言标记。 单行注释 到行末结束 多行注释,在/* */内
整数常量和实数常量 Verilog中,常量(literals)可是整数也可以是实数 整数的大小可以定义也可以不定义。整数表示为: <size>’<base><value> 其中 size :大小,由十进制数表示的位数(bit)表示。缺省为32位 base:数基,可为2(b)、8(o)、10(d)、16(h)进制。缺省为10进制 value:是所选数基内任意有效数字,包括X、Z。 实数常量可以用十进制或科学表示法表示。 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) Verilog中,字符串大多用于显示信息的命令中。Verilog没有字符串数据类型 字符串要在一行中用双引号括起来,也就是不能跨行。 字符串中可以使用一些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”
字符串(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标识符 标识符是用户在描述时给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 <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); endmodule 定义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 “<file_name>” 如 `include "global.v" `include "parts/count. v" `include "../../library/mux. v” `include可用于: include保存在文件中的全局的或经常用到的一些定义,如文本宏 在模块内部include一些任务(tasks),提高代码的可维护性。 可以是相对路径或绝对路径
Timescale `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 `timescale 1ps/ 100fs module3 (. . .); not #1.23 (. . .) // 1.23ps or 12 STUs (rounded off)
复习 Verilog中的空白符总是忽略的吗? 在源代码中插入注释有哪两种方法? 整数常数的尺寸如何指定?缺省的尺寸及数基是多少? 设置的编译指导如何解除? 编译指导影响全局吗? 在仿真时为什么要用接近实际的最大timescale精度? 是的。空白符用于隔开标识符及关键词,多余的忽略 //用于单行注释,/* */用于多行注释 整数常量的尺寸由10进制数表示的位数确定。缺省为32位,缺省的数基为十进制。 使用`resetall解除 编译指导是全局的。编译时遇到编译指导后开始有效,直至复位或被覆盖,可能影响多个文件。 使用尽可能大的精度。精度越小,仿真时间步越小,仿真时间越长。使用适当的精度,既达到必要的精度,又不会仿真太慢。