• 【数字IC验证快速入门】8、数字IC中的典型电路及其对应的Verilog描述方法


    link

    导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思清华紫光联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。

    一、硬件描述语言

    • HDL的主流语言
      • VHDL
      • Verilog
      • SystemVerilog
    • 硬件描述的层次
      • 门级(Gate-Level)【可综合】
      • 寄存器传输级(RTL-Level)【可综合】
      • 行为级【不一定可综合】
    • RTL:Register Transfer Level
      • 可综合性
      • 可阅读性

    二、典型电路

    2.1、组合逻辑电路:全加器

    module fulladd(
        input   wire    ain,
        input   wire    bin,
        input   wire    cin,
        
        output  wire    sum,
        output  wire    cout
    );
    
    assign sum  = ain ^ bin ^ cim;
    assign cout = (ain & bin) | (bin & cin) | (ain & cin);
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 在assign中赋值的变量类型必须为wire类型
    • 在always或initial中赋值必须为reg类型
    • 2.2、组合逻辑电路:四选一选择器

      module mux_4_1(
          input   wire            C,
          input   wire            D,
          input   wire            E,
          input   wire            F,
          
          input   wire    [1:0]   S,
          
          input   reg             Mux_out
      );
      
      always@(C or D or E or F or S)
      begin
          case(S)
              2'b00 : Mux_out = C;
              2'b01 : Mux_out = D;
              2'b10 : Mux_out = E;
              default : Mux_out = F;
          endcase
      end
      
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

      2.3、组合逻辑电路:38译码器

      always@(enable or ain)
      begin
          if(!enable)
              yout = 8'b0;
          else
              case(ain)
                  3'b000 : yout = 8'b0000_0001;
                  3'b001 : yout = 8'b0000_0010;
                  3'b010 : yout = 8'b0000_0100;
                  3'b011 : yout = 8'b0000_1000;
                  3'b100 : yout = 8'b0001_0000;
                  3'b101 : yout = 8'b0010_0000;
                  3'b110 : yout = 8'b0100_0000;
                  3'b111 : yout = 8'b1000_0000;
              endcase
      end
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
    • 学习上述的独热码
    • 注意l1是不一样的!
    • 2.4、组合逻辑电路:逻辑操作

      always@(A or B)
      begin
          Q1 = A > B;
          Q2 = A < B;
          Q3 = A >= B;
      end
      
      // Q3 = A >= B; 等价于下面的代码
      
      if(A >= B)
          Q3 = 1
      else
          Q3 = 0;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      2.5、组合逻辑电路:移位操作

      2.5、组合逻辑电路:移位操作

      module shift(
          input   wire    [3:0]   data,
          
          output   reg    [3:0]   q1,
          output   reg    [3:0]   q2,
      );
      
      parameter B = 2;
      
      always@(data)
      begin
          q1 = data << B;//左移
          q2 = data >> B;//右移
      end
      
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      2.6、时序逻辑电路:计数器

      module count_en(
          input   wire                    clock,
          input   wire                    reset,
          input   wire                    enable,
          
          output  reg     [WIDTH-1 : 0]   out
          
      );
      
      parameter WIDTH = 8;
      parameter UDLY  = 1;
      
      
      always@(posedge clock or negedge reset)
      begin
          if(!reset)
              out <= 8'b0;
          else if(enable)
              out <= #UDLY out + 1; //模仿器件延时,一般不提倡
      end
      
      
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    • 时序逻辑赋值,要用非阻塞赋值
    • 2.7、时序逻辑电路:异步复位D触发器

      module dff_async_pre(
          input   wire    data,
          input   wire    clk,
          input   wire    preset,
          
          output  reg     q
      );
      
      parameter U_DLY = 1;
      
      always@(posedge clk or negedge preset)//异步复位
      begin
          if(~preset)
              q <= #U_DLY 1'b1;
          else
              q <= #U_DLY data;
      end
      
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • if/else 存在优先级
    • 2.8、时序逻辑电路:同步复位D触发器

      module dff_sync_rst(
          input   wire    data,
          input   wire    clk,
          input   wire    reset,
          
          output  reg     q
      );
      
      parameter U_DLY = 1;
      
      always@(posedge clk)//同步复位
      begin
          if(!reset)
              q <= #U_DLY 1'b0;
          else
              q <= #U_DLY data;
      end
      
      endmodule
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      2.9、时序逻辑电路:复杂D触发器(用的比较少)

      module dff_sync(
          input   wire    data,
          input   wire    clk,
          input   wire    reset,
          input   wire    preset,
          
          output  reg     q
      );
      
      parameter U_DLY = 1;
      
      always@(posedge clk or negedge reset or negedge preset)//同步复位+异步复位
      begin
          if(~reset)
              q <= 1'b0;
          else if(~preset)
              q <= 1'b1;
          else
              q <= #U_DLY data;
      end
      
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

      三、TestBench功能

      在这里插入图片描述
      • 产生激励 Generate stimulus
      • 将激励输入到待测设计(DUT - Design Under Test)
      • 产生预期 Generate Expectation
      • 获取响应(Capture response)
      • 检查响应的正确性(Check the response for correctness)
        • 对于复杂的TestBench,如后续用SystemVerilog写的TestBench(即SVTB),大都需要在TestBench中加入Reference Module(RM),然后将激励引入到RM模块中,并将RM的输出结果保存起来,进而与响应输出的结果进行比对(check)。如果结果一致,那么用例通过;如果对不上,那么DUT或RM可能有问题,需要重新检查。
        • 对于VTB,测试对象比较小,功能比较简单通常不需要加入RM。
        • RM的逻辑行为与DUT一样,只不过其中没有了延时信息!
      • 根据验证目标评估验证进度(Measure the progress against the overall verification goals)
        • 验证的核心思想:验证完备性,不仅仅是找BUG
        • 证明DUT的功能是ok的,所以首先要将DUT的功能点(Feature)给分解完全!然后依次验证每个功能点是否ok,如果error,那么就要去找BUG。
        • 验证进度需要看覆盖率CDV(Coverage Driven Verification),通常可分为两种:功能覆盖率【主观】(分解功能点,需要验证每个功能点,= 100%)、代码覆盖率【客观】(可能会存在冗余代码,某些代码会验不到,<100%)

      :输入的信号称为激励,输入激励的不同组合我们称之为不同的Pattern,也叫测试点(Test Pattern)。输出的信号称为响应

      四、验证四要素

      • 1、灌激励:产生输入信号
      • 2、做预期:产生预期结果
        • Reference Model,简称为RM
      • 3、集响应:收集输出信号
      • 4、做比较:比较结果
        • 目的:验证结果比对的自动化

      五、fulladd_tb实例

      `timescale 1ns/1ps
      module fulladd_tb;
          reg ain, bin, cin;
          
          wire cout, sum;
      
          reg clk;
          always #1 clk = ~clk; //此处时钟没用,全加器只是个组合逻辑
          
          //产生激励
          initial
          begin
              clk = 0;
              
              ain = 0;
              bin = 1;
              cin = 1;
              #10
              ain = 1;
              bin = 1;
              cin = 0;
              #10
              ain = 1;
              bin = 1;
              cin = 1;
              #10
              $finish;
          end
          
          //收集响应
          initial 
          begin
              #5;
              if(sum!=0)  $display("sum calc ERROR!!!, sum = %b", sum);
              else        $display("SUM calc correct!!!");
              if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
              else        $display("cout calc correct!!!");
              #10;
              if(sum!=0)  $display("sum calc ERROR!!!, sum = %b", sum);
              else        $display("SUM calc correct!!!");
              if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
              else        $display("cout calc correct!!!");
              #10
              if(sum!=1)  $display("sum calc ERROR!!!, sum = %b", sum);
              else        $display("SUM calc correct!!!");
              if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
              else        $display("cout calc correct!!!");
          end
          
          //例化
          fulladd u0_fulladd(
              .cout   (cout),
              .sum    (sum),
              .ain    (ain),
              .bin    (bin),
              .cin    (cin)
          );
          
      endmodule
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60

      参考

      【FPGA基础】一文快速上手 Verilog 基础知识(总结版)
  • 相关阅读:
    Python字符串—String
    Sonic云真机学习总结6 - 1.4.1服务端、agent端部署
    【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
    C++学习 --pair
    es(网站的搜索技术)
    MS5611的ZYNQ驱动试验之三 控制器代码实现
    基于区域的图像分割
    算法记录|笔试中遇到的题
    Java SE 16 新增特性
    看了这篇文章CAP你还不懂,我打你!
  • 原文地址:https://blog.csdn.net/luoganttcc/article/details/125625067