2014-11-12 2 views
1

Я знаю, что писать невозможно для генерации внутри процесса, но я хочу получить функциональность, представленную кодом. Это в основном декодер адресов. Любая помощь приветствуется.for-generate внутри процесса vhdl

Следующий код выдает ошибку синтаксиса: «ошибка синтаксиса около генерации»

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.NUMERIC_STD.ALL; 

entity address_decoder is 
generic (CAM_DEPTH: integer := 8); 
port (in_address: in std_logic_vector(CAM_DEPTH-1 downto 0); 
     out_address: out std_logic_vector(2**CAM_DEPTH-1 downto 0); 
     clk : in std_logic; 
     rst: in std_logic 
    ); 
end address_decoder; 

architecture Behavioral of address_decoder is 

begin 
decode_process: 
process(clk,rst) begin 

if(clk'event and clk='1') then 
     if (rst = '1') then 
      out_address <= (others => '0'); 
     else 
      NAME: for i in 0 to 10 generate 
       if (i = to_integer(unsigned(in_address))) then 
        out_address(i) <= '1'; 
      else 
        out_address(i) <= '0'; 
       end if; 
     end generate NAME; 
end if; 
end if; 

end process; 

end Behavioral; 

ответ

8

Использование оператора цикла:

decode_process: 
    process(clk) -- synchronous reset, no rst in sensitivity list 
    begin 

     if clk'event and clk = '1' then 
      if rst = '1' then 
       out_address <= (others => '0'); 
      else 
       for i in 0 to 10 loop 
        if i = to_integer(unsigned(in_address)) then 
         out_address(i) <= '1'; 
        else 
         out_address(i) <= '0' ; 
        end if; 
       end loop; 

       -- name: for i in 0 to 10 generate 
       --  if (i = to_integer(unsigned(in_address))) then 
       --   out_address(i) <= '1'; 
       --  else 
       --   out_address(i) <= '0'; 
       --  end if; 
       -- end generate name; 
      end if; 
     end if; 
    end process; 

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

Может быть синтезирован оператор цикла, см. Теперь отмененный IEEE Std 1076.6-2004 8.8.9, синтаксис, последовательные операторы, оператор Loop или документацию вашего конкретного инструмента поставщика синтеза. Последовательные операторы, найденные в цикле, реплицируются для каждого значения параметра цикла, который рассматривается как константа.

Так в чем же разница между сгенерированием итерации и повторением цикла?

Циклы моделирования эмулируют параллелизм для назначения сигналов даже в последовательных операциях (например, в процессе). В синтезированном (развернутом) цикле нет зависимостей между одним оператором if и другим. Они будут i номер in_address распознавателей, сравнивающих i, с каждым номером out_address. Первый присваивает a(0), второй a(1) ... В этом случае оператор цикла создаст ту же логику, что и оператор generate (используя условное назначение сигнала, хотя семантика последовательной логики (часы) заставит его выглядеть неудобно).

Давайте сравним это с помощью генерировать заявление в параллельном заявлении соответствующего месте:

architecture foo of address_decoder is 
    function to_std_ulogic (inp: boolean) return std_ulogic is 
    begin 
     if inp = TRUE then 
      return '1'; 
     else 
      return '0'; 
     end if; 
    end; 
begin 

decoder: 
    for i in 0 to 10 generate 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end generate; 

end architecture; 

Функция to_std_ulogic принимает булев аргумент был добавлен для краткости в операторе условного присваивания сигнала out_address(i).

Это выглядит красиво и компактно и, вероятно, может синтезироваться в зависимости от возможности использования функции, преобразующей логическое значение в std_ulogic.

Однако, она расширяется за разработку:

architecture fum of address_decoder is 
    function to_std_ulogic (inp: boolean) return std_ulogic is 
    begin 
     if inp = TRUE then 
      return '1'; 
     else 
      return '0'; 
     end if; 
    end; 
begin 

decoder0: 
    block 
     constant i: integer := 0; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder1: 
    block 
     constant i: integer := 1; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder2: 
    block 
     constant i: integer := 2; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder3: 
    block 
     constant i: integer := 3; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder4: 
    block 
     constant i: integer := 4; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder5: 
    block 
     constant i: integer := 5; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder6: 
    block 
     constant i: integer := 6; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder7: 
    block 
     constant i: integer := 7; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder8: 
    block 
     constant i: integer := 8; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder9: 
    block 
     constant i: integer := 9; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
decoder10: 
    block 
     constant i: integer := 10; 
    begin 
     out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))) 
          when clk'event and clk = '1'; 
    end block; 
