Стиль кодирования мультиплексора на этой линии
data <= data_in((idx+1)*B-1 downto idx*B);
может сильно повлиять на логический синтез. Это приводит к очень различному количеству путей для анализа времени.
Оригинальный мультиплексор.
Сначала я проверил синтез приведенной выше строки на этом небольшом примере:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mux1 is
generic (
B : positive := 32;
M : positive := 7); -- M := ceil(log_2 N)
port (
d : in STD_LOGIC_VECTOR ((2**M)*B-1 downto 0); -- input data
s : in STD_LOGIC_VECTOR (M-1 downto 0); -- selector
y : out STD_LOGIC_VECTOR(B-1 downto 0)); -- result
end mux1;
architecture Behavioral of mux1 is
constant N : positive := 2**M;
signal idx : integer range 0 to N-1;
begin
idx <= to_integer(unsigned(s));
y <= d((idx+1)*B-1 downto idx*B);
end Behavioral;
Если кто-то синтезирует это для Spartan-6, XST сообщает об этом (отрывок):
Macro Statistics
# Adders/Subtractors : 2
13-bit subtractor : 1
8-bit adder : 1
...
Number of Slice LUTs: 1516 out of 5720 26%
...
Timing constraint: Default path analysis
Total number of paths / destination ports: 139264 / 32
Таким образом, ни один мультиплексор не был обнаружен, и анализатору времени приходится анализировать огромное количество путей. Использование логики в порядке.
Оптимизированная реализация
Такого же мультиплексирования можно добиться с помощью: (EDIT: исправление ошибки и упрощение)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mux2 is
generic (
B : positive := 32;
M : positive := 7); -- M := ceil(log_2 N)
port (
d : in STD_LOGIC_VECTOR ((2**M)*B-1 downto 0);
s : in STD_LOGIC_VECTOR (M-1 downto 0);
y : out STD_LOGIC_VECTOR(B-1 downto 0));
end mux2;
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- !! The entire architecture has been FIXED and simplified. !!
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
architecture Behavioral of mux2 is
constant N : positive := 2**M;
type matrix is array (N-1 downto 0) of std_logic_vector(B-1 downto 0);
signal dd : matrix;
begin
-- reinterpret 1D vector 'd' as 2D matrix, i.e.
-- row 0 holds d(B-1 downto 0) which is selected in case s = 0
row_loop: for row in 0 to N-1 generate
dd(row) <= d((row+1)*B-1 downto row*B);
end generate;
-- select the requested row
y <= dd(to_integer(unsigned(s)));
end Behavioral;
Теперь отчет XST выглядит намного лучше:
Macro Statistics
# Multiplexers : 1
32-bit 128-to-1 multiplexer : 1
...
Number of Slice LUTs: 1344 out of 5720 23%
...
Timing constraint: Default path analysis
Total number of paths / destination ports: 6816 / 32
Он обнаруживает, что для каждого выходного бита требуется мультиплексор 128-к-1. Оптимизированный синтез такого широкого мультиплексора встроен в инструмент синтеза. Количество LUT уменьшилось лишь незначительно. Но количество путей, которые должны быть обработаны временным анализатором, резко сокращается в 20 раз!
Реализация с использованием одного горячего селектора
В приведенных выше примерах используется селекторный сигнал с двоичным кодированием. Я проверил также вариант с одним горячим кодированием:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mux3 is
generic (
B : positive := 32;
N : positive := 128);
port ( d : in STD_LOGIC_VECTOR (N*B-1 downto 0);
s : in STD_LOGIC_VECTOR (N-1 downto 0);
y : out STD_LOGIC_VECTOR(B-1 downto 0));
end mux3;
architecture Behavioral of mux3 is
begin
process(d, s)
begin
y <= (others => '0'); -- avoid latch!
for i in 0 to N-1 loop
if s(i) = '1' then
y <= d((i+1)*B-1 downto i*B);
end if;
end loop;
end process;
end Behavioral;
Теперь отчет XST снова отличается:
Macro Statistics
# Multiplexers : 128
32-bit 2-to-1 multiplexer : 128
...
Number of Slice LUTs: 2070 out of 5720 36%
...
Timing constraint: Default path analysis
Total number of paths / destination ports: 13376 / 32
Обнаружен мультиплексор 2-к-1, т.к. описан приоритетный мультиплексор, аналог этой схемы:
if s(127) = '1' then
y <= d(128*B-1 downto 127*B);
else
if s(126) = '1' then
y <= d(127*B-1 downto 126*B);
else
...
if s(0) = '1' then
y <= d(B-1 downto 0);
else
y <= (others => '0');
end if;
end if; -- s(126)
end if; -- s(127)
Я не использовал здесь elsif
по дидактическим причинам. Каждая ступень if-else
представляет собой 32-битный мультиплексор 2-к-1. Проблема здесь в том, что синтез не знает, что s
является сигналом, закодированным в горячем виде. Таким образом, требуется немного больше логики, как в моей оптимизированной реализации.
Количество путей для анализа времени снова существенно меняется. Цифра в 10 раз ниже, чем в исходной реализации, но в 2 раза выше, чем в моей оптимизированной.
person
Martin Zabel
schedule
01.12.2015
for loop
. Синтаксис правильный, если он принимается XST без ошибок. Семантика верна, если симуляция показывает желаемый результат, а XST не выдает предупреждений. Вы не ответили на мой второй вопрос. Ответ важен для меня, чтобы, вероятно, решить ваш вопрос. - person Martin Zabel   schedule 01.12.2015