Electronic – Verilog style: one large always block vs multiple small always blocks

system-verilogverilog

Say I have multiple registers set up to update on the same clock, based on different conditions.

I could set this up as a series of multiple always blocks:

reg [7:0] counter;
reg output_even;
reg output_multiple_of_5;

always_ff @ (posedge clk)
   if(reset) 
       counter <= 0;
   else
       counter <= counter + 1;


always_ff @ (posedge clk)
   if(reset) 
       output_even <= 0;
   else begin
       if(counter % 2 == 0)
           output_even <= 1;
       else
           output_even <= 0;
   end


always_ff @ (posedge clk)
   if(reset) 
       output_multiple_of_5 = 0;
   else begin
       if(counter % 5 == 0)
           output_multiple_of_5 <= 1;
       else
           output_multiple_of_5 <= 0;
   end

Alternatively, I could set this up as a single always block with multiple conditions:

reg [7:0] counter;
reg output_even;
reg output_multiple_of_5;

always_ff @ (posedge clk)
   if(reset) begin
       counter = 0;
       output_even = 0;
       output_multiple_of_5 <= 0;
   end
   else begin
       counter = counter + 1;

       if(counter % 2 == 0)
           output_even <= 1;
       else
           output_even <= 0;

       if(counter % 5 == 0)
           output_multiple_of_5 <= 1;
       else
           output_multiple_of_5 <= 0;

   end

I suppose one way of looking at this is whether I should use separate always blocks for separate clocks, or for separate registers.

  1. Is there any difference between how these two code blocks will be synthesized? Extra clock cycle, implied latch, etc, or are they functionally equivalent?
  2. Is there any stylistic or code-maintenance reason to prefer one style vs the other?

Best Answer

Without the use of non-blocking assignments, the multiple always block style has race conditions. There no way of knowing in a clock cycle whether counter has the previous or updated value. In the single always, you must write your code in a specific flow order. You should be using non-blocking assignments to any valuables that are read by other block to prevent race conditions.

Using multiple blocks is likely to make your code more readable, but the only advantage I can think of for combining then into a single block is when you have common expressions and conditional statements. Your reset example is simple, but you don't want to repeat large case statements as that makes maintenance more difficult.