Search code examples
vhdl

How to model two D flip-flops with multiplexing logic


I would like to model two D flip-flops using a multiplexer for some logic. I want to have static outputs of "000" for the three MSB when the multiplexer selects DFF D1 (B = 0) and the three LSB should be fixed to "111" when the multiplexer selects DFF D2 (B = 1).

This is my code -- which I originally typed blindly without checking for obvious syntax errors -- below. I don't know how to solve my problem:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dff_mux is
Port ( D1, D2 : in  STD_LOGIC_VECTOR(11 DOWNTO 0);
      clk : in  STD_LOGIC;
      rst : IN STD_LOGIC;
      B : in  STD_LOGIC;
  data  : out  STD_LOGIC_VECTOR(11 DOWNTO 0));
end dff_mux;

architecture Behavioral of dff_mux is

signal Q1, Q2 : std_logic_vector(11 downto 0);

begin

process(clk,rst)
begin
    if (rst = '1') then

        Q1<="000000000000";

    elsif (clk'event and clk='1') then

        if (B = '0') then

            -- I want to fix thee MSB to "000"
            -- other bits shall retain their input value
            D1(11) <= '0';
            D1(10) <= '0';
            D1(9) <= '0';
            Q1 <= D1;

        elsif (B = '1') then

            -- fix three LSB to "111"
            -- other bits retain their input value
            D2(2) <= '1';
            D2(1) <= '1';
            D2(0) <= '1';
            Q2 <= D2;

        end if;

    end if;

end process;

-- MUX description: select D1 when B = 0, else select D2 when B = 1

MUX : process(B)
begin

    data <= Q1 when (B = '0') else
            Q2;

end process MUX;

end Behavioral;

Thanks in advance to anybody who can help me.


Solution

  • There are numerous errors in your VHDL design description. The two process statements drive the same signals (Q1 and Q2). The second process has three errors (no process statement label, while a label is specified in closing, concurrent signal assignment statements where sequential signal assignment statements are appropriate). It would appear the second process statement should be eliminated in it's entirety.

    If the intent is to have a multiplexer on the inputs to the Q1,Q2 registers the first process is non-functional. You can't assign values to a formal input inside a block.

    You should be assigning the B selected values to Q1 and Q2 directly inside the process statement (inside the clk elsif).

    Your assignment to D(11) is defective (uses == instead of <=).

    It isn't a multiplexer if you only assign one value to a particular signal (e.g. longest static prefix D1 and D2). Note there is no reset value for Q2 provided.

    There is no place data is assigned.

    If you're doing this for class work there is little benefit in someone providing the answer without learning VHDL a bit more. If you're earnestly trying to learn VHDL you need more and incrementally building exercises.

    If I understand what you are trying to do correctly it would look something like this:

    architecture Behavioral of basculeD is
    -- signal Q1, Q2 : std_logic_vector(11 downto 0);
    begin
    
    -- process(clk,rst)
    -- begin
    -- if (rst='1') then Q1<="000000000000";
    -- elsif ( clk'event and clk='1') then
    -- if (B='0') then 
    -- D1(11) =='0'; -- i want to fix the 3MSB of D1 in the "000" ... 
    -- D1(10) <='0';
    -- D1(9) <='0';
    -- Q1<= D1;
    -- elsif  (B='1') then 
    -- D2(2)<= '1'; -- the 3LSB are fixed to 111 , and defaut value ... 
    -- D2(1)<='1';
    -- D2(0)<='1';
    -- Q2<=D2;
    -- end if; 
    -- end if;
    -- end process;
    
    -- description MUX : select D1 when B=0, else select D2 when B= 1  
    -- process( B)
    -- begin
    -- Q1 <= D1 when B='0' else 
    -- Q2<=D2 when B='1'  ;
    -- end process MUX;
    
    MUXED_REG:
        process (clk,rst)
        begin
            if rst = '1' then 
                data <= (others => '0'); -- equivalent to "000000000000"
            elsif clk'event and clk = '1' then
            -- the actual multiplexer:
                if B = '0' then
                    data <= ("000" & D1(8 downto 0));
                else  -- B = '1', or other values
                    data <= (D2(11 downto 3) & "111");
                end if;
            end if;
        end process;
    end Behavioral;
    

    You could of course retain an intermediary signal, say Q and use it in place of data above, with a concurrent signal assignment from Q to data (the output).

    Using the above architecture in place of your's analyzes.

    With a test bench:

    library ieee; 
    use ieee.std_logic_1164.all;
    
    entity basculeD_test is
    end entity;
    
    architecture test of basculeD_test is
        component basculeD is
            port ( 
                d1, d2:  in   std_logic_vector(11 downto 0);
                clk:     in   std_logic;
                rst:     in   std_logic;
                b:       in   std_logic;
                data:    out  std_logic_vector(11 downto 0)
            );
        end component;
    
        signal d1:      std_logic_vector(11 downto 0) := (others => '1');
        signal d2:      std_logic_vector(11 downto 0) := (others => '0');
        signal clk:     std_logic := '0';
        signal rst:     std_logic := '1';
        signal b:       std_logic := '0';
        signal data:    std_logic_vector(11 downto 0);
    
    begin
    
    CLOCK: 
        process
        begin
            wait for 10 ns;
            clk <= not clk;
            if Now > 100 ns then
                wait;
            end if;
        end process;
    
    RESET:
        process
        begin
            wait for 31 ns;
            rst <= '0';
            wait;
        end process;
    
    DUT:
        basculeD 
            port map (
                d1   => d1,
                d2   => d2,
                clk  => clk,
                rst  => rst,
                b    => b,
                data => data
            );
    
    STIMULUS:
        process
        begin
            wait for 65 ns;
            b <= '1';
            wait;
        end process;
    
    end architecture;
    

    And using the replacement architecture for basculeD with the MUXED_REG process:

    david_koontz@Macbook: ghdl -a basculeD.vhdl
    david_koontz@Macbook: ghdl -e basculeD_test
    david_koontz@Macbook: ghdl -r basculeD_test --wave=basculeD_test.ghw
    david_koontz@Macbook: open basculeD_test.gtkw (previously saved save file)

    Gives:

    Test bench execution of basculeD_test

    There's of course the possibility that you are trying to separate storage from multiplexing entirely, which says you could use Q1 and Q2 as registers (and only need 9 bits), a separate multiplexer (as implied in your original basculeD architecture) allowing B to steer between modified Q1 and Q2 register values on output data.

    That would look something like this:

    architecture Behavioral of basculeD is
        signal Q1:  std_logic_vector(8 downto 0);
        signal Q2:  std_logic_vector(11 downto 3);
    begin
    REGS:
    process (clk, rst)
    begin
        if rst = '1' then
            Q1 <= (others => '0');
            Q2 <= (others => '0');    
        elsif clk'event and clk = '1' then
            Q1 <= D1 (8 downto 0); 
            Q2 <= D2(11 downto 3);
        end if;
    end process;
    
    MUX:
    process (B,Q1,Q2)
    begin
        if B = '0' then
            data <= ("000" & Q1);
        else
            data <= (Q2 & "111");
        end if;
    end process;
    

    And give you something like this:

    basculeD_test with separate MUX

    VHDL is meant to convey a design specification to the reader, which is made easier when using some convention for capitalization (VHDL isn't case sensitive except in extended identifiers) and indentation.