Search code examples
vhdlmux

VHDL: muxes between 11 buses 8 bits wide output


i recieved this question as a pre interview question "Draw a diagram and write the VHDL code for a module that meets the following requirements: a. Fully synchronous. b. Muxes between 11 buses where each bus is 8-bits wide. c. Has 2 cycles of latency. d. Optimized for maximum clock frequency."

ive been trying to do it myself reading my old notes and assignments i have done in university but i just don't think i'm on the right track with this. i have the code soo far posted below:

 library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity Mux is
port(

 A:  in STD_LOGIC_vector(7 downto 0);
  B:  in STD_LOGIC_vector(7 downto 0);
  C:  in STD_LOGIC_vector(7 downto 0);
  D:  in STD_LOGIC_vector(7 downto 0);
  E:  in STD_LOGIC_vector(7 downto 0);
  F:  in STD_LOGIC_vector(7 downto 0);
  G:  in STD_LOGIC_vector(7 downto 0);
  H:  in STD_LOGIC_vector(7 downto 0);
  I:  in STD_LOGIC_vector(7 downto 0);
  J:  in STD_LOGIC_vector(7 downto 0);
  K:  in STD_LOGIC_vector(7 downto 0);
 S0: in std_LOGIC_vector(3 downto 0);

 Z: out STD_LOGIC_vector(7 downto 0)
);
 end Mux;
architecture func of Mux is
begin
process (A,B,C,D,E,F,G,H,I,J,K,S0)
begin

    if S0="0001" then
        Z<= A;
    elsif S0="0010" then
        Z<= B;
    elsif S0="0011" then
        Z<= C;
    elsif S0="0100" then
        Z<= D;
    elsif S0="0101" then
        Z<= E;
    elsif S0="0110" then
        Z<= F;
    elsif S0="0111" then
        Z<= G;
    elsif S0="1000" then
        Z<= H;
    elsif S0="1001" then
        Z<= I;
    elsif S0="1010" then
        Z<= J;
    elsif S0="1011" then
        Z<= K;  
    else 
        Z<=A;
    end if;


end process;
end func;

and this is the code i have for my second file:

 LIBRARY ieee;
 USE ieee.std_logic_1164.ALL;
 use IEEE.std_logic_arith.all;
 entity mux11test is
 end entity mux11test;
 architecture test of mux11test is
  signal    T_A:  STD_LOGIC_vector(7 downto 0):="00000001";
   signal    T_B:  STD_LOGIC_vector(7 downto 0):="00000010";
  signal    T_C:  STD_LOGIC_vector(7 downto 0):="00000011";
  signal    T_D:  STD_LOGIC_vector(7 downto 0):="00000100";
  signal    T_E:  STD_LOGIC_vector(7 downto 0):="00000101";
  signal    T_F:  STD_LOGIC_vector(7 downto 0):="00000110";
  signal    T_G:  STD_LOGIC_vector(7 downto 0):="00000111";
  signal    T_H:  STD_LOGIC_vector(7 downto 0):="00001000";
  signal    T_I:  STD_LOGIC_vector(7 downto 0):="00001001";
  signal    T_J:  STD_LOGIC_vector(7 downto 0):="00001010";
  signal    T_K:  STD_LOGIC_vector(7 downto 0):="00001011";

   signal    T_S: STD_LOGIC_vector( 3 downto 0);
 signal    T_Z:  STD_LOGIC_vector(7 downto 0);

component mux11 IS
port(

 A:  in STD_LOGIC_vector(7 downto 0);
  B:  in STD_LOGIC_vector(7 downto 0);
  C:  in STD_LOGIC_vector(7 downto 0);
  D:  in STD_LOGIC_vector(7 downto 0);
  E:  in STD_LOGIC_vector(7 downto 0);
  F:  in STD_LOGIC_vector(7 downto 0);
  G:  in STD_LOGIC_vector(7 downto 0);
  H:  in STD_LOGIC_vector(7 downto 0);
  I:  in STD_LOGIC_vector(7 downto 0);
  J:  in STD_LOGIC_vector(7 downto 0);
  K:  in STD_LOGIC_vector(7 downto 0);
 S0: in std_LOGIC_vector(3 downto 0);

 Z:  out STD_LOGIC_vector(7 downto 0)
  ); 
