下载 第12章建模实例 本章给出了一些用 Verilog hdl编写的硬件建模实例。 121简单元件建模 连线是一种最基本的硬件单元。连线在 Verilog HDl中可被建模为线网数据类型。考虑4 位与门,其行为描述如下 module And4 (A, B, C)i input [3:0]B, output [3: 0A sign #5 A=B& Ci endmodule &(与)逻辑的时延定义为5ns。这个模型代表的硬件如图12-1所示。 C3]B[2]c[2]B1 门时延为5ns [1] A[O] 图 个4位与门 本实例和下面的实例表明布尔等式如何在连续赋值语句中被建模为表达式。连线单元能 被建模为线网数据类型。例如,在下面的描述中,F表示将~(非)操作符的输出连接到^(异或) 操作符输入的线网。该模块表示的电路如图12-2所示。 module Boolean Ex (D, G, E, utput D; wire F 图12-2组合电路 assign F= -Ei assign D= FG 考虑下列行为和如图12-3所示相应硬件的表示 module Asynchronous assign C=A/D >a。 =~(B4C); 图12-3异步反馈环路
下载 第12章 建 模 实 例 本章给出了一些用Verilog HDL编写的硬件建模实例。 12.1 简单元件建模 连线是一种最基本的硬件单元。连线在 Verilog HDL中可被建模为线网数据类型。考虑 4 位与门,其行为描述如下: ` t i m e s c a l e 1 n s / 1 n s m o d u l e And4 (A, B, C) ; i n p u t [3:0] B, C; o u t p u t [3:0] A; assign #5 A = B & C; e n d m o d u l e & (与)逻辑的时延定义为5 ns。这个模型代表的硬件如图 1 2 - 1所示。 图12-1 一个4位与门 本实例和下面的实例表明布尔等式如何在连续赋值语句中被建模为表达式。连线单元能 被建模为线网数据类型。例如,在下面的描述中, F表示将~ (非)操作符的输出连接到^ (异或) 操作符输入的线网。该模块表示的电路如图 1 2 - 2所示。 m o d u l e B o o l e a n _ E x (D, G, E, ) ; i n p u t G, E; o u t p u t D; w i r e F; assign F = ~E; a s s i g n D = F ^ G ; e n d m o d u l e 考虑下列行为和如图1 2 - 3所示相应硬件的表示。 m o d u l e A s y n c h r o n o u s; w i r e A, B, C, D; a s s i g n C = A|D a s s i g n A = ~ (B & C) ; e n d m o d u l e 门时延为5 ns 图12-2 组合电路 图12-3 异步反馈环路
Chinaopub.com 第2章建实例137 载 该电路带有一个异步反馈环路。如果模型用特定的值集(B=1,D=0)仿真,仿真时间将由于 仿真器总在两个赋值语句间迭代而永远停滞不前。迭代时间是两个零时延。因此,在使用带 有零时延的连续赋值语句对线网赋值,以及在表达式中使用相同的线网值时,必须格外小心 在特定的情况下,有时需要使用这样的异步反馈。下面将演示一个这样的异步反馈:语 句代表一个周期为20ns的周期性波形。其硬件表示如图12-4所示。注意这样的 always语句需 要一个 initial语句将寄存器初始化为0或1,否则寄存器的值将固定在值x上 reg Ace; ⊥n⊥tia1 Ace= 0 12-4时钟发生器 #10 Ace =4 Ace 向量线网或向量寄存器型元件能被访问,既可以访问称为位选择的单个元素,也可以访 问称为部分选择的片段。例如, reg A reg [0: 4] C: reg [5:0B, D D[4:0]=B[5:1]|c;∥/D[4:0]和B[5:1]都是部分选择 D[5]=AB[5];//D[5]和B[5]都是位选择。 第一个过程性赋值语句暗示着 D[4]=B[5]|c[0]; D[3]=B[4]|c[1]; 选择、部分选择和向量可以并置,形成更大的向量。如 wire [7: 0] C, CC wire cx assign C=CX, CC [6: 01 也可以引用索引值在运行时才可计算的向量元素。如 Adf Pib [K] 意味着解码器的输出为Adf,并且K指定选择地址。Pb是向量;本语句对解码器的行为建 模 可以使用预定义的移位操作符执行移位操作。移位操作可以用合并操作符建模。例如, wire [0: 7] A, Zi assign Z=(A [I: 7],A[0] 循环左移 assign z [7],A[0:6]}; /环右移。 assign Z=[A [1:7],1'b0)i 左移操作 向量的子域称为部分选择,也能够在表达式中使用。例如,32位指令寄存器 Instr Reg中 前16位表示地址,接下来8位表示操作码,余下的8位表示索引。给出如下说明:
该电路带有一个异步反馈环路。如果模型用特定的值集 (B=1, D= 0 )仿真,仿真时间将由于 仿真器总在两个赋值语句间迭代而永远停滞不前。迭代时间是两个零时延。因此,在使用带 有零时延的连续赋值语句对线网赋值,以及在表达式中使用相同的线网值时,必须格外小心。 在特定的情况下,有时需要使用这样的异步反馈。下面将演示一个这样的异步反馈;语 句代表一个周期为20 ns的周期性波形。其硬件表示如图 1 2 - 4所示。注意这样的always 语句需 要一个initial 语句将寄存器初始化为0或1,否则寄存器的值将固定在值 x上。 r e g A c e; i n i t i a l Ace = 0; a l w a y s #10 Ace = ~ Ace; 向量线网或向量寄存器型元件能被访问,既可以访问称为位选择的单个元素,也可以访 问称为部分选择的片段。例如, r e g A; r e g [0:4] C; r e g [ 5 : 0 ] B, D; always b e g i n . . . D [4:0] = B [5:1] | C; //D [ 4 : 0 ]和B[ 5 : 1 ]都是部分选择。 D [5] = A & B [5]; //D [ 5 ]和B[ 5 ]都是位选择。 e n d 第一个过程性赋值语句暗示着: D [4] = B [5] | C [0]; D [3] = B [4] | C [ 1 ] ; . . . 位选择、部分选择和向量可以并置,形成更大的向量。如, wire [7:0] C, CC; wire C X; . . . a s s i g n C = {CX, CC [ 6 : 0 ] } ; 也可以引用索引值在运行时才可计算的向量元素。如 : Adf = Plb [ K ] ; 意味着解码器的输出为 A d f,并且K指定选择地址。P l b是向量;本语句对解码器的行为建 模。 可以使用预定义的移位操作符执行移位操作。移位操作可以用合并操作符建模。例如, wire [0:7] A, Z; . . . a s s i g n Z = {A [1:7], A [0]}; //循环左移。 a s s i g n Z = {A [7], A [0:6]}; //循环右移。 a s s i g n Z = {A [1:7], 1'b0}; //左移操作。 向量的子域称为部分选择,也能够在表达式中使用。例如, 3 2位指令寄存器I n s t r _ R e g中 前1 6位表示地址,接下来8位表示操作码,余下的8位表示索引。给出如下说明: 第12章 建 模 实 例 137 下载 图12-4 时钟发生器
138 erilog hdl硬件描述语言 Chinapub coM 下载 reg [31: 0] Memory [0: 1023 wire [15: 0] Address wire[7: 0] op code, Index wire [0: 9] Prog ctr; wire Read ctl 从 Instr Reg读取子域信息的一种方法是使用三个连续赋值语句。指令寄存器的部份选择 被赋值给指定的线网。 assign INstr Reg Memoruprog ctr assign Address Instr Rebl: 16] assign op Code Instr Reg: 8 assign Index Instr Reg: 0] @(posedge Read ctI ask Ca11( Address, Op code 可用连续赋值语句为三态门的行为建模 wire Triout Enable TriIN 1bz 当 Enable为1时, TriO获得Tiln的值。当 Enable为0时, TroUt为高阻值 122建模的不同方式 本节给出了Ⅴ erilog HDL语言提供的三种不同ckB 建模方式的实例:数据流方式、行为方式和结构方A 式。参看图12-5所示的电路,该电路将输入A的值 8寄存器 存入寄存器,然后与输入C相乘 第一种建模方式是数据流方式,它使用连续赋 图12-5带缓冲的乘法器 值语句对电路建模 module Save Mult Df(A, C, ClkB, Z) [0:7]A input ClkB w⊥reS1 assign 2=s1*C assign S1=CIkB A S: 这种表示方法不直接蕴含任何结构,却隐式地描述了结构。但是,它的功能性非常清晰 寄存器已使用时钟控制方式建模。 第二种描述电路的方法是使用带有顺序程序块的 always语句,将电路建模为顺序程序描 module Save Mult seq (A, C, ClkB, 2)i input [0: 7]A; out [o input ClkB
r e g [31:0] Memory [0: 1023 ]; w i r e [31:0] I n s t r _ R e g ; w i r e [15:0] A d d r e s s ; w i r e [7:0] Op_Code, Index; w i r e [ 0 : 9 ] P r o g _ C t r ; w i r e R e a d _ C t l; 从I n s t r _ R e g读取子域信息的一种方法是使用三个连续赋值语句。指令寄存器的部份选择 被赋值给指定的线网。 a s s i g n INstr_Reg = Memory[P r o g _ C t r] ; a s s i g n Address = Instr_Reg[ 3 1 : 1 6 ] ; a s s i g n Op_Code = Instr_Reg[ 1 5 : 8 ] ; a s s i g n Index = Instr_Reg[ 7 : 0 ] ; . . . a l w a y s @ (p o s e d g e R e a d _ C t l) Task_Call ( Address, Op_Code, Index) ; 可用连续赋值语句为三态门的行为建模,如: w i r e Triout = Enable ? TriIN :1 ' b z ; 当E n a b l e为1时,Tr i O u t获得Tr i I n的值。当E n a b l e为0时,Tr i O u t为高阻值。 12.2 建模的不同方式 本节给出了 Verilog HDL语言提供的三种不同 建模方式的实例:数据流方式、行为方式和结构方 式。参看图 1 2 - 5所示的电路,该电路将输入 A的值 存入寄存器,然后与输入C相乘。 第一种建模方式是数据流方式,它使用连续赋 值语句对电路建模。 m o d u l e Save_Mult_Df (A , C , C l k B , Z) ; i n p u t [0:7] A; i n p u t [0:3] C; i n p u t C l k B; o u t p u t [ 0 : 1 1 ] Z; w i r e S 1; a s s i g n Z = S1 * C; assign S1 = ClkB ? A : S1; e n d m o d u l e 这种表示方法不直接蕴含任何结构,却隐式地描述了结构。但是,它的功能性非常清晰。 寄存器已使用时钟控制方式建模。 第二种描述电路的方法是使用带有顺序程序块的 always 语句,将电路建模为顺序程序描 述。 m o d u l e S a v e _ M u l t _ S e q (A , C , C l k B , Z); i n p u t [0:7] A ; i n p u t [0:3] C ; i n p u t C l k B; 138 Verilog HDL 硬件描述语言 下载 图12-5 带缓冲的乘法器 寄存器
第2章建实例139 下载 reg[0:11]z always e(Aorc。rc1kB) egin: SEQ //由于标记了程序块,可以说明一个局部寄存器变量s1 reg[0:7]S1; i£f(c1kB) Z=S1*G 这种模型也描述了电路的行为,但是没有蕴含任何结构,无论是隐式还是显示的。在这 种方式中,寄存器用谚语句建模。 第三种描述Save_Mal电路的方法是假定已存在8位寄存器和8位乘法器,将电路建模为线 网表 module Save MuIt Netlist (A, C, ClkB, 2) input [0: 7]A input [0:3]C, input ClkB; output [0: 11]2 w⊥re[0:7]S1,S3; Wire[0:15]S2; Reg8 R1(. Din(A), Clk(CIkB), Dout(s1))i Mu1t8M1(.A(s1),B(4′1b0000,c),z(z)); 种描述方式显式地描述了电路结构,但其行为是未知的。这是因为Reg8和Ml8的模块 名是任意的,并且它们可以有与其相关的各种行为。 12.3时延建模 考虑3输入或非门。它的行为可以使用连续赋值语句建模,如 assign #12 Gate out=+(A I B I C)i 这条语句对带有12个时间单位时延的或非门建模。这一时延表示从信号A、B或C上事件发 生到结果值出现在信号 Gate Out上的时间。一个事件可以是任何值的变化,如x→>z、x->0, 或者1->0 如果要显式地对上升和下降时间建模,则在连续赋值语句中使用两个时延,例如: assign #(12,14) Zoom =N(A I B I C)i /*12是上升时延,14是下降时延,min(12,14)=1是转换到x的时延+/ 在能够对高阻值Z赋值的逻辑中,也能够定义第三种时延,即关断时延。例如 assign #(12,14,10)Zoom =A>B? C: 1bz //上升时延为12,14是下降时延,min(12,14,10)=1是转换到x的时延,关断时延为10 每个时延值都能够用min:pp:max表示,例如
o u t p u t [ 0 : 1 1 ] Z; r e g [0:11] Z; a l w a y s @(A o r C o r C l k B) b e g i n: SEQ / /由于标记了程序块,可以说明一个局部寄存器变量 S 1。 r e g [0:7] S 1; i f (C l k B) S1 = A; Z = S1 * C; e n d e n d m o d u l e 这种模型也描述了电路的行为,但是没有蕴含任何结构,无论是隐式还是显示的。在这 种方式中,寄存器用i f语句建模。 第三种描述S a v e _ M u l t电路的方法是假定已存在 8位寄存器和8位乘法器,将电路建模为线 网表。 m o d u l e S a v e _ M u l t _ N e t l i s t (A , C , C l k B , Z) i n p u t [0:7] A ; i n p u t [0:3] C ; i n p u t C l k B ; o u t p u t [0:11] Z; w i r e [0:7] S 1 , S 3; W i r e [0:15] S 2; R e g 8 R 1 (. D i n(A) , .C l k(C l k B) , .D o u t(S 1) ) ; M u l t 8 M 1 ( .A(S 1) , .B( { 4′1 b 0 0 0 0 ,C} ) , .Z(Z) ) ; e n d m o d u l e 这种描述方式显式地描述了电路结构,但其行为是未知的。这是因为 R e g 8和M u l t 8的模块 名是任意的,并且它们可以有与其相关的各种行为。 12.3 时延建模 考虑3输入或非门。它的行为可以使用连续赋值语句建模,如 a s s i g n #12 Gate_Out = ~(A | B | C) ; 这条语句对带有1 2个时间单位时延的或非门建模。这一时延表示从信号 A、B或C上事件发 生到结果值出现在信号G a t e _ O u t上的时间。一个事件可以是任何值的变化,如 x -> z、 x - > 0, 或者1- > 0。 如果要显式地对上升和下降时间建模,则在连续赋值语句中使用两个时延,例如: a s s i g n #(12,14) Zoom = ~(A | B | C) ; / * 1 2是上升时延,1 4是下降时延,min(12,14) = 12是转换到x的时延* / 在能够对高阻值Z赋值的逻辑中,也能够定义第三种时延,即关断时延。例如: a s s i g n #(12,14,10) Z o o m = A > B ? C : 1bz; / /上升时延为1 2,1 4是下降时延,m i n ( 1 2 , 1 4,10) = 12是转换到x的时延,关断时延为1 0。 每个时延值都能够用m i n : t y p : m a x表示,例如, 第12章 建 模 实 例 139 下载
140 Verilog hdl硬述语言 Cb'a°dow 下载 assign#(9:10:11,11:12:13,13:14:15o0m=A>B? 时延值通常可以是表达式 基本门和UDP中的时延可以通过在实例中指定时延值建模。下面是5输入基本与门 and #(2,3)Al(Ot, InI, In2, In3, In4, In5 已指定输出的上升时延为2个时间单位,下降时延为3个时间单位 模型中位于端口边界的时延可使用指定程序块来定义。如下面的半加器模块的例子 module Half Adder(A, B,s, Cl input A, B: output s,C; specify (A=>S)=(1.2,0.8); (A=>C)=(1.2,1.0) endspecify assign S=A CB assign C=AIB 除在连续赋值语句中对时延建模外,时延还可以用指定程序块建模。是否存在一种从模 块外部指定时延的方法?一种选择是使用SDFθ(标准时延格式)和 Verilog仿真器可能提供的 反标机制。如果需要在 Verilog HDL模型中显式地指定这一信息,一种方法是在Half- Adder模 块上创建两个虚模块,每个模块带有不同的时延集 input A, Bi output s, Ci assign S=AB module Ha opt(A, B,s, C) output s,C. specify S)=(1.2,0 (B=>S)=(1.0,0.6); (A=>C)=(1.2,1.0) endspecify adde endmodule module Half Pess(A, B,s, Cl 6见参考文献
a s s i g n #(9:10:11,11:12:13,13:14:15) Z o o m = A > B ? C : 1bz; 时延值通常可以是表达式。 基本门和U D P中的时延可以通过在实例中指定时延值建模。下面是 5输入基本与门。 a n d #(2,3) A 1(O t , I n 1 , I n 2 , I n 3 , I n 4 , I n 5) ; 已指定输出的上升时延为2个时间单位,下降时延为3个时间单位。 模型中位于端口边界的时延可使用指定程序块来定义。如下面的半加器模块的例子。 m o d u l e H a l f _ A d d e r(A , B , S , C) ; i n p u t A , B; o u t p u t S , C; s p e c i f y (A => S) = (1.2,0.8); (B => S) = (1.0,0.6); (A => C) = (1.2,1.0); (B => C) = (1.2,0.6); e n d s p e c i f y a s s i g n S = A ^ B; a s s i g n C = A | B ; e n d m o d u l e 除在连续赋值语句中对时延建模外,时延还可以用指定程序块建模。是否存在一种从模 块外部指定时延的方法?一种选择是使用 S D F (标准时延格式)和 Ve r i l o g仿真器可能提供的 反标机制。如果需要在 Verilog HDL模型中显式地指定这一信息,一种方法是在 H a l f - A d d e r模 块上创建两个虚模块,每个模块带有不同的时延集。 m o d u l e H a l f _ A d d e r(A , B , S , C); i n p u t A , B ; o u t p u t S , C ; a s s i g n S = A ^ B; a s s i g n C = A | B; e n d m o d u l e module H a _ O p t(A , B , S , C); i n p u t A , B ; o u t p u t S , C ; s p e c i f y (A => S) = (1.2,0.8); (B => S) = (1.0,0.6); (A => C) = (1.2,1.0); (B => C) = (1.2,0.6); e n d s p e c i f y Half_Adder H1 (A , B , S , C) ; e n d m o d u l e m o d u l e H a l f _ P e s s(A , B , S , C) ; 140 Verilog HDL 硬件描述语言 下载 见参考文献