微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 硬件工程师文库 > Verilog HDL简明教程(2)

Verilog HDL简明教程(2)

时间:02-11 来源:网络整理 点击:

混合设计描述方式

在模块中,结构的和行为的结构可以自由混合。也就是说,模块描述中可以包含实例化的门、模块实例化语句、连续赋值语句以及always语句和initial语句的混合。它们之间可以相互包含。来自always语句和initial语句(切记只有寄存器类型数据可以在这两种语句中赋值)的值能够驱动门或开关,而来自于门或连续赋值语句(只能驱动线网)的值能够反过来用于触发always语句和initial语句。
下面是混合设计方式的1位全加器实例。
module FA_Mix (A, B, Cin, Sum, Cout);
input A,B, Cin;
output Sum, Cout;
reg Cout;
reg T1, T2, T3;
wire S1;
xor X1(S1, A, B); // 门实例语句。
always
@ ( A or B or Cin ) begin // always 语句。
T1 = A & Cin;
T2 = B & Cin;
T3 = A & B;
Cout = (T1| T2) | T3;
end
assign Sum = S1 ^ Cin; // 连续赋值语句。
endmodule
只要A或B上有事件发生,门实例语句即被执行。只要A、B或Cin上有事件发生,就执行always 语句,并且只要S1或Cin上有事件发生,就执行连续赋值语句。

设计模拟

Verilog HDL不仅提供描述设计的能力,而且提供对激励、控制、存储响应和设计验证的建模能力。激励和控制可用初始化语句产生。验证运行过程中的响应可以作为"变化时保存"或作为选通的数据存储。最后,设计验证可以通过在初始化语句中写入相应的语句自动与期望的响应值比较完成。
下面是测试模块Top的例子。该例子测试2.3节中讲到的FA_Seq模块。
‘timescale 1ns/1ns
module Top; // 一个模块可以有一个空的端口列表。
reg PA, PB, PCi;
wire PCo, PSum;
// 正在测试的实例化模块:
FA_Seq F1(PA, PB, PCi, PSum, PCo); // 定位。
initial
begin: ONLY_ONCE
reg [3:0] Pal;
//需要4位, Pal才能取值8。
for (Pal = 0; Pal < 8; Pal = Pal + 1)
begin
{PA, PB, PCi} = Pal;
#5 $display ("PA, PB, PCi = %b%b%b", PA, PB, PCi,
" : : : PCo, PSum=%b%b", PCo, PSum);
end
end
endmodule
在测试模块描述中使用位置关联方式将模块实例语句中的信号与模块中的端口相连接。也就是说,PA连接到模块FA_Seq的端口A,PB连接到模块FA_Seq的端口B,依此类推。注意初始化语句中使用了一个for循环语句,在PA、PB和PCi上产生波形。for 循环中的第一条赋值语句用于表示合并的目标。自右向左,右端各相应的位赋给左端的参数。初始化语句还包含有一个预先定义好的系统任务。系统任务$display将输入以特定的格式打印输出。
系统任务$display调用中的时延控制规定$display任务在5个时间单位后执行。这5个时间单位基本上代表了逻辑处理时间。即是输入向量的加载至观察到模块在测试条件下输出之间的延迟时间。
这一模型中还有另外一个细微差别。Pal在初始化语句内被局部定义。为完成这一功能,初始化语句中的顺序过程(begin-end)必须标记。在这种情况下, ONLY_ONCE是顺序过程标记。如果在顺序过程内没有局部声明的变量,就不需要该标记。下面是测试模块产生的输出。
PA, PB, PCi = 000 ::: PCo, PSum = 00
PA, PB, PCi = 001 ::: PCo, PSum = 01
PA, PB, PCi = 010 ::: PCo, PSum = 01
PA, PB, PCi = 011 ::: PCo, PSum = 10
PA, PB, PCi = 100 ::: PCo, PSum = 01
PA, PB, PCi = 101 ::: PCo, PSum = 10
PA, PB, PCi = 110 ::: PCo, PSum = 10
PA, PB, PCi = 111 ::: PCo, PSum = 11
验证与非门交叉连接构成的RS_FF模块的测试模块如下例所示。
`timescale 10ns/1ns
module RS_FF (Q, Qbar, R, S);
output Q, Qbar;
input R, S;
nand #1 (Q, R, Qbar);
nand #1 (Qbar, S, Q,);
//在门实例语句中,实例名称是可选的。
endmodule
module Test;
reg TS, TR;
wire TQ, TQb;
//测试模块的实例语句:
RS_FF NSTA (.Q(TQ), .S(TS), .R(TR), .Qbar(TQb));
//采用端口名相关联的连接方式。
// 加载激励:
initial
begin:
TR = 0;
TS = 0;
#5 TS = 1;
#5 TS = 0;
TR = 1;
#5 TS = 1;
TR = 0;
#5 TS = 0;
#5 TR = 1;
end
//输出显示:
initial
$monitor ("At time %t ," , $time,
"TR = %b, TS=%b, TQ=%b, TQb= %b", TR, TS, TQ, TQb);
endmodule
RS_FF模块描述了设计的结构。在门实例语句中使用门时延;例如,第一个实例语句中的门时延为1个时间单位。该门时延意味着如果R或Qbar假定在T时刻变化,Q将在T+1时刻获得计算结果值。
模块Test是一个测试模块。测试模块中的RS_FF用实例语句说明其端口用端口名关联方式连接。在这一模块中有两条初始化语句。第一个初始化语句只简单地产生TS和TR上的波形。这一初始化语句包含带有语句间时延的程序块过程赋值语句。
第二条初始化语句调用系统任务$monitor。这一系统任务调用的功能是只要参数表中指定的变量值发生变化就打印指定的字符串。下面是测试模块产生的输出。请注意`timescale指令在时延上的影响。
At time 0, TR=0, TS=0, TQ=x, TQb= x
At time 10, TR=0, TS=0, TQ=1, TQb= 1
At time 50, TR=0, TS=1, TQ=1, TQb= 1
At time 60, TR=0, TS=1, TQ=1, TQb= 0
At time 100, TR=1, TS=0, TQ=1, TQb= 0
At time 110, TR=1, TS=0, TQ=1, TQb= 1
At time 120, TR=1, TS=0, TQ=0, TQb= 1
At time 150, TR=0, TS=1, TQ=0, TQb= 1
At time 160, TR=0, TS=1, TQ=1, TQb= 1
At time 170, TR=0, TS=1, TQ=1, TQb= 0
At time 200, TR=0, TS=0, TQ=1, TQb= 0
At time 210, TR=0, TS=0, TQ=1, TQb= 1
At time 250, TR=1, TS=0, TQ=1, TQb= 1
At time 260, TR=1, TS=0, TQ=0, TQb= 1
 

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top