SystemVerilog note (3)

本文介绍了一个基于SystemVerilog的测试平台实现案例,包括事务级建模、生成器、驱动器、接口及环境等模块的设计。通过随机化事务级刺激信号来验证加法器模块的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SystemVerilog TestBench Example - ADDER

Part 1 Transaction

  • Fields required to generate the stimulus are declared in the transaction class.
  • Transaction class can also be used as the placeholder for the activity monitored by the monitor on DUT signals.
    class transaction;        //declaring the transaction items
      rand bit [3:0] a;
      rand bit [3:0] b;
           bit [6:0] c;
      function void display(string name);
        $display("- %s ",name);
        $display("- a = %0d, b = %0d",a,b);
        $display("- c = %0d",c);
      endfunction
    endclass

    Part 2 Generator

  • Generating the stimulus by randomizing the transaction class
  • Sending the randomized class to driver
    class generator;
       
      rand transaction trans;   //declaring transaction class
       
      mailbox gen2driv;         //declaring mailbox
     
      event ended;             //event, to indicate the end of transaction generation
     
      //constructor
      function new(mailbox gen2driv);
        this.gen2driv = gen2driv;          //getting the mailbox handle from env
      endfunction
       
      //main task, generates(create and randomizes) the packets and puts into mailbox
      task main();
          trans = new();
          if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
          gen2driv.put(trans);     //put data into mailbox
          -> ended; //triggering indicatesthe end of generation
      endtask   
    endclass

    Part 3 Interface

  • The interface will group the signals
    interface myintf(input logic clk,reset);   
      //declaring the signals
      logic       valid;
      logic [3:0] a;
      logic [3:0] b;
      logic [6:0] c;   
    endinterface

    Part 4 Driver

  • receive the stimulus generated from generator and drive to DUT by assigning transaction class values to interface signals. 
    class driver;
      
      //used to count the number of transactions
      int no_transactions;
       
      //creating virtual interface handle  定义虚接口
      virtual myintf vif;
       
      //creating mailbox handle
      mailbox gen2driv;
       
      //constructor
      function new(virtual myintf vif,mailbox gen2driv);
        //getting the interface
        this.vif = vif;
        //getting the mailbox handles from  environment
        this.gen2driv = gen2driv;
      endfunction
       
      //Reset task, Reset the Interface signals to default/initial values
      task reset;
        wait(vif.reset);
        $display("[ DRIVER ] ----- Reset Started -----");
        vif.a <= 0;
        vif.b <= 0;
        vif.valid <= 0;
        wait(!vif.reset);
        $display("[ DRIVER ] ----- Reset Ended   -----");
      endtask
       
      //drivers the transaction items to interface signals
      task main;
        forever begin
          transaction trans;
          gen2driv.get(trans);
          @(posedge vif.clk);
          vif.valid <= 1;
          vif.a     <= trans.a;
          vif.b     <= trans.b;
          @(posedge vif.clk);
          vif.valid <= 0;
          trans.c   <= vif.c;
          @(posedge vif.clk);
          trans.display("[ Driver ]");
          no_transactions++;
        end
      endtask           
    endclass

    Part 5 Environment

  • Environment is container class contains MailboxGenerator and Driver
    class environment;
       
      generator gen;       //generator and driver instance
      driver    driv;
       
      mailbox gen2driv;    //mailbox handle's
       
      virtual myintf vif;    //virtual interface
       
      //constructor
      function new(virtual myintf vif);
        this.vif = vif;     //get the interface from test    
        //creating the mailbox (Same handle will be shared across generator and driver)
        gen2driv = new();
        gen  = new(gen2driv);        //creating generator and driver
        driv = new(vif,gen2driv);
      endfunction
       
      //
      task pre_test();
        driv.reset();     //function in driver class
      endtask
       
      task test();
        fork
        gen.main();
        driv.main();
        join_any
      endtask
       
      task post_test();
        wait(gen.ended.triggered);
        wait(gen.repeat_count == driv.no_transactions);
      endtask 
       
      //run task
      task run;
        pre_test();
        test();
        post_test();
        $finish;
      endtask
       
    endclass

    Part 6 Test

  • Creating the environment.
  • Configuring the testbench i.e, setting the type and number of transactions to be generated. 
  • Initiating the stimulus driving.
    `include "environment.sv"
    program test(myintf);
       
      environment env;     //declaring environment instance
       
      initial begin
        env = new(myintf);      //creating environment
         
        //setting the repeat count of generator as 10, means to generate 10 packets
        env.gen.repeat_count = 10;
         
        //calling run of env, it interns calls generator and driver main tasks.
        env.run();
      end
    endprogram

    Part 7 Top

  • This is the topmost file, which connects the DUT and TestBench. 
  • TestBench top consists of DUT, Test and Interface instances.
  • The interface connects the DUT and TestBench.
    `include "interface.sv"
    `include "random_test.sv"
     
    module tbench_top;
       
      bit clk;
      bit reset;
        
      always #5 clk = ~clk;    //generate clk
       
      //reset Generation
      initial begin
        reset = 1;
        #5 reset =0;
      end   
       
      //creatinng instance of interface, inorder to connect DUT and testcase 实例interface
      myintf i_intf(clk,reset);
       
      //实例 test class
      test t1(i_intf);
       
      //DUT instance, interface signals are connected to the DUT ports
      adder DUT (
        .clk(i_intf.clk),
        .reset(i_intf.reset),
        .a(i_intf.a),
        .b(i_intf.b),
        .valid(i_intf.valid),
        .c(i_intf.c)
       );
       
      //enabling the wave dump
      initial begin
        $dumpfile("dump.vcd"); $dumpvars;
      end
    endmodule

     

### SystemVerilog 中取余运算符的使用 SystemVerilog 提供了多种算术运算符来支持数值计算,其中包括加法 (`+`)、减法 (`-`)、乘法 (`*`) 和除法 (`/`) 等常见操作。除此之外,取余运算符 `%` 是一种重要的二元运算符,用于返回两个整数相除后的余数[^2]。 #### 取余运算符的基本定义 取余运算符 `%` 的作用是对两个整数执行模运算 (Modulo Operation),并返回其结果作为余数。需要注意的是,在 SystemVerilog 中,该运算符仅适用于整型数据类型(如 `integer`, `shortint`, 或者自定义位宽的数据类型)。如果尝试对浮点数或其他非整型数据应用此运算符,则会引发编译错误。 #### 运算优先级说明 根据引用中的描述可知,“&&”和“||”这类逻辑运算符具有较低的优先权等级;而感叹号 `"!"` 则拥有较高的优先顺序位于算术类之前[^1]。至于具体的四则混合表达式里边,像乘 (*) 以及除 (/) 它们要比加 (+)(-) 更先被处理,并且同样也高于条件判断式的比较部分。但是这里讨论的重点——取模%,它的优先度正好介于上述提到的一些主要类别之间,即它仅次于普通的乘除但又高过简单的增益或者损失动作。 下面给出几个关于如何正确运用这个功能的例子: #### 示例代码展示 以下是若干个利用 `%` 实现不同场景需求下的具体实现方式: ```systemverilog module mod_example; initial begin integer a, b, result; // Example 1: Basic usage of modulus operator a = 10; b = 3; result = a % b; // This will assign &#39;result&#39; the value 1 because 10 divided by 3 leaves remainder 1. $display("Result of %d %% %d is %d", a, b, result); // Example 2: Using with negative numbers a = -7; b = 4; result = a % b; // Depending on implementation, this could be either -3 or 1 $display("For negatives, Result of %d %% %d might vary as per tool but here it&#39;s %d", a, b, result); // Note that behavior when dealing with negatives can depend upon simulator specifics so always check documentation. // Example 3: Within conditional statements if ((a % 2) == 0) begin $display("%d is even.", a); end else begin $display("%d is odd.", a); end end endmodule ``` 以上模块展示了三种不同的情况:基础用法、涉及负数的情况以及将其嵌入到控制结构之中来进行决策制定的过程。 #### 特殊注意事项 当涉及到负的操作数时,某些工具可能按照截断向零(truncate towards zero)的方式工作从而得出正的结果,另一些却遵循向下舍入(flooring division)原则因而得到负值。因此开发人员应当仔细查阅所使用的仿真器的手册以确认确切的行为模式。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值