I am working on a code convertor using multiplexors and I am facing issues when testing it on ModelSim. Basically it outputs X where there should output 1.
I found out that the error may be where I put others >= '0' as when I changed it to 1; the opposite occurred where the X appeared where there should be a 0.
Here's my code:
use IEEE.std_logic_1164.all;
entity mux8x1 is
port( s : in std_logic_vector(2 downto 0);
i : in std_logic_vector(7 downto 0);
m2b:out std_logic);
end;
architecture behave of mux8x1 is
begin
m2b <= i(0) when s="000" else
i(1) when s="001" else
i(2) when s="010" else
i(3) when s="011" else
i(4) when s="100" else
i(5) when s="101" else
i(6) when s="110" else
i(7);
end;
and
use IEEE.std_logic_1164.all;
entity mux_example is
port( A : in std_logic;
B : in std_logic;
C : in std_logic;
D : in std_logic;
W : out std_logic;
X : out std_logic;
Y : out std_logic;
Z : out std_logic);
end;
architecture struct of mux_example is
begin
-- Mux instantiations
mux1: entity work.mux8x1
port map (
s => "000",
i => (others => '0'),
m2b => W
);
mux2: entity work.mux8x1
port map (
s => "001",
i => (others => '0'),
m2b => X
);
mux3: entity work.mux8x1
port map (
s => "011",
i => (others => '0'),
m2b => Y
);
mux4: entity work.mux8x1
port map (
s => "100",
i => (others => '0'),
m2b => Z
);
-- Combinatorial logic
W <= (A and not B and C) or
(A and C and not D) or
(A and B and not C and D) or
(not A and B and C and D) or
(not A and not B and not C and D);
X <= (B and not C and not D) or
(not B and not C and D) or
(not A and B and C) or
(not B and C and not D);
Y <= (A and B and not C) or
(not C and D) or
(not A and D);
Z <= (not A and not B and D) or
(B and not D);
end architecture;
The
'X'value ofstd_logicmeans "unknown," and it arises in simulation when there's a tug-of-war between multiple drivers of a singlestd_logicsignal driving conflicting values, i.e. one concurrent assignment is driving'0'at the same time another is driving'1'. This is what's happening in your code - let's consider just one mux:So you have two drivers driving values to
Wbecause you have two concurrent statements that assign values to it. For astd_logictype, since it is a resolved type, this will trigger your simulator to use the resolution function to settle on a value. Thus:If the logic for the second assignment to
Wyields'0', then the drivers agree and the resolution is simply'0'.If the logic for the second assignment to
Wyields'1', then the simulator has no reason to choose one driver over the other, so the conflict resolves to'X'- unknown.When you flipped the value of the
othersassignment, this is why it flipped to'X'where you expect'0'- it's the same process but with the logic inverted.This answers the question you raise in the title - why you're seeing
'X'instead of what you expect - but, as others have pointed out, your inputsA,B,C, andDare doing nothing so far as your muxes are concerned, and the muxes themselves, I assume for the sake of example to reproduce the unknown driver resolution, are not doing anything functional. You need to decide whether you want the combinatorial logic or the mux drivingWand the other outputs, but that's a separate design consideration.One practice you might consider is using
std_ulogicrather thanstd_logicfor wires that are not intentionally driven by multiple sources. Becausestd_ulogicis unresolved (hence the "u"), the compiler will throw an error rather than use a resolution function to handle the drivers.Another point to consider is that your architecture
structisn't purely structural, as you've mixed behavioral logic with your instantiations. Some designers prefer to avoid mixed architectures, both for readability and modularity considerations and to avoid potential pitfalls like this one.