1.9.4 延迟定义块
Verilog HDL语言可以对模块中某一指定的路径进行延迟定义,这一路径连接模块的输入端口(或双向端口)与输出端口(或双向端口)。延迟定义块在一个独立的块结构中定义模块的时序部分,这样功能验证就可以与时序验证相独立。这是时序驱动设计的关键部分,因为包含时序信息的这部分程序在不同的抽象层次上可以保持不变。
在延迟定义块中要完成的典型任务有:
——描述模块中的不同路径并给这些路径赋值
——描述时序核对,以确认硬件设备的时序约束是否能得到满足
延迟定义块的内容要放在关键字specify和endspecify之间,而且必须在某一模块内部。在定义块中还可以使用specparam关键字定义参数。举例说明如下:
电路图如图4所示。
a b c o
图4:noror模块电路示意图
进行路径延迟定义如下:
module noror (o, a, b, c);
output o;
input a, b, c;
nor n1 (net1, a, b);
or o1 (o, c, net1);
specify
(a => o) = 2;
(b => o) = 3;
(c => o) = 1;
endspecify
endmodule
对于这一简单电路的延迟定义可以采用将所有的延迟集中在最后一个或门上定义的方法,简单但不精确;另一种方法就是如上述模块所做,把延迟分布在每个门上,即定义了从a点到o点的延迟为2,从b点到o点的延迟为3,从c点到o点延迟时间为1。这种做法比前者精确,但要同时满足一系列等式,工作量大。
第二节 Verilog-XL仿真
从
测试模块由以下几部分组成:
a. 数据类型的定义
b. 模块实例
c. 施加激励
d. 显示结果
上例的测试模块如下:
module testfixture;
reg a, b, sel; //定义数据类型
MUX2_1 mux(out, a, b, sel); //MUX实例
initial
begin
a = 0; b = 1; sel = 0;
#5 b = 0;
#5 b = 1; sel = 1;
#5 a = 1;
#5 $finish;
end //加激励
initial
$monitor($time, "out = %b a = %b b = %b sel = %b", out, a, b, sel); //显示结果
endmodule
编译指令
编译指令用重音符(`)表示,这些指令将引起使Verilog编译器产生特殊的动作。编译指令将一直保持有效,除非被其他编译指令所覆盖或失效。
1) 文本交换(`define)
功能:`define 指令提供了一个简洁的文本交换的功能。
指令格式:`define <name> <macro_text>
作用:增强描述的可读性。
定义全局参数,如延迟、位宽等,好处是当需要改变配置时,秩序对一处进行修改即可。
对Verilog的某些命令做缩记。
应用举例:
`define not_delay #1
`defineand_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
注:
l 可以将一列`define指令放到一个文件中,将这一文件与其它设计文件一起编译即可,例如:
verilog definitions.v mux.v
l +define+命令具有重新进行宏定义的功能,例:
verilog +define+gate=“or” test.v
module test;
`define gate and
reg a, b;
`gate (c, a, b);
initial
begin
a=0; b=1;
$monitor ($time, , c, a, b);
$finish;
end
endmodule
2) 文本包含(`include)
功能:`include编译指令用来插入一个完整文件的内容。
指令格式:`include "<file_name>"
作用:
可以把全局或经常使用的一些定义单独放到一个文件中,然后包含这个文件
可以包含一些task任务块,但这些任务块中不能有压缩的重复代码,这会使维护代码很困难。
例: `include "global.v"
`include "parts/count.v"
注: `include指令最多可以嵌套八层
3) 时间尺度(`timescale)
功能:`timescale编译指令用来定义时间单位和精度。
指令格式:`timescale <time_unit> / <time_precision>
time_unit延迟和时间的计量单位
time_precision时间精度,在仿真之前确定如何驱动时间
二者都是由整数和分别代表大小和单位的字符串组成,有效的整数是1,10和100,字符串可以是s,ms,ns,us,ps,fs
注:
l 如果时间单位和精度相差太大,仿真速度会大大降低,因为时间轮是由精度的倍数来驱动的。例:有一`timescale 1s / 1ps,时间轮要扫描10
l 所有时间尺度指令的最小精度作为整个仿真的时间单位,因为仿真器需要保证设计中定义的最小时间精度,并以它的倍数来推进时间轮。
例如:
`timescale 1ns/10ps
module1(···);
···
endmodule
`timescale 100ns/1ns
module2(···);
···
endmodule
`timescale 1ps/100fs
module3(···);
···
endmodule
仿真的时间单位是100fs,即时间轮总是以100fs为倍数向前推进。第一个时间尺度表明模块1以1ns为单位,精度是10ps,也就是设置了最小的仿真时间步长为10ps;第二个时间尺度表示模块2的时间单位是100ns,而它的精度为1ns,因为1ns大于10ps,故最小仿真补偿仍为10ps;第三个时间尺度表示模块3的时间单位是1ps,精度为100fs,由于100fs小于10ps,故最小仿真补偿变为100fs。

