vhdldecoder

Simultaneous activation of two outputs in the 3 to 8 decoder


I'm trying to build a Decoder3to8 using A Decoder2to4 using Vhdl. i have the following code for Decoder2to4

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Decoder2to4 is
Port( 
    A0, A1: in STD_LOGIC; 
    y0, y1, y2, y3: out STD_LOGIC
);
end Decoder2to4;

architecture Behavioral of Decoder2to4 is
begin
y0 <= not A0 and not A1;
y1 <= not A0 and A1;
y2 <= A0 and not A1;
y3 <= A0 and A1;
end Behavioral;

and this is the code for my Decoder3to8:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Decoder3to8 is
Port( 
    A0, A1, A2: in STD_LOGIC; 
    Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7: out STD_LOGIC
);
end Decoder3to8;

architecture Behavioral of Decoder3to8 is
component Decoder2to4 is
    Port( 
        A0, A1: in STD_LOGIC; 
        y0, y1, y2, y3: out STD_LOGIC
    );
end component;

signal B0, B1, B2, B3: std_logic;
begin
B0 <= (not A2) and A0;
B1 <= (not A2) and A1;
B2 <= A2 and A0; 
B3 <= A2 and A1;

Decoder2to4_0: Decoder2to4 port map (B0, B1, Y0, Y1, Y2, Y3);
Decoder2to4_1: Decoder2to4 port map (B2, B3, Y4, Y5, Y6, Y7);

end Behavioral;

The problem is when i give 0 as input to A0, A1 and A2, Y0 and Y4 become enabled. i think there is some problem with how i connect the signals but i can't see the problem.

Update 1: I checked the inputs and found that it doesn't matter what value A1 and A2 are, in any case as long as A2 is equal to 0, Y4 will turn on and when A2 is equal to 0, Y0 will turn on.


Solution

  • If I understand correctly, your Decoder2to4 is a one-hot encoder with this behavior:

    enter image description here

    And now you want to extend your implementation to support a 3-bit input:

    enter image description here

    You mention you are trying to do this using two instances of Decoder2to4. If you absolutely must use Decoder2to4 to construct your Decoder3to8, then I think the key step is to note that the truth table of Decoder3to8 contains two copies of Decoder2to4's truth table, and the rest is all zeros:

    enter image description here

    To implement this in VHDL, my first tip would be to reverse the indexing in Decoder2to4. It is conventional to treat the lowest index (0) as the least significant bit, in which case the A* indexes in Decoder2to4 should be swapped like this:

        y0 <= not A1 and not A0;
        y1 <= not A1 and A0;
        y2 <= A1 and not A0;
        y3 <= A1 and A0;
    

    After that, you could replace the architecture statement area of Decoder3to8 with this:

        Decoder2to4_0 : entity work.Decoder2to4 port map (A0, A1, B0, B1, B2, B3);
        
        Y0 <= B0 when A2 = '0' else '0';
        Y1 <= B1 when A2 = '0' else '0';
        Y2 <= B2 when A2 = '0' else '0';
        Y3 <= B3 when A2 = '0' else '0';
        
        Y4 <= '0' when A2 = '0' else B0;
        Y5 <= '0' when A2 = '0' else B1;
        Y6 <= '0' when A2 = '0' else B2;
        Y7 <= '0' when A2 = '0' else B3;
    

    And that will implement the truth table above.

    However, if it is not absolutely necessary to use Decoder2to4, then I would recommend a more generic approach. For example, you could generalize your implementation to support any input width by using standard array types like this:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity decoder is
    generic(
        INPUT_WIDTH : POSITIVE
    );
    port( 
        A : in UNSIGNED(INPUT_WIDTH-1 downto 0);
        Y : out STD_LOGIC_VECTOR(2**INPUT_WIDTH-1 downto 0)
    );
    end decoder;
    
    architecture behavioral of decoder is
    begin
    
        process(A)
        begin
            Y <= (others => '0');
            Y(to_integer(A)) <= '1';
        end process;
    
    end behavioral;
    

    If you want to verify that this works correctly with an input width of 3, here is a minimal testbench:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity tb is
    end tb;
    
    architecture sim of tb is
        constant INPUT_WIDTH    : positive := 3;
        
        signal A    : unsigned(INPUT_WIDTH-1 downto 0);
        signal Y    : std_logic_vector(2**INPUT_WIDTH-1 downto 0);
    begin
        
        -- Generate input
        process
        begin
            for i in 0 to 2**INPUT_WIDTH-1 loop
                A <= to_unsigned(i, INPUT_WIDTH);
                wait for 10 ns;
            end loop;
            
            A <= (others => 'X');
            wait;
        end process;
        
        -- Unit under test
        uut : entity work.decoder
        generic map(
            INPUT_WIDTH => INPUT_WIDTH
        )
        port map( 
            A => A,
            Y => Y
        );
        
    end sim;