Есть способ сделать ваш индекс адресным для статического синтеза.
Во-первых, на основе цикла, который мы можем указать position
должно иметь значение в диапазоне shift_aux
, иначе вы получите нулевые фрагменты (IEEE Std 1076-2008 8.5 Slice names).
Это может быть показано в объявлении объекта:
library ieee;
use ieee.std_logic_1164.all;
entity shift_register is
generic (
N: integer := 6;
M: integer := 6
);
port (
en_s: in std_logic;
cod_result: in std_logic_vector (N + M - 1 downto 0);
position: in integer range 0 to N + M - 1 ; -- range ADDED
shift_result: out std_logic_vector(N + M - 1 downto 0)
);
end entity shift_register;
Что изменилось, так это добавление диапазона ограничения к декларации порта position
. Идея заключается в поддержке моделирования, где значением по умолчанию может быть целое число: integer'left
. Имитация вашего shift_register
потерпит неудачу по нарастающему фронту en_s
, если position
(фактический драйвер) не дал начального значения в диапазоне индексов shift_aux
.
С точки зрения синтеза неограниченное целочисленное значение требует, чтобы вы принимали как положительные, так и отрицательные целочисленные значения для учетной записи. Цикл for использует только положительные целые значения.
То же самое можно сделать в декларации в процессе переменной i
:
variable i: integer range 0 to N + M - 1 := 0; -- range ADDED
Для решения насущной проблемы синтеза мы рассмотрим цикл.
Вопрос поддержки Xilinx AR# 52302 говорит нам, что проблема заключается в использовании динамических значений для индексов.
Решение состоит в том, чтобы изменить то, что делает цикл:
architecture shift_loop of shift_register is
begin
process (en_s)
variable shift_aux: std_logic_vector(N + M - 1 downto 0);
-- variable i: integer range 0 to N + M - 1 := 0; -- range ADDED
begin
if en_s'event and en_s = '1' then
-- i := position;
shift_aux := (others => '0');
for i in 0 to N + M - 1 loop
-- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0);
if i = position then
shift_aux(N + M - 1 downto i)
:= cod_result(N + M - 1 - i downto 0);
end if;
end loop;
shift_result <= shift_aux;
end if;
end process;
end architecture shift_loop;
Если i
становится статическое значение, когда цикл раскатывают в синтезе он может быть использован при расчете индексов.
Обратите внимание, что это дает нам входной мультиплексор N + M, где каждый вход выбирается, когда i = position
.
Эта конструкция может быть фактически свернута в баррель-переключатель по оптимизации, хотя вы можете ожидать, что число переменных, участвующих в больших значениях N и M, может занять чрезмерное усилие синтеза или просто выйти из строя.
Когда синтез будет успешным, вы скомпенсируете каждый выходной элемент в назначении в отдельный мультиплексор, который будет соответствовать от Patrick barrel shifter.
Для достаточно больших значений N и M мы можем определить глубину в количестве слоев мультиплексора в баррель-переключателе в зависимости от количества бит в двоичном выражении целочисленного диапазона расстояния.
Для этого требуется объявленный целочисленный тип или подтип для position
или нахождения значения log2 для N + M. Мы можем использовать значение log2, потому что оно будет использоваться только статически. (XST поддерживает log2 (x), где x является Real для определения статических значений, эта функция находится в пакете IEEE math_real). Это дает нам двоичную длину position
. (Сколько бит требуется для описания расстояния сдвига, количества уровней мультиплексоров).
architecture barrel_shifter of shift_register is
begin
process (en_s)
use ieee.math_real.all; -- log2 [real return real]
use ieee.numeric_std.all; -- to_unsigned, unsigned
constant DISTLEN: natural := integer(log2(real(N + M))); -- binary lengh
type muxv is array (0 to DISTLEN - 1) of
unsigned (N + M - 1 downto 0);
variable shft_aux: muxv;
variable distance: unsigned (DISTLEN - 1 downto 0);
begin
if en_s'event and en_s = '1' then
distance := to_unsigned(position, DISTLEN); -- position in binary
shft_aux := (others => (others =>'0'));
for i in 0 to DISTLEN - 1 loop
if i = 0 then
if distance(i) = '1' then
shft_aux(i) := SHIFT_LEFT(unsigned(cod_result), 2 ** i);
else
shft_aux(i) := unsigned(cod_result);
end if;
else
if distance(i) = '1' then
shft_aux(i) := SHIFT_LEFT(shft_aux(i - 1), 2 ** i);
else
shft_aux(i) := shft_aux(i - 1);
end if;
end if;
end loop;
shift_result <= std_logic_vector(shft_aux(DISTLEN - 1));
end if;
end process;
end architecture barrel_shifter;
XST также поддерживает **
, если левый операнд 2 и значение i
трактуются как константа в последовательности операторов, найденных в операторе цикла.
Это может быть реализовано с помощью сигналов вместо переменных или структурно в выражении generate вместо оператора цикла внутри процесса или даже в качестве подпрограммы.
Основная идея здесь с этими двумя архитектурами, полученными от вас, заключается в том, чтобы получить что-то синтетическое.
Преимущества второй архитектуры над первым в сокращении количества синтеза усилий в процессе оптимизации для больших значений N + М.
Ни один из этих архитектур были проверены на отсутствие в испытательном стенде оригинала. Они анализируют и разрабатывают.
Дать простой случай: испытательный стенд
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity shift_register_tb is
end entity;
architecture foo of shift_register_tb is
constant N: integer := 6;
constant M: integer := 6;
signal clk: std_logic := '0';
signal din: std_logic_vector (N + M - 1 downto 0)
:= (0 => '1', others => '0');
signal dout: std_logic_vector (N + M - 1 downto 0);
signal dist: integer := 0;
begin
DUT:
entity work.shift_register
generic map (
N => N,
M => M
)
port map (
en_s => clk,
cod_result => din,
position => dist,
shift_result => dout
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > (N + M + 2) * 20 ns then
wait;
end if;
end process;
STIMULI:
process
begin
for i in 1 to N + M loop
wait for 20 ns;
dist <= i;
din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1));
end loop;
wait;
end process;
end architecture;
И имитируя показывает, что диапазон position
и число итераций цикла необходимо только, чтобы покрыть число битов в умножитель и не множимое. Нам не нужен полный баррель.
Это может быть легко зафиксировано в обеих архитектурах shift_register и имеет побочный эффект, заключающийся в том, что архитектура shift_loop будет намного более привлекательной, было бы легче синтезировать на основе длины бит мультипликатора (предположительно M), а не длины бит продукта (N + M).
И это даст вам:
library ieee;
use ieee.std_logic_1164.all;
entity shift_register is
generic (
N: integer := 6;
M: integer := 6
);
port (
en_s: in std_logic;
cod_result: in std_logic_vector (N + M - 1 downto 0);
position: in integer range 0 to M - 1 ; -- range ADDED
shift_result: out std_logic_vector(N + M - 1 downto 0)
);
end entity shift_register;
architecture shift_loop of shift_register is
begin
process (en_s)
variable shift_aux: std_logic_vector(N + M - 1 downto 0);
-- variable i: integer range 0 to M - 1 := 0; -- range ADDED
begin
if en_s'event and en_s = '1' then
-- i := position;
shift_aux := (others => '0');
for i in 0 to M - 1 loop
-- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0);
if i = position then -- This creates an N + M - 1 input MUX
shift_aux(N + M - 1 downto i)
:= cod_result(N + M - 1 - i downto 0);
end if;
end loop; -- The loop is unrolled in synthesis, i is CONSTANT
shift_result <= shift_aux;
end if;
end process;
end architecture shift_loop;
Изменение испытательный стенд:
STIMULI:
process
begin
for i in 1 to M loop -- WAS N + M loop
wait for 20 ns;
dist <= i;
din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1));
end loop;
wait;
end process;
дает результат, показывающий, что сдвиги в диапазоне от значения множителя (указанный М):
Итак, мораль здесь не нужна полная баррель, только один, который работает по диапазону множителей, а не по ассортименту.
Последний бит кода должен соответствовать синтезу.
Я знаю, почему не работает, моя задача - реализовать множитель Бутла, поэтому я не могу использовать x <= a * b. В любом случае спасибо –
@DarioFigliuzzi, так что ваш реальный вопрос: «Как мне реализовать баррель?». В этом случае существуют существующие вопросы. –
Я думал больше о том, как обойти эту проблему. Альтернативный способ –