• SV 过程块


    过程块

    scope: 域

    • 硬件域:例化硬件的空间
      • module ... endmodule
      • interface ... endinterface
    • 软件域:定义软件变量的空间
      • program ... endprogram
      • class ...  endclass

    always

    • 用来描述硬件时序电路和组合电路的正确打开方式,因此只能在module或者interface中使用
    • 用法: always @(敏感信号列表)

    initial

    • 只执行一次
    • initial和always一样,无法被延迟执行,在仿真一开始都会同时执行
    • initial和always之间在执行顺序上没有顺序可言
    • initial 不可综合,用于测试
    • initial 过程块可以在module、interface和program中使用
    • 使用begin ... end包裹

    function

    • 可以在参数列表中指定输入参数(input)、输出参数(output)、输入输出参数(inout)、或者引用参数(ref)
    • 可以返回数值或者不返回数值(void);如果返回,使用关键字return
    • 默认的数据类型是logic,例如input [7:0] addr
    • 数组可以作为形式参数传递
    • 只有数据变量可以在形式参数列表中被生命ref类型,线网类型不能
    • 在使用ref时,有时候为了保护数据对象只被读取而不被写入。可以使用const的方式来限定ref声明的参数
    • 支持默认值
    function int double_f0(int a);
      return 2*a;
    endfunction
    
    function void double_f1(input int a, output int b);
      b = 2*a;
    endfunction
    
    function void double_f2(inout int a);
      a = 2*a;
    endfunction
    
    function automatic void double_f3(ref int a);
      a = 2*a;
    endfunction
    
    initial begin: 
      int v1, v2;
      
      v1 = 10;
      v2 = double_f0(v1);
      $display("v1 = %0d, double function result is %0d", v1, v2);
    
      v1 = 10;
      double_f1(v1, v2);
      $display("v1 = %0d, double function result is %0d", v1, v2);
    
      v1 = 10;
      $display("v1 is %0d before calling double_f2(v1)", v1);
      double_f2(v1);
      $display("v1 is %0d (result) after calling double_f2(v1)", v1);
    
      v1 = 10;
      $display("v1 is %0d before calling double_f3(v1)", v1);
      double_f3(v1);
      $display("v1 is %0d (result) after calling double_f3(v1)", v1);
    end

    task

    • task无法通过return返回结果,只能通过output,inout 或ref的参数返回
    • task内可以置入耗时语句,而function不能;常见的耗时语句包括,@event、wait event、#delay等
    • task 中可以调用 task 和 function, 而 function 只能调用function
    task double_t1(input int a, output int b);
      b = 2*a;
    endtask
    
    task double_t2(inout int a);
      a = 2*a;
    endtask
    
    task automatic double_t3(ref int a);
      a = 2*a;
    endtask
    
    task double_t2_delay(inout int a);
      a = 2*a;
      #10ns;
    endtask
    
    task automatic double_t3_delay(ref int a);
      a = 2*a;
      #10ns;
    endtask
    
    initial begin: 
      int v1, v2;
      
      v1 = 10;
      double_t1(v1, v2);
      $display("v1 = %0d, double task result is %0d", v1, v2);
    
      v1 = 10;
      $display("v1 is %0d before calling double_t2(v1)", v1);
      double_t2(v1);
      $display("v1 is %0d (result) after calling double_t2(v1)", v1);
    
      v1 = 10;
      $display("v1 is %0d before calling double_t3(v1)", v1);
      double_t3(v1);
      $display("v1 is %0d (result) after calling double_t3(v1)", v1);
    end

    inout vs  ref

    initial begin: inout_vs_ref
      int v1, v2;
      v1 = 10;
      $display("v1 is %0d before calling double_t2_delay(v1)", v1);
      fork
        double_t2_delay(v1);
        begin #5ns; $display("@%0t v1 = %0d in task call double_t2_delay(v1)", $time, v1); end
      join
      $display("v1 is %0d (result) after calling double_t2_delay(v1)", v1);
    
      v1 = 10;
      $display("v1 is %0d before calling double_t3_delay(v1)", v1);
      fork
        double_t3_delay(v1);
        begin #5ns; $display("@%0t v1 = %0d in task call double_t3_delay(v1)", $time, v1); end
      join
      $display("v1 is %0d (result) after calling double_t3_delay(v1)", v1);
    end

    变量生命周期

    动态: automatic

    • 如果数据变量被声明为automatic,那么进入该进程或方法后,automatic变量会被创建,离开进程或方法后被销毁

    静态:static

    • 全局变量伴随程序执行开始到结束,module中的变量默认情况下全部为全局变量

    • static变量在仿真开始时会被创建,在进程或方法执行过程中,可以被多个京城和方法共享

    static vs automatic

    • 对于automatic方法,其内部变量默认也是automatic,伴随automatic方法的声明周期建立和销毁
    • 对于static方法,其内部的所有变量默认为static类型
    • 无论是automatic或者static方法,可以对其内部定义的变量做单个声明。使其类型被显式声明为automatic或static
    • 对于static变量用户在声明是应该对齐做初始化,而初始化只会伴随他的生命周期发生一次,并不会随着方法调用被多次初始化
    module tb1;
    
        function automatic int auto_cnt(input a);
            int cnt =0;
            cnt +=a;
            return cnt;
        endfunction
    
        function static int static_cnt(input a);
            int cnt=0;
            cnt += a;
            return cnt;
        endfunction
    
        function int def_cnt(input a);
            int cnt=0;
            cnt += a;
               return cnt;
        endfunction
    
        function int def_cnt_a(input a);
            automatic int cnt=0;
            cnt += a;
            return cnt;
        endfunction
    
        initial begin
            $display("@1  auto_cnt=%0d",   auto_cnt(1));
            $display("@2  auto_cnt=%0d",   auto_cnt(1));
            $display("@1  static_cnt=%0d", static_cnt(1));
            $display("@2  static_cnt=%0d", static_cnt(1));
            $display("@1  def_cnt=%0d",    def_cnt(1));
            $display("@2  def_cnt=%0d",    def_cnt(1));
            $display("@1  def_cnt_a=%0d",  def_cnt_a(1));
            $display("@2  def_cnt_a=%0d",  def_cnt_a(1));
        end
    endmodule
    
    /*
    result
    @1  auto_cnt=1
    @2  auto_cnt=1
    @1  static_cnt=1
    @2  static_cnt=2
    @1  def_cnt=1
    @2  def_cnt=2
    @1  def_cnt_a=1
    @2  def_cnt_a=1
    */

  • 相关阅读:
    readAsDataURL(file) & readAsText(file, encoding)
    MySQL: Integer & String types
    JavaScript 中事件绑定的三种方式
    vue-router 导航守卫
    js 常见数组算法
    CSS渐变色边框,解决border设置渐变后,border-radius无效的问题
    margin:auto你真的理解么
    当margin和padding的值是百分比时,如何计算
    关于 js 函数参数的this
    Vue.js 中的 v-cloak 指令
  • 原文地址:https://www.cnblogs.com/gareth-yu/p/14610793.html
Copyright © 2020-2023  润新知