2017-02-01 18 views
0

Я внедрил модифицированный множитель Booth в vhdl. Мне нужно сделать синтез с Vivado, но это невозможно из-за этой ошибки: «сложное назначение не поддерживается». Это код сдвига, который вызывает ошибку:Синтез Vivado: сложное назначение не поддерживается

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; 
shift_result : out std_logic_vector(N+M-1 downto 0) 
);  
end shift_register; 

architecture shift_arch of shift_register is 
begin 
process(en_s) 

variable shift_aux : std_logic_vector(N+M-1 downto 0); 
variable i : integer := 0; --solo per comodità 
begin 
    if(en_s'event and en_s ='1') then 
     i := position; 
     shift_aux := (others => '0'); 
     shift_aux(N+M-1 downto i) := cod_result(N+M-1-i downto 0); --ERROR!! 
     shift_result <= shift_aux ; 
    end if; 
end process; 
end shift_arch; 

стенд мультипликатор работает с любой размерностью оператора. Поэтому я не могу изменить этот общий код на конкретный. Пожалуйста, помогите мне! Большое спасибо

ответ

0

Вы пытаетесь создать диапазон, используя переменное значение времени выполнения, и это не поддерживается инструментом синтеза. cod_result(N+M-1 downto 0); будет поддерживаться, потому что N, M и 1 известны во время синтеза.

Если вы пытаетесь реализовать множитель, вы получите наилучший результат, используя x <= a * b, и дайте инструменту синтеза выбрать наилучший способ его реализации. Если у вас есть операнды, более широкие, чем ширина множителя на вашем устройстве, вам нужно посмотреть документацию, чтобы определить лучший маршрут, который обычно будет включать в себя конвейерную обработку.

Если вам нужен переменный сдвиг во время выполнения, найдите «баррель-сдвиг». На них есть ответы, например this one.

+0

Я знаю, почему не работает, моя задача - реализовать множитель Бутла, поэтому я не могу использовать x <= a * b. В любом случае спасибо –

+0

@DarioFigliuzzi, так что ваш реальный вопрос: «Как мне реализовать баррель?». В этом случае существуют существующие вопросы. –

+0

Я думал больше о том, как обойти эту проблему. Альтернативный способ –

1

Есть способ сделать ваш индекс адресным для статического синтеза.

Во-первых, на основе цикла, который мы можем указать 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; 

дает результат, показывающий, что сдвиги в диапазоне от значения множителя (указанный М):

shift_register_tb_1.png

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

Последний бит кода должен соответствовать синтезу.