Search code examples
vhdlhdl

How to choose one of top architectures in VHDL (from one file)?


I've got 3 main architectures for vhdl top in conf_gate.vhd. In each of architecture I want to choose one of two architecture of instantion (depends on value of constant). Can I choose one of architecture by using configure keywords from the same top (conf_gate.vhd)? Example is listed below (configuration statement is at end of file)

Pastebin 3_architecture_vhdl

-- configuration gate
-- File: conf_gate.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity xor_gate is
    generic(
        DATA_WIDTH : natural := 3
        );
    port( 
        a : in std_logic_vector(DATA_WIDTH-1 downto 0);
        b : in std_logic_vector(DATA_WIDTH-1 downto 0);
        c : out std_logic_vector(DATA_WIDTH-1 downto 0)

        );
end xor_gate;

architecture arch of xor_gate is

begin
    c <= a xor b;
end arch;

architecture not_arch of xor_gate is

begin
    c <= a xnor b;
end not_arch;

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity or_gate is
    generic(
        DATA_WIDTH : natural := 3
        );
    port( 
        a : in std_logic_vector(DATA_WIDTH-1 downto 0);
        b : in std_logic_vector(DATA_WIDTH-1 downto 0);
        c : out std_logic_vector(DATA_WIDTH-1 downto 0)

        );
end or_gate;

architecture arch of or_gate is

begin
    c <= a or b;
end arch;

architecture not_arch of or_gate is

begin
    c <= a nor b;
end not_arch;

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity and_gate is
    generic(
        DATA_WIDTH : natural := 3
        );
    port( 
        a : in std_logic_vector(DATA_WIDTH-1 downto 0);
        b : in std_logic_vector(DATA_WIDTH-1 downto 0);
        c : out std_logic_vector(DATA_WIDTH-1 downto 0)

        );
end and_gate;

architecture arch of and_gate is

begin
    c <= a and b;
end arch;

architecture not_arch of and_gate is

begin
    c <= a nand b;
end not_arch;

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity conf_gate is
    generic(
        DATA_WIDTH : natural := 3
        );
    port( 
        a : in std_logic_vector(DATA_WIDTH-1 downto 0);
        b : in std_logic_vector(DATA_WIDTH-1 downto 0);
        c : out std_logic_vector(DATA_WIDTH-1 downto 0)

        );
end conf_gate;

architecture and_gate_arch of conf_gate is

constant negated : boolean := true ;

begin

negated_gate : if negated = true generate
    mod_inst : and_gate(not_arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate negated_gate;

gate : if negated = false generate
    mod_inst : entity work.and_gate(arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate gate;


end and_gate_arch;

architecture or_gate_arch of conf_gate is

constant negated : boolean := true ;

begin

negated_gate : if negated = true generate
    mod_inst : entity work.or_gate(not_arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate negated_gate;

gate : if negated = false generate
    mod_inst : entity work.or_gate(arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate gate;


end or_gate_arch;

architecture xor_gate_arch of conf_gate is

constant negated : boolean := true ;

begin

negated_gate : if negated = true generate
    mod_inst : entity work.xor_gate(not_arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate negated_gate;

gate : if negated = false generate
    mod_inst : entity work.xor_gate(arch)
        generic map (
         DATA_WIDTH => DATA_WIDTH
        )
        port map (
            a => a,
            b => b,
            c => c
        );
    end generate gate;


end xor_gate_arch;

configuration CONF of conf_gate is
    for and_gate_arch
        for mod_inst : entity work.and_gate
            use entity work.conf_gate;
        end for;
    end for;
end CONF;

Solution

  • Component binding deferred to a configuration declaration:

    configuration conf of conf_gate is
        for and_gate_arch
            for negated_gate
                for mod_inst: and_gate
                    use entity work.and_gate(not_arch);
                end for;
            end for;
       end for;
    end configuration conf;
    

    requires component instantiation:

    architecture and_gate_arch of conf_gate is
        constant negated:  boolean := true ;
        component and_gate is
            generic ( DATA_WIDTH:  natural := 3 );
            port ( 
                a:  in  std_logic_vector(DATA_WIDTH - 1 downto 0);
                b:  in  std_logic_vector(DATA_WIDTH - 1 downto 0);
                c:  out std_logic_vector(DATA_WIDTH - 1 downto 0)
            );
        end component;
    begin
    negated_gate:  
        if negated = true generate
    mod_inst:  
            -- entity work.and_gate (not_arch)
            and_gate
                generic map ( DATA_WIDTH => DATA_WIDTH )
                port map (
                    a => a,
                    b => b,
                    c => c
                );
        end generate negated_gate;
    
    gate:  
        if negated = false generate
    mod_inst:  
            entity work.and_gate(arch)
                generic map ( DATA_WIDTH => DATA_WIDTH )
                port map (
                    a => a,
                    b => b,
                    c => c
                );
        end generate gate;
    
    end architecture and_gate_arch;
    

    You should be aware configuration declarations are not widely supported by synthesis vendors. It's worth checking your vendor's supported VHDL constructs (e.g. Xilinx Vivado User Guide 901 for synthesis).

    The alternative can be providing the configuration specifications in the enclosing declarative region for the component instantiation.

    See IEEE Std 1076-2008 3.4 Configuration declarations and 7.3 Configuration specification. It's also useful to understand the difference between an explicit binding indication (7.3.2 Binding indication) and a default binding indication (7.3.3 Default binding indication).