end architecture; 

И еще хуже, каждый из этих блоков заявления одновременно условные операторы присваивания сигнала становится процесс утверждение вида:

decoder10: 
    block 
     constant i: integer := 10; 
    begin 
     process 
     begin 
      if clk'event and clk = '1' then 
       out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address))); 
      end if; 
     wait on clk, in_address; 
     end process; 

Так что теперь внезапно, вместо того, чтобы имитировать один процесс, у вас одиннадцать, и каждый из этих процессов чувствителен к clk и in_address, что означает, что процесс становится активным больше, чем на обоих ребрах часов.

Таким образом, не только оператор цикла и выражение сгенерирования производят одно и то же аппаратное обеспечение после разработки и синтеза, оператор цикла, как гарантируется, будет быстрее в симуляции, что является целью.

Все в спецификации дизайна VHDL переходит к блочным операторам, операторам процессов и подпрограммам (функциям, процедурам).Параллельные процедуры также передаются, а функции - это выражения.

Гарантируется, что синтез сначала разрабатывает дизайн. Разница синтеза в этом случае между оператором generate и одним процессом, содержащим цикл, группируется. Оператор процесса переводится отдельно, если инструмент синтеза не принимает атрибут, разрешающий сглаживание (например, DISSOLVE_HIERARCHY как атрибут инструкции generate).

В операторе цикла в одном случае процесса есть возможность совместно использовать логику распознавания адреса между 10 назначением сигналов по умолчанию, что потенциально создает меньше логики.

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

+0

Спасибо, Дэвид. У меня есть еще один вопрос, какое влияние это окажет на аппаратный уровень. Я знаю одну вещь: в циклах операторы будут выполняться последовательно, а генерация цикла будет «генерировать» те многие параллельные операторы –

+0

@prernaB операторы цикла и генерировать для операторов, которые выполняют одну и ту же логику, часто синтезируются в идентичное аппаратное обеспечение. Синтезатор просто определяет, какая комбинационная логика и флип-флоп необходимы для создания поведения, описанного «последовательными» процессами. Последовательные операторы являются просто конструкцией языка, операторы фактически не выполняются индивидуально или последовательно после синтеза в аппаратное обеспечение. – QuantumRipple

+0

Оператор generate представляет собой, по меньшей мере, два уровня операторов блока и любые входящие в него параллельные операторы. Все параллельные операторы передаются в операторы блоков (иерархия) и/или операторы процесса. Мы моделируем или синтезируем сеть, на которую воздействуют операторы процесса (функции - это выражения). Оператор цикла представляет собой последовательность последовательных операторов, которые могут быть повторены с другим значением для применяемой константы цикла. Мы представляем (распознаем) аппаратное обеспечение из последовательности последовательных операторов, обнаруженных в процессах, которые представляют собой параллельное выполнение. – user1155120

0

Ваш декодер - это просто двоичный код с одним горячим кодировщиком с нижестоящим регистром. Таким образом, вы можете извлечь кодер и положить его в функцию

function bin2onehot(value : std_logic_vector) return std_logic_vector is 
    variable result : std_logic_vector(2**value'length - 1 downto 0) := (others => '0'); 
begin 
    result(2 ** to_integer(unsigned(value))) := '1'; 
    return result; 
end function; 

И это ваш регистр:

process(clk) 
begin 
    if rising_edge(clk) then 
    if (rst = '1') then 
     out_address <= (others => '0'); 
    else 
     out_address <= bin2onehot(in_address); 
    end if; 
    end if; 
end process; 

Вы можете сэкономить rst из списка чувствительности, потому что это синхронный сброс.

+0

Спасибо Paebbels. Он выглядит хорошо и отлично работает. –

0

Просто хотел бы добавить к предыдущим ответам,

GENERATE заявление одновременно заявления, она может быть использована только в уровне архитектуры.

Блок PROCESS может быть последовательным/параллельным, поэтому, я думаю, по этой причине GENERATE не допускается внутри блока PROCESS.

Смежные вопросы