VHDL coding tips and tricks: VHDL: Can you change a signal at both positive and negative edges of the clock?

Friday, March 5, 2010

VHDL: Can you change a signal at both positive and negative edges of the clock?

Consider the following code:

signal c : std_logic_vector(3 downto 0):="0000";

process(clk)
begin
    c <= c +'1';
end process;

This code is supposed to work as a simple 4 bit counter, counting at both negative and positive edge of the clock. The design works perfectly at the simulation level. But when you synthesize this code you will get the following warnings :
WARNING:Xst:647 - Input clk is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:Xst:2170 - Unit test : the following signal(s) form a combinatorial loop: Madd_c4.
WARNING:Xst:2170 - Unit test : the following signal(s) form a combinatorial loop: Madd_c6.
WARNING:Xst:2170 - Unit test : the following signal(s) form a combinatorial loop: Madd_c_cy<0>.
Normally most of the warnings can be neglected during synthesis without posing any critical problems. But in this case, the warning "the input clk is never used" cannot be ignored. The synthesis tool was unable to find the right resource in the fpga for the logic we wanted to implement. So it simply ignores the clock signal and surrounded logic and synthesizes a combinatorial circuit.

Lets modify the first version of the code above and see if we can make it work. 

process(clk)
begin
    if(rising_edge(clk)) then   -- for posedge
        c <= c +'1';
    end if;
    if(falling_edge(clk)) then  --for negedge
        c <= c +'1';
    end if;
end process;

It seems no! We still get a synthesis error.
Signal c cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
The second version clearly shows that it is not possible to change a signal at both negative and positive edges of the clock. Xilinx ISE either synthesizes it in a different way or it gives an error.

One reader asked in the comment section, why does the following code synthesis correctly?

PROCESS(A, B)
BEGIN
    if A = '1' then
        C <= B;
    else
        C <= (others => 'Z');
    end if;
END PROCESS;

The answer is that in the above code, we are not trying to implement a sequential circuit, but a combinatorial circuit. On the simulation level, any change in A or B will trigger the PROCESS. And on synthesis level, the circuit is implemented using a LUT(look up table) rather than flipflops. 

Sequential circuits are edge triggered while combinatorial circuits are level triggered. And most of the fpga doesnt have flipflops which can be triggered on both edges of a clock.

3 comments:

  1. ok but what about:

    bla : PROCESS(A, B)
    BEGIN
    if A = '1' then
    C <= B;
    else
    C <= (others => 'Z');
    end if;
    END PROCESS;

    that synthesizes fine for me

    ReplyDelete
    Replies
    1. this will work fine because you havnt used it as a clock. you are not doing edge detection here. but only level detection of A and B.

      Delete
  2. actually in spartan and virtex series board do not have dual edge sensitive flipflop. Once hardware is unavailable how could u implement it. But I got an information that in cool runner series board u can implement this logic.
    But u can consider two separate process where one is rising edge sensitive and other one is negative edge sensitive

    ReplyDelete