过程块
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 */