Procedural blocks in system verilog
In Verilog, there are initial and always procedural blocks as we have seen. In system Verilog, these procedural blocks were improved, and a few more procedural blocks were added. Some of these added procedural blocks are synthesizable and some are non-synthesizable. In this article we will see these blocks in detail.
always block was used to define both combinational and sequential circuits. But in
always block if we forget to add the else part it may be considered as latch during synthesis. Also, the sensitivity list needs to be provided correctly for the simulation to match the actual circuit.
To account for these problem System Verilog introduced a new
always block construct known as
always_comb begin ... end
always_combautomatically executes once at time-zero apart from normal execution whereas
alwaysexecutes only when there is change in the signal defined in the sensitivity list. This is helpful as in always block the value of signal is normally x until the block is triggered.
always_combautomatically infers the sensitivity list whereas in
alwaysblock sensitivity list needs to be given manually. Sometimes some signal may be missed out in the always block leading to different result in simulation and actual hardware.
always_combensures that the variable on the left-hand side of the assignment is not written by another process. Whereas in
alwaysmultiple process can write to the same variable.
System Verilog introduces
always_latch to write the latch logic. In
always_latch the sensitivity list is also automatically inferred from the signals used inside the block.
The only difference in
always_latch is that we need to have a if statement to support the enable signal for the latch
always_latch begin if(enable_cond) begin ... end end
System Verilog introduces
always_ff to write sequential logics which can be synthesized. Always_ff also ensures that the left side of the assignment is not written by any other process.
In always_ff we can have a
iff keyword to control the triggering of the block.
always_ff @(event_control) begin end
module proc_mod(input wire clk, rst, a, b, c, en, output reg op1, op2, op3); always_comb begin op1 = a + b; end always_latch begin if(en) begin op2 = c; end end always_ff @(posedge clk or negedge rst) begin if(!rst) op3 = 0; else begin op3 = a + b + c; end end endmodule
The test bench for the above code is not given. It is recommended to implement a test bench using the concepts discussed so far. In this scenario there is no specific requirement for the design to match. Thus, the test bench can be implemented in various ways.Try this code in EDA Playground
Final is a new procedural block introduced in system Verilog. It is non synthesizable and is called at the end of the simulation. This block is basically used to carry out last moment house keeping activites. As it is non-synthesizable it is mainly used in test bench codes. One use could be to print the report of a test in the final block.
final begin end
module final_block; initial begin $display("[%0t] Printing from intitial block", $time); #30; $finish(); end final begin $display("[%0t] Printing from final block", $time); end endmodule
In Verilog, we have seen that we can name procedural blocks using a
:. In System Verilog this has been extended and we can write the block name at the end of the block as well. This helps to improve the readability of the code as we can easily identify the opening and closing of a block.
module abc; initial begin:init_block $display("Initial block"); end:init_block endmodule
Simulators may give errors or warnings if the name at the end is different than the name of the block at the beginning.