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.
Combinational logic
In Verilog, 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.
Syntax
always_comb begin
...
endAdvantage over normal always construct
always_combautomatically executes once at time-zero apart from normal execution whereasalwaysexecutes 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 inalwaysblock 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 inalwaysmultiple process can write to the same variable.
Latch logic
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
Syntax
always_latch begin
if(enable_cond) begin
...
end
endSequential Logic
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.
Syntax
always_ff @(event_control) begin
endExample
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
endmoduleThe 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 PlaygroundFinal
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.
Syntax
final begin
endExample
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
endmoduleNamed blocks
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.
Example
module abc;
initial begin:init_block
$display("Initial block");
end:init_block
endmoduleSimulators may give errors or warnings if the name at the end is different than the name of the block at the beginning.