Идеи для гибкого/универсального декодера в VHDL

Я хочу создать адресный декодер, который будет достаточно гибким, чтобы я мог использовать его при изменении количества битов селектора и декодированных выходных сигналов.

Итак, вместо статического (фиксированного размера ввода/вывода) декодера, который выглядит примерно так:

entity Address_Decoder is
Generic
(
    C_INPUT_SIZE: integer := 2
);
Port
(
    input   : in  STD_LOGIC_VECTOR (C_INPUT_SIZE-1 downto 0);
    output  : out STD_LOGIC_VECTOR ((2**C_INPUT_SIZE)-1 downto 0);
    clk : in  STD_LOGIC;
    rst : in  STD_LOGIC
);
end Address_Decoder;

architecture Behavioral of Address_Decoder is

begin        
        process(clk)
            begin
               if rising_edge(clk) then 
                  if (rst = '1') then
                     output <= "0000";
                  else
                     case <input> is
                        when "00" => <output> <= "0001";
                        when "01" => <output> <= "0010";
                        when "10" => <output> <= "0100";
                        when "11" => <output> <= "1000";
                        when others => <output> <= "0000";
                     end case;
                  end if;
               end if;
            end process;

end Behavioral;

Имейте что-то более гибкое/общее, что выглядит так:

    entity Address_Decoder is
    Generic
    (
        C_INPUT_SIZE: integer := 2
    );
    Port
    (
        input   : in  STD_LOGIC_VECTOR (C_INPUT_SIZE-1 downto 0);
        output  : out STD_LOGIC_VECTOR ((2**C_INPUT_SIZE)-1 downto 0);
        clk : in  STD_LOGIC;
        rst : in  STD_LOGIC
    );
    end Address_Decoder;

    architecture Behavioral of Address_Decoder is

    begin        

DECODE_PROC:
    process (clk)
    begin

        if(rising_edge(clk)) then
         if ( rst = '1') then
           output <= conv_std_logic_vector(0, output'length);
         else
           case (input) is
             for i in 0 to (2**C_INPUT_SIZE)-1 generate
             begin
                when (i = conv_integer(input)) => output <= conv_std_logic_vector((i*2), output'length);        
             end generate;
            when others => output <= conv_std_logic_vector(0, output'length);
           end case;
         end if;
        end if;
    end process;

    end Behavioral;

Я знаю, что этот код недействителен и что контрольные примеры «когда» должны быть константами, и что я не могу использовать for-generate между оператором case, подобным этому, но он показывает, что мне нужно: объект достаточно умен, чтобы вырасти до моих потребностей.

Я пытался найти элегантное решение этой проблемы без особого успеха, поэтому я открыт для любых предложений.

Заранее спасибо, Эрик


person Erick Tejada    schedule 24.01.2011    source источник
comment
numeric_std предоставляет функцию, которая сдвигает вектор на указанное число. Таким образом, вы могли бы предположительно сдвинуть вектор 0 => '1', others => '0' влево на (входное число - 1).   -  person Anon.    schedule 25.01.2011


Ответы (2)


Очевидно, вы хотите, чтобы вход был индексом выходного бита, который должен быть установлен.

Пишите так. Что-то вроде (при условии, что типы из numeric_std):

output <= (others => '0'); -- default
output(to_integer(input)) <= '1';
person Jan Decaluwe    schedule 24.01.2011
comment
Коротко и эффективно (и отлично сработало!). Это заставляет меня понять, что иногда желание пойти немного ниже в описании оборудования (пытаясь определить логику ближе к тому, как будет выглядеть его аппаратная реализация), может ослепить вас от очевидных решений, которые ставят часть дизайна загружается на программное обеспечение вместо вас. Спасибо за решение Ян. - person Erick Tejada; 26.01.2011
comment
Я рад, что вы получили мета-послание :-) Поздравляю с этим пониманием, которое на удивление редко встречается в мире дизайна HDL! - person Jan Decaluwe; 26.01.2011

Я всегда находил такие вещи более простыми, когда вы просто перебираете каждый бит, поэтому что-то вроде:

     if ( rst = '1') then
       output <= (others=>'0');
     else
       for i in 0 to (2**C_INPUT_SIZE)-1 generate
       begin
         if (i = conv_integer(input)) then
           output(i) <= '1';
         else
           output(i) <= '0';
         end if;
       end generate;
     end if;
person Charles Steinkuehler    schedule 25.01.2011