Search code examples
vectorlogicvhdl

Concatenating STD_LOGIC to STD_LOGIC_VECTOR within testbench in VHDL


enter image description here

This is my simple Schematic of 4 to 1 MUX. and I have trouble with concatenating LOGIC to LOGIC_VECTOR...

here is my testbench code. I just want to show performance of MUX for all possible inputs. It is compiled well, but it isn't working as I expected. I guess newly declared vector "X" and "I" isn't linked with real inputs of Schematic

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
LIBRARY UNISIM;
USE UNISIM.Vcomponents.ALL;
ENTITY MUX_SCHE_MUX_SCHE_sch_tb IS
END MUX_SCHE_MUX_SCHE_sch_tb;
ARCHITECTURE behavioral OF MUX_SCHE_MUX_SCHE_sch_tb IS 

   COMPONENT MUX_SCHE
   PORT( X3 :   IN  STD_LOGIC; 
          X2    :   IN  STD_LOGIC; 
          X1    :   IN  STD_LOGIC; 
          X0    :   IN  STD_LOGIC; 
          I0    :   IN  STD_LOGIC; 
          I1    :   IN  STD_LOGIC; 
          Y :   OUT STD_LOGIC);
   END COMPONENT;

   SIGNAL X3    :   STD_LOGIC := '0';
   SIGNAL X2    :   STD_LOGIC := '0';
   SIGNAL X1    :   STD_LOGIC := '0';
   SIGNAL X0    :   STD_LOGIC := '0';
   SIGNAL I0    :   STD_LOGIC := '0';
   SIGNAL I1    :   STD_LOGIC := '0';
   SIGNAL Y : STD_LOGIC;

    ---------- New Variable ----------
    SIGNAL X : STD_LOGIC_VECTOR(3 downto 0);
    SIGNAL I : STD_LOGIC_VECTOR(1 downto 0);
    SIGNAL j : integer := 0;
    SIGNAL k : integer := 0;

BEGIN

    X <= X3 & X2 & X1 & X0;
    I <= I1 & I0;
    UUT: MUX_SCHE PORT MAP(
        X3 => X3, 
        X2 => X2, 
        X1 => X1, 
        X0 => X0, 
        I0 => I0, 
        I1 => I1, 
        Y => Y
   );

-- *** Test Bench - User Defined Section ***
   tb : PROCESS
   BEGIN
    X <= "0000";
    I <= "00";
        while(j<4) loop
            while(k<8) loop
                X <= X + '1'; WAIT FOR 10 NS;
            end loop;
            I <= I + '1'; WAIT FOR 10 NS;
       end loop;

   END PROCESS;
-- *** End Test Bench - User Defined Section ***

END;

Solution

  • As Brian notes the assignments to X (and I) are incorrect.

    There's also the case that X is always all 'X's, there are two drivers. The concurrent signal assignment to X and the assignments in the unlabeled process. Further the unlabeled process would unsuccessfully initializes X because there is no intervening suspension of the process between the first assignment to "0000" and the first assignment in the inner while loop.

    You could also note there is no assignment to j and k meaning you'll never finish the inner while loop and provide a different value of I.

    Overcoming the problems in the present testbench can also involve simplification:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity mux_sche_tb is
    end entity mux_sche_tb;
    
    architecture foo of mux_sche_tb is 
        use ieee.numeric_std.all;
        component mux_sche
            port ( 
               x3:   in  std_logic; 
               x2:   in  std_logic; 
               x1:   in  std_logic; 
               x0:   in  std_logic; 
               i0:   in  std_logic; 
               i1:   in  std_logic; 
               y:    out std_logic
            );
        end component;
    
       -- signal x3:       std_logic := '0';
       -- signal x2:       std_logic := '0';
       -- signal x1:       std_logic := '0';
       -- signal x0:       std_logic := '0';
       -- signal i0:       std_logic := '0';
       -- signal i1:       std_logic := '0';
        signal y:  std_logic;
    
        -- ---------- new variable ----------
        signal x:  unsigned(3 downto 0);
        signal i:  unsigned(1 downto 0);
        -- signal j:  integer := 0;
        -- signal k:  integer := 0;
    
    begin
    
        -- x <= x3 & x2 & x1 & x0;
        -- i <= i1 & i0;
    
    uut: 
        mux_sche 
            port map (
                x3 => x(3), 
                x2 => x(2), 
                x1 => x(1), 
                x0 => x(0), 
                i0 => i(0), 
                i1 => i(1), 
                y => y
            );
    
    tb:  
       process
       begin
        -- x <= "0000";
        -- i <= "00";
            wait for 10 ns; -- show initial state
            for j in 0 to 3 loop
                I <= to_unsigned(j, 2);
                for k in 0 to 15 loop
                    X <= to_unsigned(k, 4);
                    wait for 10 ns;
                end loop;
            end loop;
            wait;
           --  while(j < 4) loop
           --      while(k < 8) loop
           --          x <= x + '1';
           --          wait for 10 ns;
           --      end loop;
           --      i <= i + '1';
           --      wait for 10 ns;
           -- end loop;
    
       end process;
    end architecture;
    

    Instead of while loops for iteration schemes are used in loop statements. Brian's suggestion of assigning elements of X are extended to I and only a single assignment to either is provided eliminating multiple drivers.

    The use clause making the declarations in package ieee.numeric_std visible is moved to the architecture allowing the original architecture to be analyzed (and it's use clause allowing declarations found in the Synopsys package ieee.std_logic_unsigned is moved to it's architecture declarative region).

    The for loop iterators are variables implicitly declared in the loop statement iteration scheme and are converted from their default type of integer to unsigned X and I.

    The unsigned X and I have elements that have the same base type as the std_logic formal ports for mux_sche and can be used as actuals (as Brian recommends).

    To provide a Minimal, Complete and Verifiable example a compatible mux_sche must be provided:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity mux_sche is
        port (
            X3: in  std_logic;
            X2: in  std_logic;
            X1: in  std_logic;
            X0: in  std_logic;
            I0: in  std_logic;
            I1: in  std_logic;
            Y:  out std_logic
        );
    end entity;
    
    architecture foo of mux_sche is
    
    begin
        process (X3, X2, X1, X0, I0, I1)
        variable I: std_logic_vector (1 downto 0);
        begin
            I := TO_X01(I1 & I0);
            case I is
                when "00" =>
                    Y <= TO_X01(X0);
                when "01" =>
                    Y <= TO_X01(X1);
                when "10" =>
                    Y <= TO_X01(X2);
                when "11" =>
                    Y <= TO_X01(X3);
                when others =>
                    Y <= 'X';
            end case;
        end process;
    end architecture;
    

    When that's analyzed before the testbench and the testbench is analyzed, elaborated and simulated we end up with:

    changed.png

    Showing no X's and incremented X and I.

    This testbench version relies on the numeric_std package to_unsigned conversion from natural range integers noting X and I have the range specified in the loop iteration scheme implicit declarations.

    Is it possible to use the original testbench? Not with the threshold tests for j and k in place. What will occur is k will go through 8 iterations followed by j going through 4 iterations:

    enter image description here

    Using while loops with signal iterators is a bit tougher than using for loops with variable iterators.