Reputation: 155
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;
Upvotes: 2
Views: 4875
Reputation:
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:
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:
Using while loops with signal iterators is a bit tougher than using for loops with variable iterators.
Upvotes: 1
Reputation: 7099
There are two issues in your code: first, X <= X3 & X2 & X1 & X0;
concatenates X3
to X0
and assigns the result to X
. In the process tb
, you're again assigning to X
, creating what is usually referred to as "multiple drivers", ie. multiple parts of code driving (possibly different) values to the same signal. This is rarely what you want in well-written VHDL code.
VHDL deals with multiple drivers by using a resolution function: a function is applied to all values driven to the signal and its output is then written to the signal; see this for the resolution table that is used.
I'd stronly advice against using resolved types such as std_logic
or std_logic_vector
and go for their unresolved pendants std_ulogic
and std_ulogic_vector
(note the u
); if you had used those, your error would have been caught during elaboration.
Second, as mentioned in the comments, X3
to X0
are never assigned any values, leaving them as U
.
Upvotes: 0