三、6【Verilog HDL】基础知识之门级建模

参考书籍:Verilog HDL 数字设计与综合》第二版,本文档为第5章的学习笔记。由于本章也讲述的建模方式。该建模方式是通常设计师常用的底层抽象层次。更为低层的为开关级建模。

想了解更多低层建模方式之开关级建模:

三、5【Verilog HDL】基础知识之开关级建模_FPGA-桥的博客-CSDN博客参考书籍:《VerilogHDL 数字设计与综合》第二版,本文档为第五章的学习笔记。Verilog HDL中的门级原语、实例引用、符号、真值表如何根据电路的逻辑图生成Verilog描述学习门级设计中的上升、下降和关断延迟https://blog.csdn.net/ARM_qiao/article/details/124220910

关于门电路的数电基础知识介绍,请参考本人的相关《数字电子技术基础》的书籍阅读笔记,有助于大家对门级建模有深入的认识与学习

https://blog.csdn.net/arm_qiao/category_11744079.htmlicon-default.png?t=M3K6https://blog.csdn.net/arm_qiao/category_11744079.html

 学习目标 

  • 掌握Verilog提供的门级原语
  • 理解门的应用
  • 会根据门电路写Verilog描述
  • 清楚门级设计中的上升、下降和关断延迟
  • 门级设计中的最小、最大和典型延迟

5.1 门的类型

基本的逻辑门分为两类:1、与/或门类(and/or);2、缓冲器/非门类(buf/not)

5.1.1 与门(and)和或门(or)

相对应的关键字有

and   //与门           nand    //与非门
or    //或门           nor     //或非门
xor   //异或门         xnor    //同或门

门级原语实例化引用的时候,我们可以不指定具体实例的名字。

门级的实例引用:

wire OUT, IN1, IN2;

//基本门的实例引用
and   a1(OUT, IN1, IN2);
nand  na1(OUT, IN1, IN2);
or    or1(OUT, IN1, IN2);
nor   nor1(OUT, IN1, IN2);
xor   xor1(OUT, IN1, IN2);
xnor  xnor1(OUT, IN1, IN2);
//输入端超过两个;三输入的与非门
nand na1_3inp(OUT, IN1, IN2, IN3);

5.1.2 缓冲器/非门(buf/not)

相对应的关键字,及关键字的实例引用

//关键字
buf    //缓冲器          not      //非门
//缓冲门、非门的调用  ,实例引用时可以不加实例命名
buf b1(OUT1, IN);
not n1(OUT1, IN);

//输出端多于两个
buf b1_2out(OUT1, OUT2, IN);

带控制端的缓冲器/非门(bufif / notif)

 相对应的关键字,及关键字的实例引用

//关键字
bufif1   //高电平使能导通的缓冲门      notif1      //高电平使能导通的非门
bufif0   //低电平使能导通的缓冲门      nitif0      //低电平使能导通的非门
//实例化引用
bufif1 b1(out, in ,ctrl);
bufif0 b0(out, in ,ctrl);

notif1 n1(out, in, ctrl);
notif0 n0(out, in, ctrl);

5.1.3 实例数组

有很多情况下,需要多某种相同的门类型进行多次调用(实例引用),这些相同的门实例的区别仅仅在于它们分别连接在不同的向量信号位上,为了简化这种类型的门,Verilog允许用户自己来定义门实例数组。

//简单的门级原语实例数组
wire [3:0] OUT, IN1, IN2;       //声明了3个4位线型变量

//基本门的数组调用
nand n_gate[3:0] (OUT, IN1, IN2);

//上面一条语句相当于4条实例引用语句
nand n_gate0(OUT[0], IN1[0], IN2[0]);
nand n_gate1(OUT[1], IN1[1], IN2[1]);
nand n_gate2(OUT[2], IN1[2], IN2[2]);
nand n_gate3(OUT[3], IN1[3], IN2[3]);

5.1.4 门级建模举例

(1)门级多路选择器

 引脚信息表及功能真值表

输入输出信号描述
信号位宽类型功能描述
i01bitinput输入信号0
i11bitinput输入信号1
i21bitinput输入信号2
i31bitinput输入信号3
s01bitinput地址输入信号
s11bitinput地址输入信号
out1bitoutput输出信号
mux_4_1数据选择器真值表
输入信号地址输入信号输出
s0s1out
i000i0
i101i1
i210i2
i311i3

 程序块

