VHDL coding tips and tricks: Be careful when using functions in your code.

Wednesday, February 16, 2011

Be careful when using functions in your code.

There are many coding styles in VHDL where the code which work well in the simulation will not work on the actual fpga. In this article I am going to talk about one such RTL coding style.

As you know VHDL programmers normally use functions to represent combinational logic. But using functions every where without much thinking may result in dangerous bugs in the code. One perfect example is a function which replaces the code for a latch.

See the below code, which doesn't use a function:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity test is
port(   en1,a,Clk : in std_logic;                    
      output : out std_logic );
end test;

architecture BEHAVIORAL of test is

begin

process(Clk)
begin    
    if ( rising_edge(Clk) ) then      
        if(en1 = '1') then
            output <= a;
        end if;
   end if;
end process;

end BEHAVIORAL;

In the above code, whenever signal en1 goes high, at the positive edge of Clk we assign a to output port. We don't specify what will happen when the value of en1 is '0'. So basically the code results in a latch.
When synthesised, XST(Xilinx synthesis tool) uses a FDE flip flop for implementing the code. If you check the link pointed by FDE, you can see the truth table of FDE flip flop. As expected, it works like a latch. Whenever CE is '0' the flip flop retains the previous output.

Now I am going re-write the above code using functions. I will replace some part of the combinational logic inside the process with a function. See the code below:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity test is
port(   en1,a,Clk : in std_logic;                    
      output : out std_logic );
end test;

architecture BEHAVIORAL of test is

function latch (en1,a : std_logic ) return std_logic is
variable output : std_logic := '0';
begin
    if(en1 = '1') then
        output := a;
    end if;
return output;
end latch; 

begin

process(Clk)
begin    
    if ( rising_edge(Clk) ) then      
        output <= latch(en1,a);
   end if;
end process;

end BEHAVIORAL;

At the first look the above code is same as the first code. To confirm both has the same functionality, I simulated them. The outputs are matching. So they indeed work the same way in the simulation. But wait a minute. How about the synthesis results?

I ran XST for the above code and checked the technology viewer to see the synthesised circuit. What I saw was, instead of a FDE flipflop, XST used a FDR flipflop this time. Go to the link pointed by FDR and check the truth table given there. You can see that its not a latch. When R is '1' the flipflop output is reset to '0' rather than maintaining the previous value. So both the codes are going to work differently on board.

How did this happen? This is because all functions are synthesised into pure combinational logic by the synthesis tool. This means that you cannot go on using functions every where you want without proper brain storming. If you do, then the pre and post synthesis results may vary.

Note:- Both the codes where simulated and synthesized using Xilinx Webpack 12.1. The results may a vary a little depending on the tool you are using.

3 comments:

  1. It happens because of this line:

    variable output : std_logic := '0';

    You've initialised the variable to '0' so it can;t latch. To build a functional latch, you'd have to pass the current output into the function and use it to initialise the output variable. But I don't see why that's so surprising to be honest?

    ReplyDelete
  2. @martin : Thanks for the comment.
    When you remove the initialization of the variable, inside the function the XST doesnt use en1 input at all. It just manages the implementation with a simple FD flipflop.

    what I wanted to say was that just replacing the combinational logic with a function may not work in certain cases.
    And as you said you have to feedback the output if you want to synthesis the latch, which was not an obvious fact to beginners in vhdl.
    Here is the code as per your suggestion for creating the latch using the function:

    architecture BEHAVIORAL of test is

    function latch (en1,a,o : std_logic ) return std_logic is
    variable output : std_logic := o;
    begin
    if(en1 = '1') then
    output := a;
    end if;
    return output;
    end latch;

    signal o : std_logic;

    begin

    output <= o;

    process(Clk)
    begin
    if ( rising_edge(Clk) ) then
    o <= latch(en1,a,o);
    end if;
    end process;

    end BEHAVIORAL;

    ReplyDelete
  3. Hi vipin,
    you were talking about coding style in VHDL. I am newbie in VHDL and I want to know, can you provide me a link regarding these coding styles ?

    Thanks,
    Rez

    ReplyDelete