1
\$\begingroup\$

I'm implementing a simple adder with carry out in VHDL on a BASYS2 board.

This is the code below:

entity adder is
    port (
        a, b        : in std_logic_vector(3 downto 0);
        sum     : out std_logic_vector(3 downto 0);
        cout        : out std_logic;
        kopce       : in std_logic;
        ledica  : buffer std_logic
    );
end adder;

architecture sobirac of adder is

signal tmp : signed(4 downto 0);

begin
    process(kopce)
    begin
        if(rising_edge(kopce)) then

            ledica <= (not ledica);

            tmp <= signed(("0" & a)) + signed(("0" & b));
            --sum <= std_logic_vector(tmp(3 downto 0));

            sum(3) <= std_logic(tmp(3));
            sum(2) <= std_logic(tmp(2));
            sum(1) <= std_logic(tmp(1));
            sum(0) <= std_logic(tmp(0));

            cout <= tmp(4);
        end if;
    end process;

end sobirac;

The "problem" is that I need to push the button two times in order for it to generate an output which I'm displaying on the onboard LEDs, why does it behave like this ? If I remove the process statement, and make it concurrent, it works in the instant I give it an input (2x4 switches).

Regards, Aleks

\$\endgroup\$
  • \$\begingroup\$ (Disclaimer : Noob here )---AFAIK signal assignments generally take place AFTER the current iteration of the process rather than IN the process (which has effect on the speed ). If you want the result immediately, use Variable. So for your case, tmp is declared signal. Just change it to variable and put the declaration and initialisation inside the process. (Again, it's a guess) \$\endgroup\$ – Plutonium smuggler Nov 21 '14 at 3:58
1
\$\begingroup\$

The <= assignment in the process is done in a special way. First all of the right side statements are evaluated, and then all of the left side signals are assigned. In your case, first the std_logic(tmp(n)); parts are evaluated with the 'old' value of tmp, and only then tmp and sum values are assigned.

\$\endgroup\$
0
\$\begingroup\$

See this answer describing the VHDL Simulation Cycle

In your case it means you can't evaluate an expression comprised of a signal assigned in the current simulation cycle. It's scheduled to take effect at some point in the simulation time future. This includes an assignment without a delay.

Your code sample has defined four registers. ledica, tmp, sum and cout.

To remove a delay on the sum you could move the assignment for to outside the clock edge evaluate portion of the process (which requires adding a, b, and tmp to the sensitivity list) or make them concurrent assignment statements:

architecture foo of adder is
    signal tmp : signed(4 downto 0);
begin
    process(kopce)
    begin
        if rising_edge(kopce) then
            ledica <= not ledica;  
            sum    <= std_logic_vector(tmp(3 downto 0)); 
            cout   <= tmp(4);
        end if;
    end process;

    tmp <= signed("0" & a) + signed ("0" & b);

end architecture;

Because there's nothing between tmp and sum and cout there's no reason to use a pipeline register for tmp.

Depending on the package providing signed adding operators the concatenation with b may not necessary. Some "+" operators take the result length from the left argument.

(I got rid of a lot of the superfluous parentheses pairs, I couldn't help myself).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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