Предположим, следующий компонент VHDL:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port
(
iClk : in std_logic;
iDataA : in unsigned(7 downto 0);
iDataB : in unsigned(7 downto 0);
iDataC : in unsigned(7 downto 0);
oResultA : out unsigned(7 downto 0);
oResultB : out unsigned(7 downto 0)
);
end entity;
architecture behaviour of adder is
begin
process
begin
wait until rising_edge(iClk);
if iDataB /= 0 then
oResultA <= iDataA + iDataB;
else
oResultB <= iDataA + iDataC;
end if;
end process;
end behaviour;
Как видно, он содержит два дополнения. Я ожидал, что синтезированная логика тоже будет содержать два сумматора. Вместо этого Quartus, кажется, считает хорошей идеей использовать только один сумматор и мультиплексировать в него второй вход (см. RTL ниже). На мой взгляд, в этом нет никакого смысла. Это не экономит аппаратные ресурсы, потому что для мультиплексора требуется такое же количество логических элементов, как и для сумматора. Кроме того, мультиплексор должен ждать, пока не будет оценено условие if, что приводит к худшему времени.
У меня такое случалось с гораздо большим компонентом и большим конечным автоматом, что приводило к нарушениям синхронизации. Как предотвратить такого рода «оптимизацию»? Я установил режим оптимизации «Производительность (Агрессивный — увеличивает время выполнения и площадь)», но, похоже, это не имеет значения. Единственное, что привело к ожидаемому результату, это введение дополнительных сигналов, например:
tmpA <= iDataA + iDataB;
tmpB <= iDataA + iDataC;
process
begin
wait until rising_edge(iClk);
if iDataB /= 0 then
oResultA <= tmpA;
else
oResultB <= tmpB;
end if;
end process;
Есть ли лучший способ сделать это, так как это делает код очень трудным для чтения. Я использую Quartus 20.1 с FPGA Max10.