Использование оператора цикла:
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 назначением сигналов по умолчанию, что потенциально создает меньше логики.
Таким образом, в синтезе может быть мало различий, но значительная разница в симуляции, где практическое воздействие зависит от размера вашего дизайна.
Спасибо, Дэвид. У меня есть еще один вопрос, какое влияние это окажет на аппаратный уровень. Я знаю одну вещь: в циклах операторы будут выполняться последовательно, а генерация цикла будет «генерировать» те многие параллельные операторы –
@prernaB операторы цикла и генерировать для операторов, которые выполняют одну и ту же логику, часто синтезируются в идентичное аппаратное обеспечение. Синтезатор просто определяет, какая комбинационная логика и флип-флоп необходимы для создания поведения, описанного «последовательными» процессами. Последовательные операторы являются просто конструкцией языка, операторы фактически не выполняются индивидуально или последовательно после синтеза в аппаратное обеспечение. – QuantumRipple
Оператор generate представляет собой, по меньшей мере, два уровня операторов блока и любые входящие в него параллельные операторы. Все параллельные операторы передаются в операторы блоков (иерархия) и/или операторы процесса. Мы моделируем или синтезируем сеть, на которую воздействуют операторы процесса (функции - это выражения). Оператор цикла представляет собой последовательность последовательных операторов, которые могут быть повторены с другим значением для применяемой константы цикла. Мы представляем (распознаем) аппаратное обеспечение из последовательности последовательных операторов, обнаруженных в процессах, которые представляют собой параллельное выполнение. – user1155120