module mux_4_1(out, i0, i1, i2, i3, s1, s0);
//模块的输入输出端口声明
    output out;    
    input i0, i1, i2, i3;
    input s1, s0;

//模块内部线网连接变量声明
    wire s1n, s0n;
    wire y0, y1, y2, y3;
   
//非门(not)实例引用
    not n1(s1n, s1);
    not n0(s0n, s0);
//与门(and)实例引用
    and a0(y0, i0, s1n, s0n);
    and a1(y1, i1, s1n, s0);
    and a2(y2, i2, s1,  s0n);
    and a3(y3, i3, s1,  s0);
//或门(or)实例化引用
    or (out, y0, y1, y2, y3);
endmodule

程序块逻辑综合后的RTL逻辑图: 

由于RTL中并没有三线的与门和四线的或门。因此用两个两线与门代替三线的一个与门;用三个两线或门代替一个四线与门,同时这里的非门直接加在了与门和或门的引脚上。有上图通过逻辑综合出来的RTL逻辑图与原本的逻辑选择器进行对比发现逻辑并无错误。

激励块

module tb_mux_4_1();
//声明激励块中与代码块中的连接变量
    wire OUT;
    reg IN0, IN1, IN2, IN3;
    reg S1, S0;
//实例引用代码块并进行变量连接
    mux_4_1  mux_4_1_stim(OUT, IN0, IN1, IN2, IN3, S1, S0);
    
    initial begin
        IN0 = 1'b1;  IN1 = 1'b0;  IN2 = 1'b1;  IN3 = 1'b0;
        #30 $display("IN0=%b, IN1=%b, IN2=%b, IN3=#b\n", IN0, IN1, IN2, IN3);
        //选择IN0
        S1 = 0;  S0 = 0;
        #30 $display("s1=%b, s0=%b, OUT=%b\n", S1, S0, OUT);
        //选择IN1
        S1 = 0;  S0 = 1;
        #30 $display("s1=%b, s0=%b, OUT=%b\n", S1, S0, OUT);
        //选择IN2
        S1 = 1;  S0 = 0;
        #30 $display("s1=%b, s0=%b, OUT=%b\n", S1, S0, OUT);
        //选择IN3
        S1 = 1;  S0 = 1;
        #30 $display("s1=%b, s0=%b, OUT=%b\n", S1, S0, OUT);   
    end 
endmodule

通过逻辑仿真得出逻辑仿真结果,与真值表对比也并无错误。 

(2)四位脉动进位全加器 

四位脉动进位全加器可以使用四个一位全加器构成。

 而一位全加器可由两个一位半加器,加上同或门构成。

一位全加器逻辑式:sum=(a\oplus b\oplus cin) ; cout=(a\cdot b)+cin\cdot (a\oplus b)

 代码块

//一位加法器
module full_add(sum, c_out, a, b, c_in);
//端口变量声明
    output sum, c_out;
    input  a, b, c_in;    
//内部网线变量声明
    wire s1, c1, s2;

//门级实例化
    xor (s1, a, b);
    and (c1, a, b);
    
    xor (sum, s1, c_in);
    and (s2, s1, c_in);
    
    xor (c_out, s2, c1);
endmodule

对其进行综合,可以看到RTL逻辑视图,并与其逻辑原理图对比:

//四位脉动进位全加器,为顶层模块
module full_add4(sum, c_out, a, b, c_in);
//端口变量声明
    output [3:0] sum;
    output c_out;
    input [3:0] a, b;
    input c_in;
//内部线网变量声明    
    wire c1, c2, c3;
//实例化全加器,串联形成4位脉动全加器
    full_add fa0(sum[0], c1, a[0], b[0], c_in);
    full_add fa1(sum[1], c2, a[1], b[1], c1);
    full_add fa2(sum[2], c3, a[2], b[2], c2);
    full_add fa3(sum[3], c_out, a[3], b[3], c3);
endmodule

 对其进行逻辑综合生成RTL逻辑视图,与其原理逻辑视图对比可知,并没有问题: 

激励块:验证代码块的逻辑功能

//逻辑仿真激励块
//Company: 追逐者——桥的小作坊
module tb_full_add4();
    reg [3:0] A, B;
    reg C_IN;
    wire [3:0] SUM;
    wire C_OUT;
    
