vhdl program not swapping integers

322 views Asked by At

The VHDL code below is a simple swap program. But it is not swapping the inputs a and b. I have given the transcript values in the comments.

library ieee;
use ieee.std_logic_1164.all;

entity vhdl_swap is
  port(a,b: inout integer);
end vhdl_swap;

architecture ar of vhdl_swap is
  signal s : std_logic;
begin

  process(s)
    variable var : integer:=0;
  begin
    report "var is" & integer'image(var); -- 0
    report "a is " & integer'image(a);    -- 10 - (given value when simulated)
    report "b is " & integer'image(b);  -- 20 - (given value when simulated)

    report "---------------------------";

    var := a;
    report "var is " & integer'image(var);--var = 10 (assigned properly)
    a<=b;
    report "a is " & integer'image(a);-- a=10(same value but not assigned)
    b<=var;
    report "b is " & integer'image(b);-- b=20(same value but not assigned)

    report "-----------------------------------";

    report "a is " & integer'image(a);--a=10
    report "b is " & integer'image(b);--b=20

    --print()  

  end process;
end;

There is something which acts in the statement a<=b, but i don't know what prevents itself from assigning it.

2

There are 2 answers

0
Morten Zilmer On

The new value assigned with VHDL <= is not available for read until an delta delay has passed.

This is a fundamental property of VHDL, since it reflects the way register update works then the signal that triggers the update is a clock.

This also means that you can actually do the swap without a variable, but simply doing:

a <= b;
b <= a;

There are other issues with the code, e.g. what is the s used for, using a and b for both input and output will give a drive conflict, unless resolution function is added.

4
Martin Zabel On

If you assign a new value to a signal in VHDL with <= without giving an explicit delay (with after <time>), then the new signal value will be available in the next delta cycle. A new delta cycle starts, when the simulator has suspended all processes which have been scheduled for the current delta cycle. And a process is suspended at a wait statement. Your process has an implicit wait on S; statement at the end, because you described a process with a sensitivity list containing S. You assigned the inout ports a and b here which behave the same as a signal.

Because, the signal update is visible not until the next delta cycle, all your report statements print out the same value for a and b respectively. That is, they print out the values of a and b when the process has started / resumed.

Assigning a signal is different to assigning a variable, e.g. var in your code, which gets updated immediately.

Your process is executed only once, because the signal S is not changed. Every process is executed once after the simulation starts and then suspended at the wait statement (the implicit one in your code as described above).

You said, that a and b have the initial value of 10 and 20, respectively, but I couldn't reproduce this with ModelSim nor GHDL. I tried it with the following testbench which I think is the only possible way:

library ieee;
use ieee.std_logic_1164.all;

entity vhdl_swap_tb is
end entity vhdl_swap_tb;

architecture sim of vhdl_swap_tb is
  -- component ports
  signal a : integer := 10;
  signal b : integer := 20;
begin  -- architecture sim

  -- component instantiation
  DUT: entity work.vhdl_swap
    port map (
      a => a,
      b => b);

end architecture sim;

I had to use initial values for a and b here, because both ports of mode inout and of an unresolved type. Thus, I cannot add a second driver by assigning a and b in another testbench process.


Because, the signal updates are delayed (at least) until the next delta cycle, you do not need an extra variable. Here is a very short example code demonstrating the swapping of two signals:

library ieee;
use ieee.std_logic_1164.all;

entity swap is
end entity swap;

architecture sim of swap is
  signal a     : integer   := 10;
  signal b     : integer   := 20;
  signal clock : std_logic := '1';
begin

  -- clock generation
  clock <= not clock after 10 ns;

  -- swapping
  process(clock)
  begin
    if rising_edge(clock) then
      a <= b;
      b <= a;
    end if;
  end process;
end sim;

The swapping is done at every rising edge of the clock, as can be seen in the following waveform:

simulation output