对于unique-if ,如果condition没有一个匹配且没有加else语句,则会报告一个错误;如果超过1个condition匹配,也会报告错误;
unique0-if与unique-if的不同之处在于,如果没有一个condition匹配也不会报错;
- module tb;
- int x = 4;
-
- initial begin
- // This if else if construct is declared to be "unique"
- // Error is not reported here because there is a "else"
- // clause in the end which will be triggered when none of
- // the conditions match
- unique if (x == 3)
- $display ("x is %0d", x);
- else if (x == 5)
- $display ("x is %0d", x);
- else
- $display ("x is neither 3 nor 5");
-
- // When none of the conditions become true and there
- // is no "else" clause, then an error is reported
- unique if (x == 3)
- $display ("x is %0d", x);
- else if (x == 5)
- $display ("x is %0d", x);
- end
- endmodule
- module tb;
- int x = 4;
-
- initial begin
- // Exits if-else block once the first match is found
- priority if (x == 4)
- $display ("x is %0d", x);
- else if (x != 5)
- $display ("x is %0d", x);
- end
- endmodule
- module tb;
- bit [1:0] abc;
-
- initial begin
- abc = 1;
-
- // None of the case items match the value in "abc"
- // A violation is reported here
- unique case (abc)
- 0 : $display ("Found to be 0");
- 2 : $display ("Found to be 2");
- //使用unique case此时多加default
- endcase
- end
- endmodule
- bit [2:0] a;
- priority case(a) // 值4,5,6,7会引起一个运行时警告
- 3'b00?: $display("0 or 1");
- 3'b0??: $display("2 or 3");
- endcase
在SV中,always块不能存在于类和其他过程块中,所以用forever代替。格式如下:
- always begin
- // Multiple statements
- end
- class Monitor;
- virtual task run();
- forever begin
- @(posedge vif.clk);
- if (vif.write & vif.sel)
- // Capture write data
- if (!vif.write & vif.sel)
- // Capture read data
- end
- endtask
- endclass
-
- module tb;
- Monitor mon;
-
- // Start the monitor task and allow it to continue as
- // long as there is activity on the bus
- initial begin
- fork
- mon.run();
- join_none
- end
- endmodule
为了防止循环体在delta时间内产生无限循环,导致仿真挂起,forever循环体内部必须带有时序控制或者disable语句。
类C语言的break声明立即结束循环操作。循环不会重新执行,除非执行流程重新到达循环的起点
- 1 // find first bit set within a range of bits
- 2 always_comb begin
- 3 first_bit = 0;
- 4 for (int i=0; i<=63; i=i+1) begin
- 5 if (i < start_range) continue;
- 6 if (i > end_range) break; // exit loop
- 7 if ( data[i] ) begin
- 8 first_bit = i;
- 9 break; // exit loop
- 10 end
- 11 end // end of the loop
- 12 ... // process data based on first bit set
- 13 end
类C语言的continue声明跳转到循环的末尾并执行循环的控制。使用continue声明时,不需要对代码添加命名的begin…end块,而这在使用disable声明时是必要的。
- 1 logic [15:0] array [0:255];
- 2 always_comb begin
- 3 for (int i = 0; i <= 255; i++) begin : loop
- 4 if (array[i] == 0)
- 5 continue; // skip empty elements
- 6 transform_function(array[i]);
- 7 end // end of loop
- 8 end
system verilog增加了类C语言的return声明,用于从一个非void函数中返回数值或者从一个void函数或任务返回。return声明可以在任务或函数执行流程的任意一点执行。当return声明执行后,任务或者函数立即退出而不需要执行到任务或者函数的末尾
- 1 task add_up_to_max (input [ 5:0] max,
- 2 output [63:0] result);
- 3 result = 1;
- 4 if (max == 0) return; // exit task
- 5 for (int i=1; i<=63; i=i+1) begin
- 6 result = result + result;
- 7 if (i == max) return; // exit task
- 8 end
- 9 endtask
disable :用于在多进程的场景下终止一个或多个进程
disable语句可以用在task或者块中去终止指定的task或块,包括终止disable语句所在的块或者task。disable也可以用在function中去终止task或者块,但不能用于终止function。当在function中用dsiable语句终止了一个task或者块,而这个task或者块刚好又是这个function的caller, 这种情况的结果是未知的。
- task proc_a;
- begin
- ...
- ...
- if (a == 0)
- disable proc_a; // return if true
- ...
- ...
- end
- endtask
event是一个静态对象句柄,用于在两个或多个同时活动的进程之间进行同步。 一个进程将触发事件,另一个进程将等待事件。
【1】可以赋值或与其他事件变量进行比较
【2】可以赋值为空
【3】当赋值给另一个事件时,两个变量都指向同一个同步对象
【4】可以传递给队列,函数和任务
如何触发并等待事件?
【1】可以使用->或->>运算符触发命名事件
【2】进程可以使用@运算符或.triggered等待事件
- module tb;
-
- //创建一个事件变量,进程可用于触发和等待
- event event_a;
-
- // 线程1:使用“->”运算符触发事件
- initial begin
- #20 ->event_a;
- $display ("[%0t] Thread1: triggered event_a", $time);
- end
-
- // 线程2:使用“ @”运算符等待事件
- initial begin
- $display ("[%0t] Thread2: waiting for trigger ", $time);
- @(event_a);
- $display ("[%0t] Thread2: received event_a trigger ", $time);
- end
-
- // 线程3:使用“ .triggered”等待事件
- initial begin
- $display ("[%0t] Thread3: waiting for trigger ", $time);
- wait(event_a.triggered);
- $display ("[%0t] Thread3: received event_a trigger", $time);
- end
- endmodule