下载 第11章验证 本章介绍了如何编写测试验证程序( test bench)。测试验证程序用于测试和验证设计的正 确性。 Verilog hdl提供强有力的结构来说明测试验证程序, 11.1编写测试验证程序 测试验证程序有三个主要目的 1)产生模拟激励(波形)。 2)将输入激励加入到测试模块并收集其输出响应 3)将响应输出与期望值进行比较 Ⅴ erilog HDl提供了大量的方法以编写测试验证程序。在本章中,我们将对其中的某些方 法进行探讨。典型的测试验证程序形式如下: 通常测试验证程序没有输入和输出端I cal reg and net declarations Generate waveforms using initial always statements Instantiate module under test Moni tor output and compare with expected values endmodule 测试中,通过在测试验证程序中进行实例化,激励自动加载于测试模块。 112波形产生 有两种产生激励值的主要方法: 1)产生波形,并在确定的离散时间间隔加载激励。 2)根据模块状态产生激励,即根据模块的输出响应产生激励。 通常需要两类波形。一类是具有重复模式的波形,例如时钟波形,另一类是一组指定的 值确定的波形。 11.21值序列 产生值序列的最佳方法是使用 initial语句。例如 in⊥t⊥a1 Reset= #100 Reset=1 #80 Reset =0 #30 Reset 产生的波形如图11-1所示。 Initial语句中的赋值语句用时延控制产生波形。此外,语句内 时延也能够按如下实例所示产生波形
下载 第11章 验 证 本章介绍了如何编写测试验证程序 (test bench)。测试验证程序用于测试和验证设计的正 确性。Verilog HDL提供强有力的结构来说明测试验证程序。 11.1 编写测试验证程序 测试验证程序有三个主要目的: 1) 产生模拟激励(波形)。 2) 将输入激励加入到测试模块并收集其输出响应; 3) 将响应输出与期望值进行比较。 Verilog HDL提供了大量的方法以编写测试验证程序。在本章中,我们将对其中的某些方 法进行探讨。典型的测试验证程序形式如下: module T e s t _ B e n c h; / /通常测试验证程序没有输入和输出端口。 L o c a l _ r e g _ a n d _ n e t _ d e c l a r a t i o n s G e n e r a t e _ w a v e f o r m s _ u s i n g _ i n i t i a l _ & _ a l w a y s _ s t a t e m e n t s I n s t a n t i a t e _ m o d u l e _ u n d e r _ t e s t M o n i t o r _ o u t p u t _ a n d _ c o m p a r e _ w i t h _ e x p e c t e d _ v a l u e s e n d m o d u l e 测试中,通过在测试验证程序中进行实例化,激励自动加载于测试模块。 11.2 波形产生 有两种产生激励值的主要方法: 1) 产生波形,并在确定的离散时间间隔加载激励。 2) 根据模块状态产生激励,即根据模块的输出响应产生激励。 通常需要两类波形。一类是具有重复模式的波形,例如时钟波形,另一类是一组指定的 值确定的波形。 11.2.1 值序列 产生值序列的最佳方法是使用 i n i t i a l语句。例如: i n i t i a l b e g i n R e s e t = 0; #100 R e s e t = 1; #80 Reset = 0; #30 Reset = 1; e n d 产生的波形如图11 - 1所示。I n i t i a l语句中的赋值语句用时延控制产生波形。此外,语句内 时延也能够按如下实例所示产生波形
第章验证 119 下载 ⊥n⊥tia1 beG⊥n Reset =0 Reset =#800; Reset =#30 1 end Reset 图11-1使用 initial语句产生的波形 因为使用的是阻塞性过程赋值,上面语句中的时延是相对时延。如果使用绝对时延,可 用带有语句内时延的非阻塞性过程性赋值,例如, initial begin Reset Reset < #100 1 Reset <=#1800 Reset<=#2101; 这三个 initial语句产生的波形与图11-1中所示的波形一致。 为重复产生一个值序列,可以使用 always语句替代 initial语句,这是因为 initial语句只执行 次而 al ways语句会重复执行。下例的 always语句所产生的波形如图12所示。 parameter REPEAT DELAY= 35 integer Coinvalue always begin co⊥ n value=0 #7 Coinvalue 25 #2 Coinvalue=5 #8 Coinvalue= 10 #6. Coinvalue =5 排 REPEAT DELAY Coin value o251050510 个周期 图12使用 always语句产生的重复序列 1122重复模式 重复模式的生成通过使用如下形式的连续赋值形式加以简化
i n i t i a l b e g i n R e s e t = 0; R e s e t = #100 1; R e s e t = #80 0; R e s e t = #30 1; e n d 图11-1 使用initial语句产生的波形 因为使用的是阻塞性过程赋值,上面语句中的时延是相对时延。如果使用绝对时延,可 用带有语句内时延的非阻塞性过程性赋值,例如, i n i t i a l b e g i n R e s e t <= 0; R e s e t <= #100 1; R e s e t <= #180 0; R e s e t <= #210 1; e n d 这三个i n i t i a l语句产生的波形与图11 - 1中所示的波形一致。 为重复产生一个值序列,可以使用 a l w a y s语句替代i n i t i a l语句,这是因为i n i t i a l语句只执行 一次而a l w a y s语句会重复执行。下例的a l w a y s语句所产生的波形如图11 - 2所示。 p a r a m e t e r REPEAT_DELAY = 35; i n t e g e r C o i n V a l u e ; a l w a y s b e g i n CoinValue = 0; #7 C o i n V a l u e = 25; #2 C o i n V a l u e = 5; #8 C o i n V a l u e = 10; #6 C o i n V a l u e = 5; #R E P E A T _ D E L A Y; e n d 图11-2 使用always语句产生的重复序列 11.2.2 重复模式 重复模式的生成通过使用如下形式的连续赋值形式加以简化: 第11章 验 证 119 下载 一个周期
120 Verilog hdl硬件描述语言 下载 assign #(PERIOD/2) clock = clock; 但是这种做法并不完全正确。问题在于 Clock是一个线网(只有线网能够在连续赋值中被赋 值),它的初始值是z,并且,z等于x,~x等于x。因此Cock的值永远固定为值x。 现在需要一种初始化 Clock的方法。可以用 initial语句实现。 in⊥七ia1 但是现在 Clock必须是寄存器数据类型(因为只有寄存器数据类型能够在 initial语句中被赋 值),因此连续赋值语句需要被变换为 always语句。下面是一个完整的时钟产生器模块。 module Gen Clk A(Clk A output CIk A: reg clk parameter tPERIOD= 1( ⊥n主七ia1 ClK A=0 always #(tPERIOD/2) clk A=-Clk A 图11-3显示了该模块产生的时钟波形 Clk_A 」「1「L「L 20 30 图11-3周期性的时钟波形 下面给出了产生周期性时钟波形的另一种可选方式。 module Gen Clk B(Clk B) output Clk B start =1 end nor #2(Clk B, Start Clk B)i endmodul //产生一个高、低电平宽度均为2的时钟 initial语句将Sant置为1,这促使或非门的输出为0(从x值中获得)。5个时间单位后,在 iar变为0时,或非门反转产生带有周期为4个时间单位的时钟波形。产生的波形如图11-4所 如果要产生高低电平持续时间不同的时钟波形,可用 always语句建立模型,如下所示 module Gen Clk C(clk C) parameter toN 5, tOFF =10 output Clk C
a s s i g n # (P E R I O D/2) Clock = ~ C l o c k; 但是这种做法并不完全正确。问题在于 C l o c k是一个线网(只有线网能够在连续赋值中被赋 值),它的初始值是z,并且,z等于x,~ x等于x。因此C l o c k的值永远固定为值x。 现在需要一种初始化C l o c k的方法。可以用i n i t i a l语句实现。 i n i t i a l C l o c k = 0; 但是现在C l o c k必须是寄存器数据类型 (因为只有寄存器数据类型能够在 i n i t i a l语句中被赋 值),因此连续赋值语句需要被变换为 a l w a y s语句。下面是一个完整的时钟产生器模块。 m o d u l e Gen_Clk_A (C l k _ A) ; o u t p u t C l k _ A; r e g C l k _ A ; p a r a m e t e r tPERIOD = 10; i n i t i a l C l k _ A = 0; always # (t P E R I O D/2) Clk_A = ~ C l k _ A; e n d m o d u l e 图11 - 3显示了该模块产生的时钟波形。 图11-3 周期性的时钟波形 下面给出了产生周期性时钟波形的另一种可选方式。 m o d u l e Gen_Clk_B (C l k _ B) ; o u t p u t C l k _ B; r e g S t a r t; i n i t i a l b e g i n S t a r t = 1; #5 S t a r t = 0; e n d n o r #2 (Clk_B, Start, C l k _ B) ; e n d m o d u l e / /产生一个高、低电平宽度均为2的时钟。 i n i t i a l语句将S t a rt置为1,这促使或非门的输出为 0 (从x值中获得)。5个时间单位后,在 S t a rt变为0时,或非门反转产生带有周期为 4个时间单位的时钟波形。产生的波形如图 11 - 4所 示。 如果要产生高低电平持续时间不同的时钟波形,可用 a l w a y s语句建立模型,如下所示: m o d u l e Gen_Clk_C (C l k _ C) ; p a r a m e t e r tON = 5, t O F F = 10; o u t p u t C l k _ C ; 120 Verilog HDL 硬件描述语言 下载
Chinaopub.com 第1验证121 下载 reg Clk c begin Cik C= 0 tOFF Clk C=1 endmodul Start 图11-4受控时钟 因为值0和1被显式地赋值,在这种情况下不必使用 initial语句。图11-5显示了这一模块生 成的波形。 为在初始时延后产生高低电平持续时间不同的时钟,可以在 initial语句中使用 forever循环 语句。 Clk C 「L 图11-5高低电平持续时间不同的时钟 module Gen Clk D (CIk D) output Clk D; parameter START DELAY 5, LOW TIME 2, HIGH TIME =3 ⊥n⊥tia1 begi Clk D =0: START DELAY forever begin 普 LOW TIME; Clk D= 1 HIGH TIME Clk D=0 上面模块所产生的波形如图11-6所示 为产生确定数目的时钟脉冲,可以使用 repeat循环语句。下面带参数的时钟模块产生一定 数目的时钟脉冲数列,时钟脉冲的高低电平持续时间也是用参数表示的
第11章 验 证 121 下载 r e g C l k _ C ; a l w a y s b e g i n # tON Clk_C = 0; # tOFF Clk_C = 1; e n d e n d m o d u l e 图11-4 受控时钟 因为值0和1被显式地赋值,在这种情况下不必使用 i n i t i a l语句。图11 - 5显示了这一模块生 成的波形。 为在初始时延后产生高低电平持续时间不同的时钟,可以在 i n i t i a l语句中使用f o r e v e r循环 语句。 图11-5 高低电平持续时间不同的时钟 m o d u l e Gen_Clk_D (Clk_D); o u t p u t C l k _ D ; r e g C l k _ D ; p a r a m e t e r START_DELAY = 5, LOW_TIME = 2, HIGH_TIME = 3; i n i t i a l b e g i n Clk_D = 0; # S T A R T _ D E L A Y ; f o r e v e r b e g i n # LOW_TIME ; Clk_D = 1; # H I G H _ T I M E; Clk_D = 0; e n d e n d e n d m o d u l e 上面模块所产生的波形如图 11 - 6所示。 为产生确定数目的时钟脉冲,可以使用 r e p e a t循环语句。下面带参数的时钟模块产生一定 数目的时钟脉冲数列,时钟脉冲的高低电平持续时间也是用参数表示的
122 Verilog hdl硬停横述语言 下载 CIK E parameter Tburst 10, Ton =2, Toff =5 initial begin CIK E=1'b0: repeat( Burst begin Toff Clk E=1b1 Ton Clk E= 1'b0 Clk D 202225 图11-6带有初始时延的时钟 模块 Gen Clk e在具体应用时,参数 Burst、Ton和To〃可带不同的值 module Test wire Clk Ea, Cik Eb, Cik Ec Gen Cik E GIClk Ea //产生10个时钟脉冲,高、低电平持续时间分别为2个和5个时间单位 Gen Cik E (5, 1,3) Clk Eb) /产生5个时钟脉冲,高、低电平持续时间分别为1个和3个时间单位。 Gen Clk E #(25,8, 10) Ik Ec)i //产生25个时钟脉冲,高、低电平持续时间分别为8个和10个时间单位 Clk eb的波形如图11-7所示 Clk eb 3478111215161920 图11-7确定数目的时钟脉冲 可用连续赋值产生一个时钟的相移时钟。下述模块产生的两个时钟波形如图11-8所示。 个时钟是另一个时钟的相移时钟 module Phase (Master Clk, Slave C2l output Master Clk, Slave Clki
m o d u l e Gen_Clk_E (C l k _ E) ; o u t p u t C l k _ E ; r e g C l k _ E ; p a r a m e t e r Tburst = 10, Ton = 2, Toff = 5; i n i t i a l b e g i n C l k _ E = 1'b0; r e p e a t(T b u r s t) b e g i n # Toff Clk_E = 1'b1; # Ton Clk_E = 1'b0; e n d e n d e n d m o d u l e 图11-6 带有初始时延的时钟 模块G e n _ C l k _ E在具体应用时,参数T b u r s t、To n和To f f可带不同的值。 m o d u l e T e s t; w i r e Clk_Ea, Clk_Eb, Clk_Ec; Gen_Clk_E G1(C l k _ E a) ; / /产生1 0个时钟脉冲,高、低电平持续时间分别为2个和5个时间单位。 Gen_Clk_E # (5, 1, 3) (C l k _ E b) ; / /产生5个时钟脉冲,高、低电平持续时间分别为1个和3个时间单位。 Gen_Clk_E # (25, 8, 10) (C l k _ E c) ; / /产生2 5个时钟脉冲,高、低电平持续时间分别为8个和1 0个时间单位。 e n d m o d u l e C l k _ E b的波形如图11 - 7所示。 图11-7 确定数目的时钟脉冲 可用连续赋值产生一个时钟的相移时钟。下述模块产生的两个时钟波形如图 11 - 8所示。 一个时钟是另一个时钟的相移时钟。 m o d u l e Phase (Master_Clk, Slave_Clk) ; o u t p u t Master_Clk, Slave_Clk; reg Master_Clk; 122 Verilog HDL 硬件描述语言 下载