END COMPONENT ;
signal clk : std_LOGIC;
constant clk_period: time:=100ns;
begin

umux: Mux11 port map(T_A,T_B,T_C,T_D,T_E,T_F,T_G,T_H,T_I,T_J,T_K,T_S,T_Z);
clk_process:process 
begin
clk<='0';
wait for clk_period/2;
clk <='1';
wait for clk_period/2;
end process;
PROCESS
begin
if T_S="0001" then
    T_Z <= T_A ;
elsif  T_S="0010" then  
T_Z <= T_B ; wait for 100 ns; 
elsif  T_S="0011" then
T_Z <= T_C ; wait for 100 ns; 
elsif  T_S="0100" then
T_Z  <= T_D ; wait for 100 ns;
elsif  T_S="0101" then
T_Z  <=T_E ; wait for 100 ns;
elsif  T_S="0110" then
T_Z <=  T_F ; wait for 100 ns;
    elsif  T_S="0111" then
T_Z  <= T_G ; wait for 100 ns;
    elsif  T_S="1000" then
T_Z  <= T_H ; wait for 100 ns;
elsif  T_S="1001" then
T_Z  <= T_I ; wait for 100 ns;
elsif  T_S="1010" then
T_Z  <= T_J ; wait for 100 ns;
elsif  T_S="1011" then
T_Z <= T_K ; wait for 100 ns;


wait;

end if;
end PROCESS;

end architecture test;

is there anyone who could tell me if im on the right path and if this is fully synchronous and how would i start implementing or determining 2 cycles of latency?


Solution

  • I try to write a clear answer to help you.

    First of all you need a clock in your design let's call it clk.

    entity Mux is
    port(
    
      clk: in std_logic;
      A:  in STD_LOGIC_vector(7 downto 0);
      B:  in STD_LOGIC_vector(7 downto 0);
      C:  in STD_LOGIC_vector(7 downto 0);
      D:  in STD_LOGIC_vector(7 downto 0);
      E:  in STD_LOGIC_vector(7 downto 0);
      F:  in STD_LOGIC_vector(7 downto 0);
      G:  in STD_LOGIC_vector(7 downto 0);
      H:  in STD_LOGIC_vector(7 downto 0);
      I:  in STD_LOGIC_vector(7 downto 0);
      J:  in STD_LOGIC_vector(7 downto 0);
      K:  in STD_LOGIC_vector(7 downto 0);
      S0: in std_LOGIC_vector(3 downto 0);
    
      Z: out STD_LOGIC_vector(7 downto 0));
    
    end Mux;
    

    The idea when you use synchronous processes is to always update your values on an edge of your clock. Let's say the rising edge. Thus your processes have to be only sensitive to your input clk.

    P : PROCESS (clk)
    BEGIN
       IF (rising_edge(clk)) THEN
         ...
       END IF;
    END PROCESS;
    

    Concerning your multiplexer, your idea was good. Yet I would suggest to use a CASE statement because it is easier to read than IF ELSIF.

    CASE S0 IS
        WHEN "0001"  => Z <= A;
        WHEN "0010"  => Z <= B;
        ...
        WHEN "1011"  => Z <= K;
    END CASE;
    

    EDIT : since I forgot to talk about the 2 cycles latency I'll say two words. There you need two intermediate signals (ie Z_i and Z_ii). Z_ii takes Z_i after one clock cycle and Z takes Z_ii after one clock cycle.

    Z_ii <= Z_i;
    Z    <= Z_ii;
    

    Of course you then need to drive Z_i (and not Z) in you process.