2
\$\begingroup\$

Occasionally writing some FPGA-targeted Verilog code at my job, I often need to drive output signals high during one clock cycle exactly. Sometimes I use the following “trick“ to achieve this (let me show a simple example):

module SignalEvery10thClock(
        input clock,
        output reg signal);
  
    reg [3:0] count = 0;
    always @(posedge clock) begin
        
        // The trick.
        if (signal)
            signal <= 0;

        if (count != 10)
            count <= count + 1'b1;
        else begin
            count <= 0;
            signal <= 1;
        end
    end
endmodule

The code like the above seems to synthesize and work just fine (at least, in Synplify and Verilator). However, I don't have a clear understanding why it even compiles successfully: the assignment to signal seems ambiguous in the case when signal == 1 and count == 10.

What this ambiguity synthesizes into?

Can the synthesizer deduce that the case when both signal == 1 and count == 10 are true isn't actually possible?

Is writing code like this considered good or bad practice?

What is the proper way to reset the output signal once next clock arrives?

\$\endgroup\$
2
  • \$\begingroup\$ The simulation is done in tiny steps. If 'signal' is '1' during a tiny step, then it must have been set when 'count == 10' in the immediately prior step and where 'count' is always then set to 0. So when 'signal' is '1' it is always the case that 'count' is 0. That removes ambiguity as your case cannot arise. Synthesis, to the degree possible, should mirror this, I think. \$\endgroup\$
    – jonk
    Commented May 1, 2021 at 1:16
  • 1
    \$\begingroup\$ It would be more clear if you set signal to zero in the block where you increment count. Also this code will set signal to $1$ every eleven ticks instead of 10, because you are counting from 0 to 10. \$\endgroup\$
    – IanJ
    Commented May 1, 2021 at 18:47

2 Answers 2

3
\$\begingroup\$

However, I don't have a clear understanding why it even compiles successfully: the assignment to signal seems ambiguous in the case when signal == 1 and count == 10. What this ambiguity synthesizes into? Can the synthesizer deduce that the case when both signal == 1 and count == 10 are true isn't actually possible?

There is no ambiguity on signal even if that condition gets satisfied (of course it won't happen in this case). For eg., suppose you simply write under @(posedge clk):

if (a) begin    
   b <= 1'b1 ;
   b <= 1'b0 ;
end

The synthesiser will 'ignore' the first statement as the final assignment to b gets 'precedence' on satisfying that condition on a.

Synthesiser therefore synthesises the code equivalent to:

if (a) begin    
   b <= 1'b0 ;
end

This is because in a hardware, a signal can only settle to a single value on any rising edge of the clock. The synthesiser is smart enough to deduce that.

Is writing code like this considered good or bad practice?

Can't generalize it as it depends on the context. But all fine as far as it is synthesisable construct.

For instance, your code snippet was synthesised in (Vivado synthesiser) to a netlist with count == 10 controlling the set to signal register:

enter image description here

Alternatively, you could have achieved the same functionality by:

 if (count != 10) begin
    count  <= count + 1'b1 ;
    signal <= 0            ;
 end

 else begin
    count  <= 0 ;
    signal <= 1 ;
 end

OR

 signal <= 0 ;

 if (count != 10) begin
    count  <= count + 1'b1 ;        
 end

 else begin
    count  <= 0 ;
    signal <= 1 ;
 end

In my Vivado synthesiser, the above code snippets were synthesised to the same netlist, with count != 10 controlling the reset to signal register:

enter image description here

Timing performance is similar for all the code snippets with same path complexity, however the last two code snippets' netlist used two sets of LUTs to control reset to count, and reset to signal register. While the first code snippet's netlist used the same LUT to control reset to count register and set to signal register.

Side note: It's always recommended to use a reset signal to reset all registers in your design.

\$\endgroup\$
1
\$\begingroup\$

I would not recommend the coding style you used. It will be hard to understand the design intent for those reading the code (it might be you in the future). As much as possible, use a single conditional block for driving a signal.

I recommend using unique if if your EDA tool supports SystemVerilog, else use the plain if statement in a single block. Like this:

 unique if (count != 10) begin
    count  <= count + 1'b1;
    signal <= 0;
 end
 else begin
    count  <= 0;
    signal <= 1;
 end
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.