Verilog 模型可以是实际电路中不同级别的抽象。所谓不同的抽象级别,实际上是指同一个物理电路,可以在不同的层次上用Verilog语言来描述它。如果只从行为和功能的角度描述某一个电路模块,就称为行为模块 ;如果从电路结构的角度来描述该电路模块,就称为结构模块。抽象的界别和它们对应模型常可以分为以下5种,即Verilog语法支持数字电路系统5种不同描述方法:
(1) 系统级(system)
(2) 算法级(algorithmic)
(3) RTL级(RegisterTransferLevel):
(4) 门级(gate-level):
(5) 开关级(switch-level)
系统级、算法级和RTL级是属于行为级的,门级是属于结构级的。熟练使用掌握门级、RTL级、算法级、系统级是非常重要的。对于电路基本部件库的设计者而言,则需要掌握用户自定义源语文件(UDP)和开关级的描述。
一个逻辑电路是由许多逻辑门和开关所组成,因此用基本逻辑门的模型来描述逻辑电路结构是最直观的。用一些描述门类型的关键字,可以用于门级结构建模。
下面列出了八个基本的门类型(GATETYPE)关键字和它们所表示的门的类型:
and 与门
nand 与非门
nor 或非门
or 或门
xor 异或门
xnor 异或非门
buf 缓冲器
not 非门
门与开关的说明语法可以用标准的声明语句格式和一个简单的实例引用加以说明。门声明语句的格式
如下:
<门的类型>[<驱动能力><延时>]<门实例1>[,<门实例2>,…<门实例n>];
门的类型是门声明语句所必需的,它可以是Verilog HDL语法规定的26种门类型中的任意一种。驱动能力和延时是可选项,可根据不同的情况选不同的值或不选。
最后我们用一个具体的例子来说明门类型的引用:
nand #10 nd1(a,data,clock,clear);
这说明在模块中引用了一个名为nd1的与非门(nand),输入为data、clock和clear,输出为a,输出与输入的延时为10个单位时间。
下面的例子是用Verilog HDL语言描述的D型主从触发器模块。
module flop(data,clock,clear,q,qb);
input data,clock,clear;
output q,qb;
nand #10 nd1(a,data,clock,clear),
nd2(b,ndata,clock),
nd4(d,c,b,clear),
nd5(e,c,nclock),
nd6(f,d,nclock),
nd8(qb,q,f,clear); //调用nand 声明6个延时10个单位的与非门(1、2、4、5、、6、8)
nand #9 nd3(c,a,d),
nd7(q,e,qb); //调用 nand 声明2个延时9个单位的与非门(3、7)
not #10 iv1(ndata,data),
iv2(nclock,clock); //调用not声明2个延时10个单位的非门(1、2)
endmodule
如果已经编制了一个模块,如4.1.2.中的flop,我们可以在另外的模块中引用这个模块,引用的方法与门类型的实例引用非常类似。只需在前面写上已编的模块名,紧跟着写上引用的实例名,按顺序写上实例的端口名即可。见下面的两个例子:
module flop(data,clock,clear,q,qb);
(1) flop f1op_d( d1, clk, clrb, q, qn);
(2) flop flop_d (.clock(clk),.q(q),.clear(clrb),.qb(qn),.data(d1));
模块的端口名可以按序排列也可以不必按序排列,如果模块的端口名按序排列,只需按序列出实例的端口名。(见例1)。如果模块的端口名不按序排列,则实例的端口信号和被引用模块的端口信号必需一一列出(见例2)。
flop f1(d[0],clk,clrb,q[0],)
通过Verilog HDL模块的调用,可以构成任何复杂结构的电路。这种以结构方式所建立的硬件模型不仅是可以仿真的,也是可综合的,这就是以门级为基础的结构描述建模的基本思路。
请注意f1实例引用已编模块flop时,由于不需要flop端口中的qb口,故在引用时把它省去,但逗号仍需要留着。
用户定义的原语是从英语User Defined Primitives直接翻译过来的,利用UDP用户可以定义自己设计的基本逻辑元件的功能,也就是说,可以利用UDP来定义有自己特色的用于仿真的基本逻辑元件模块并建立相应的原语库。这样,我们就可以与调用Verilog HDL基本逻辑元件同样的方法来调用原语库中相应的元件模块来进行仿真。
UDP是用查表的方法来确定其输出的,用仿真器进行仿真时,对它的处理速度较对一般用户编写的模块快得多。
定义UDP的语法:
primitive 元件名(输出端口名,输入端口名1,输入端口名2,…)
output 输出端口名;
input 输入端口名1, 输入端口名2,…;
reg 输出端口名;
initial begin
输出端口寄存器或时序逻辑内部寄存器赋初值(0,1,或 X);
end
table
//输入1 输入2 输入3 … : 输出
逻辑值 逻辑值 逻辑值 … : 逻辑值 ;
逻辑值 逻辑值 逻辑值 … : 逻辑值 ;
逻辑值 逻辑值 逻辑值 … : 逻辑值 ;
… … … … : … ;
endtable
endprimitive
注意点:
(1) UDP只能有一个输出端,而且必定是端口说明列表的第一项。
(2)UDP可以有多个输入端,最多允许有10个输入端。
(3) UDP所有端口变量必须是标量,也就是必须是1位的。
(4) 在UDP的真值表项中,只允许出现0、1、X三种逻辑值,高阻值状态Z是不允许出现的。
(5) 只有输出端才可以被定义为寄存器类型变量。
(6) initial语句用于为时序电路内部寄存器赋初值,只允许赋0、1、X三种逻辑值,缺省值为X。
用行为描述的方法来描述带清零端的4位寄存器
module hardreg(d,clk,clrb,q)
input clk,clrb;
input[3:0] d;
output[3:0] q;
reg[3:0] q;
always@(posedge clk or posedge clrb)
begin
if (clrb)
q<=0;
else
q<=d;
end
endmodule
四位寄存器结构图
异步电路电路图
异步电路主要是组合逻辑电路,用于产生地址译码器、FIFO或RAM的读写控制信号脉冲,但它同时也用在时序电路中,此时它没有统一的时钟,状态变化的时刻是不稳定的,通常输入信号只在电路处于稳定状态时才发生变化。也就是说一个时刻允许一个输入发生变化,以避免输入信号之间造成的竞争冒险。电路的稳定需要有可靠的建立时间和保持时间。