//实例化
    full_add4 fadd4(SUM, C_OUT, A, B, C_IN);
    
    initial begin
        $monitor($time, "A=%b, B=%b, C_IN=%b, -----  C_OUT=%b, SUM=%b\n", A, B, C_IN, C_OUT, SUM);    
    end
    initial begin
        A = 4'd0;   B = 4'd0;  C_IN = 1'b0;
        #50 A = 4'd3;   B = 4'd4;  
        #50 A = 4'd2;   B = 4'd5;  
        #50 A = 4'd9;   B = 4'd9;  
        #50 A = 4'd10;   B = 4'd15; 
        #50 A = 4'd10;   B = 4'd5;  C_IN = 1'b1;
    end
endmodule

仿真结果如下图所示:

5.2 门延迟 

在MOS管组成的电路中由于内部的等效电容与电阻形成的RC电路,故在0、1变化时,一定会出现变化延迟现象,如果不能理解这句话,请大家一定要重新学习CMOS门电路。关于延迟本章只是做了简单的介绍,更为详细的讲解,将在第十章进行讲解与学习。

5.2.1 上升、下降和关断延迟

在Verilog门级原语中,有三种从输入到输出的延迟。

  • 上升延迟

在门的输入发生变化的情况下,门的输出从0,X,Z变化为1所需要的时间称为上升延迟。

  •  下降延迟

下降延迟为门的输入从1,X,Z变化为0所需的时间

  • 关断延迟

关断延迟指门的输出从0,1,X,变化为高阻抗Z所需的时间。

另外,如果值变化到不确定值X,则所需的时间可以看成是以上三种延迟值最小的那个。

        在Verilog中,用户可以使用三种不同的方法来说明门的延迟。

  1. 当指定一个延迟值时,所有延迟类型都使用该值
  2. 当指定两个延迟值时,分别代表上升延迟和下降延迟
  3. 当指定三个延迟值时,分别代表升延迟、下降延迟和关断延迟
  4. 如果未指定延迟时间,那么默认延迟值为0
//门延迟值说明
//一个延迟值
and #(delay_time) a1(out, i1, i2);
and #(5) a11(out, i1, i2);
//两个延迟值
and #(rise_val, fall_val) a2(out, i1, i2);
and #(4, 6)  a21(out, i1, i2);
//三个延迟值
bufif0 #(rise_val, fall_val, turnoff_val) b1(out, in, control);
bufif0 #(3, 4, 5) b11(out, in, cintrol);

5.2.2  最小、经典、最大延迟

在Verilog中,除了指定以上三种延迟外,对每种类型的延迟还可以指定其最小值、最大值和典型值延迟。可以在仿真一开始进行指定,也可以在仿真过程中指定。具体控制方法与使用的仿真器和操作系统有关,未指定则默认为典型延迟值。

Verilog用户可以灵活地对设计中的各种类型的延迟(上升、下降、典型)使用三个不同的具体数值,不必修改设计就可以使用的延迟值进行仿真。

//一个延迟
//最小延迟=4
//典型延迟=5
//最大延迟=6
and #(4:5:6) a1(out, i1, i2);

//两个延迟
//最小延迟,上升延迟=3,下降延迟=5,关断延迟=min(3,5)
//典型延迟,上升延迟=4,下降延迟=6,关断延迟=min(4,6)
//最大延迟,上升延迟=5,下降延迟=7,关断延迟=min(5,7)
and #(3:4:5, 5:6:7) a2(out, i1, i2);

//三个延迟
//最小延迟,上升延迟=3,下降延迟=5,关断延迟=7
//典型延迟,上升延迟=4,下降延迟=6,关断延迟=8
//最大延迟,上升延迟=5,下降延迟=7,关断延迟=9
and #(3:4:5, 5:6:7, 7:8:9) a3(out, i1, i2);


//通过命令行可以启动行方式
> verilog test.v +maxdelays

5.2.3 延迟举例

module delay(out, a, b, c);
    output out;
    input a,b,c;
    wire e;
    and #(50) a1(e,a,b);
    or #(40) o1(out,e,c);
endmodule
module tb_delay();
    wire OUT;
    reg A,B,C;
    
    delay d1(OUT,A,B,C);
    initial begin
        A=1'b0;   B=1'b0;   C=1'b0;
        #100 A=1'b1;   B=1'b1;   C=1'b1;
        #100 A=1'b1;   B=1'b0;   C=1'b0;
        #200 $finish;
    end 
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐者-桥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值