-1

I'm going straight to specifics.

I'm using Ubuntu 14.04LTS, GHDL compiler and GTKWave for simulation.

I have two files for simulating a simple 2-multiplexer: mux2.vhd and mux2_testbench.vhd

This is the code for mux2.vhd

-- Libraries

library ieee;
use ieee.std_logic_1164.all;


-- Entity declaration

entity mux2 is

    port(
        e0, e1 : in std_logic;
        c : in std_logic;
        output : out std_logic
    );

end mux2;


-- Architecture declaration

architecture mux2_arch of mux2 is

    begin
    process (e0, e1, c)

        begin
        if c = '0' then
            output <= e0;
        else
            output <= e1;
        end if;
    end process;
end mux2_arch;

Code for the testbench

--Libraries

library ieee;
use ieee.std_logic_1164.all;

--Empty entity for simulation

entity mux2_testbench is
end mux2_testbench;

architecture testbench_arch of mux2_testbench is
    component test is
        port(
            c : in std_logic;
            e0, e1 : in std_logic;
            output : out std_logic
        );
    end component;

    signal c: std_logic;
    constant clk: time:=50 ns;
    signal e0: std_logic;
    signal e1: std_logic;
    signal output: std_logic;

    begin
        lab: test
        port map(
            c => c,
            e0 => e0,
            e1 => e1,
            output => output
        );



        process
        begin

            --Case 1: Control signal is low
            c <= '0';

            e0 <= '0';
            e1 <= '0';
            wait for 100 ns;
            e0 <= '0';
            e0 <= '1';
            wait for 100 ns;
            e0 <= '1';
            e0 <= '0';
            wait for 100 ns;
            e0 <= '1';
            e0 <= '1';
            wait for 100 ns;

            --Case 2: Control signal is high
            c <= '1';

            e0 <= '0';
            e1 <= '0';
            wait for 100 ns;
            e0 <= '0';
            e0 <= '1';
            wait for 100 ns;
            e0 <= '1';
            e0 <= '0';
            wait for 100 ns;
            e0 <= '1';
            e0 <= '1';
        end process;

end testbench_arch;

Things I'm doing:

I'm compiling via terminal without errors with: ghdl -a mux2.vhd and ghdl -a mux2_testbench.vhd

Then, I create the executable for the testbench: ghdl -e mux2_testbench

Finally, I create the vcd file I need to use gtkwave: ghdl -r mux2_testbench --vcd=test.vcd &

Simulation: gtkwave test.vcd

I have two problems with this code: 1. Even though I'm writing different values in signals e0 and e1, e1 shows nothing in the simulation. It's always '0'.

  1. Output signal shows value "U" in the simulation, I'm not even sure what this means and wasn't able to find anything clear in Google.

Thank you all in advance, pals.

Matthew Taylor
  • 13,365
  • 3
  • 17
  • 44
RbeJG
  • 1
  • 3
  • 2
    Which line writes anything other than '0' to e1? None that I can see ... is there a copy/paste error? Also, I see no entity/arch for component "test". –  Mar 25 '16 at 21:22
  • Please format your code. – Paebbels Mar 25 '16 at 23:16

2 Answers2

1

In keeping with Brian's comment I added a configuration specification to use mux2 instead of test in the testbench:

architecture testbench_arch of mux2_testbench is
    component test is
        port (
            c:       in  std_logic;
            e0, e1:  in  std_logic;
            output:  out std_logic
        );
    end component;

    signal c:       std_logic;
    constant clk:   time := 50 ns;
    signal e0:      std_logic;
    signal e1:      std_logic;
    signal output:  std_logic;

    for lab: test use entity work.mux2; -- added

begin
lab: 
    test
        port map (
            c => c,
            e0 => e0,
            e1 => e1,
            output => output
        );

    process
    begin

        --Case 1: Control signal is low
        c <= '0';

        e0 <= '0';
        e1 <= '0';
        wait for 100 ns;
        e0 <= '0';
        e0 <= '1';
        wait for 100 ns;
        e0 <= '1';
        e0 <= '0';
        wait for 100 ns;
        e0 <= '1';
        e0 <= '1';
        wait for 100 ns;

        --Case 2: Control signal is high
        c <= '1';

        e0 <= '0';
        e1 <= '0';
        wait for 100 ns;
        e0 <= '0';
        e0 <= '1';
        wait for 100 ns;
        e0 <= '1';
        e0 <= '0';
        wait for 100 ns;
        e0 <= '1';
        e0 <= '1';
        wait for 100 ns;  -- added to terminate the simulation
        wait;             -- added ""
    end process;

end architecture testbench_arch;

I also added the two wait statements so the simulation would terminate without adding a --stop-time=somvalue flag while using --wave=testbench.ghw instead of --vcd=test.vcd.

(Gtkwave also accepts the GHW dump file format which is unique to ghdl, it's a compressed format and no as amenable to being CTL-C'd to stop a simulation that would otherwise loop continuously).

This gives:

mux2_testbench.png

Note that in deference to Matthew's answer with e1 always low, you can still distinguish which input shows up on output, demonstrating c provides it's selection function.

The 'U' would have shown up because component test was unbound an entity test not being found in the working library.

The binding indication in the above example is done by the configuration specification. See IEEE Std 1076-2008 7.3 Configuration specification and 7.3.2 Binding indication.

You could also use direct entity instantiation as Matthew advocates or by using a configuration declaration containing a binding indication leave the test component instantiation as is.

The ability to reuse the testbench would be limited by the stimuli patterns for inputs to the unit under test (lab).

0

Firstly, 'U' is the default value for type std_logic. It means uninitialised. Any signal that has not been assigned to or is not driven will have the value 'U'. I think it is highly likely that your outputs are not driven, because you have instantiated a component called test yet your device under test entity is called mux2. I recommend changing the name of your component to mux2, then the default binding rules will enable your entity mux2 to be bound to the component mux2:

component mux2 is 
  port( c : in std_logic; 
        e0, e1 : in std_logic; 
        output : out std_logic );
end component;

and

    -- this is component instantiation
    lab: mux2
    port map(
        c => c,
        e0 => e0,
        e1 => e1,
        output => output
    );

So, the entity mux2 is not being bound to the component test. Think of a component as being like an IC socket; think of an entity as being like the IC that goes in the socket. If your component is called test and your entity is called mux2, how does the simulator know to bind (i.e. connect) the two together? You could write what is called a configuration to do this binding, but it would be much easier to change the component name to mux2, then this will happen automatically.

(Or better still, why use component instantiation at all? Why bother with the component? Why not use direct instantiation instead?)

    -- this is direct instantiation
    lab: entity work.mux2
    port map(
        c => c,
        e0 => e0,
        e1 => e1,
        output => output
    );

Secondly, it seems clear that you are not driving e1. Surely lines like this:

    e0 <= '0';
    e0 <= '1';

should be

    e0 <= '0';
    e1 <= '1';
--   ^
--   |
Matthew Taylor
  • 13,365
  • 3
  • 17
  • 44