Как увеличить std_logic_vector внутри типа массива с помощью индекса? VHDL

Предыстория:

У меня есть массив типов из четырех 4-битных std_logic_vector:

type my_arr_type is array (0 to 3) of std_logic_vector (3 downto 0);

и соответствующий сигнал:

signal my_signal : my_arr_type;

У меня также есть 2-битный вектор, который будет использоваться в качестве индекса массива:

signal index : std_logic_vector (1 downto 0) := "00";

Это позволяет мне динамически обращаться к каждому 4-битному вектору следующим образом:

my_signal(to_integer(unsigned(index))) <= "0001";

В этом случае индексированный 4-битный вектор получит значение b"0001".

Проблема:

Я хотел бы увеличить значение текущего индексированного 4-битного вектора на 1, когда какое-то условие истинно, например. переключатель высокий.

Я думал, что могу это сделать с чем-то вроде:

process(clk)
begin
  if(rising_edge(clk)) then
      if switch = '1' then --switch flicked (increment)
          my_signal(to_integer(unsigned(index)))
          <= std_logic_vector(unsigned( my_signal(to_integer(unsigned(index))) ) + 1);
      else --remain the same
          my_signal(to_integer(unsigned(index))) 
          <= my_signal(to_integer(unsigned(index)));
      end if;
   end if;
 end process;

Однако я должен делать что-то не так, поскольку передача результирующего сигнала на выход дает сообщение об ошибке - в строках:

Signal X is connected to multiple drivers. ERROR:HDLCompiler:1401

Вопрос:

Что я делаю неправильно в приведенной выше попытке? Что будет правильным решением?

Я не могу найти в Интернете никаких примеров, связанных с увеличением ячеек в индексированном массиве.

(Проектирование для синтеза с Digilent Nexys 3 в ISE Proj Nav)

(edit) Более длинный фрагмент кода для большей тщательности:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ui_top is
Port (  clk         : in    std_logic;
            buttons     : in    std_logic_vector (4 downto 0); -- centre, left, up, right, down
            switches    : in    std_logic_vector (7 downto 0);
            leds            : out std_logic_vector (7 downto 0);
            digit           : out std_logic_vector (3 downto 0) := "1110";
            segments    : out std_logic_vector (7 downto 0) := (others => '0');
            uart_tx     : out std_logic);
end ui_top;

architecture Behavioral of ui_top is

    type my_arr_type is array (0 to 3) of std_logic_vector(3 downto 0);

    signal my_signal : my_arr_type;
    signal index : std_logic_vector (1 downto 0) := "00";


begin

    -- send indexed signal to leds
    leds(3 downto 0) <= my_signal(to_integer(unsigned(index)));

    -- set other outputs arbitrarily
    leds(7 downto 4) <= (others => '1');
    uart_tx <= '1';
    digit <= "1110";
    segments <= (others => '0');

    -- set index
    index <= "00";

    process(clk)
    begin
        if (rising_edge(clk)) then
            if switches(1) = '1' then -- up
                my_signal(to_integer(unsigned(index)))
                <= std_logic_vector(unsigned( my_signal(to_integer(unsigned(index))) ) + 1);
            end if;
        end if; -- rising clock edge
    end process;

    -- set non indexed values arbitrarily
    my_signal(1) <= "0000";
    my_signal(2) <= "0000";
    my_signal(3) <= "0000";

end Behavioral;

Изменить: Все ответы и комментарии были полезными. Спасибо!


person Thomas McKay-Smith    schedule 27.12.2015    source источник
comment
Ваш инструмент синтеза не распознает, что index является постоянным значением. Таким образом, он вычисляет несколько драйверов для каждого имени сигнала, а не для каждого имени индекса. Пожалуйста, измените свой сигнал index на константу, и он должен его распознать (это просто для тестирования).   -  person Paebbels    schedule 28.12.2015
comment
@Paebbels Хорошо. В этом есть смысл. И вы правы - изменение index на постоянное значение делает код пригодным для синтеза. Любые советы о том, как преодолеть эту проблему, когда индекс не является константой?   -  person Thomas McKay-Smith    schedule 28.12.2015
comment
Даже с постоянным индексом мой инструмент зависает во время «Place & Route».   -  person Thomas McKay-Smith    schedule 28.12.2015
comment
Решение: переместите назначения my_signal в процесс. Назначайте только те индексы, к которым никогда не обращается index.   -  person Paebbels    schedule 28.12.2015
comment
Какой инструмент вы используете?   -  person Paebbels    schedule 28.12.2015
comment
@Paebbels Навигатор проекта ISE   -  person Thomas McKay-Smith    schedule 28.12.2015
comment
В любом случае, увеличение std_logic_vector — глупая идея, или, говоря более вежливо, проблема дизайна. Используя библиотеку numeric_std, если она представляет число без знака, объявите ее unsigned. Или, что еще лучше, объявите свой индекс как natural. В любом случае вы одним махом устраняете большинство уродливых преобразований типов.   -  person user_1818839    schedule 28.12.2015
comment
Вы использовали последнюю версию ISE, то есть 14.7? Потому что сообщение об ошибке там немного отличается, и в нем перечислены все несколько драйверов. Конечно, в вашем примере не очевидно, откуда они берутся. Более того, если index изменить на константу, синтез, а также размещение и маршрут выполняются успешно без ошибок.   -  person Martin Zabel    schedule 29.12.2015


Ответы (3)


Это связано с самым длинным статическим префиксом, это не только проблема синтеза, но и отражение в моделировании.

Драйверы для my_signal в процессе определяются по самому длинному статическому префиксу my_signal.

Используя нестатическое значение для индекса в массиве, вы создали драйверы для my_signal(0), my_signal(1), my_signal(2) и my_signal(3) в своем непомеченном процессе.

Каждое из параллельных назначений сигналов имеет эквивалентный процесс, и они имеют самый длинный статический префикс, который включает числовые литералы, используемые в качестве индекса в вашем массиве my_signal.

Два общих драйвера между немаркированным процессом и каждым эквивалентным процессом для каждого параллельного оператора присваивания приводят к разрешенному значению сигнала, которое в моделировании будет давать значения «X» или «U» для конфликтующих значений элементов std_logic. Ваш синтез блокируется и сообщает, что вы замкнули драйверы вместе.

См. IEEE Std 1076-2008 8. Имена, 8.1 Общие положения (самый длинный статический префикс, параграф 8), 14.7 Исполнение модели, 14.7.2 Драйверы, параграф 1, 14.7.3 Распространение значений сигнала, 14.7.3.1 Общие положения, параграф 5.

Если бы вы использовали неразрешенный тип элемента (BIT, BIT_VECTOR), вы бы получили отчеты об одной или нескольких ошибках во время разработки для нескольких драйверов в сигнальной сети. Это эквивалент того, что сообщает ваш инструмент синтеза.

person Community    schedule 27.12.2015

Ваша проблема связана с несколькими дисками. Это сообщение и его ответ могут помочь понять это. Поскольку вы используете разрешенные типы (std_logic), вы не получите ошибок или предупреждений при компиляции или моделировании. Используемый вами инструмент (ISE) представляет собой логический синтезатор. Он пытается сопоставить описанное вами поведение с существующими аппаратными ресурсами. Поскольку ваше аппаратное обеспечение не поддерживает несколько дисков, вы получаете ошибки. Мои советы:

  • не используйте разрешенные типы, когда они не нужны,
  • используйте соответствующие типы (как мудро предложил Брайан Драммонд).

Что-то вроде следующего кода должно быть лучше. Адаптируйте его к вашим конкретным потребностям. Обратите внимание, что тип unsigned для ieee.numeric_std, к сожалению, является разрешенным типом. Поэтому используйте его осторожно и избегайте ситуаций с несколькими дисками. Или, что еще лучше, если ваши инструменты поддерживают это, используйте unresolved_unsigned неразрешенную версию unsigned.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ui_top is
  Port(clk         : in  std_ulogic;
       buttons     : in  std_ulogic_vector (4 downto 0); -- centre, left, up, right, down
       switches    : in  std_ulogic_vector (7 downto 0);
       leds        : out std_ulogic_vector (7 downto 0);
       digit       : out std_ulogic_vector (3 downto 0);
       segments    : out std_ulogic_vector (7 downto 0);
       uart_tx     : out std_ulogic);
end ui_top;

architecture Behavioral of ui_top is

  constant n: positive := 4;
  type my_arr_type is array (0 to 3) of unsigned(n-1 downto 0);
  -- type my_arr_type is array (0 to 3) of unresolved_unsigned(n-1 downto 0);

  signal my_signal : my_arr_type;
  signal index : natural range 0 to n-1;

begin

  -- send indexed signal to leds
  leds(n-1 downto 0) <= std_ulogic_vector(my_signal(index));

  -- set other outputs arbitrarily
  leds(7 downto n) <= (others => '1');
  uart_tx <= '1';
  digit <= "1110";
  segments <= (others => '0');
  -- set index
  index <= 0;

  process(clk)
  begin
    if (rising_edge(clk)) then
      -- set non indexed values arbitrarily
      for i in 0 to n-1 loop
        if i = index then
          if switches(1) = '1' then -- up
            my_signal(i) <= my_signal(i) + 1;
          end if;
        else
          my_signal(i) <= (others => '0');
        end if;
      end loop;
    end if; -- rising clock edge
  end process;

end Behavioral;
person Renaud Pacalet    schedule 28.12.2015
comment
Использование неразрешенных типов обычно является хорошим советом, но здесь он бесполезен. Синтезатор ISE 14.7 жалуется на ту же ошибку, независимо от того, используется ли std_logic_vector или std_ulogic_vector для элементов my_signal. Перечислены несколько драйверов, но, к сожалению, непонятно, откуда они берутся. - person Martin Zabel; 29.12.2015
comment
@MartinZabel Использование неразрешенных типов не мешает вам писать фиктивный код. Это просто поможет вам избежать ситуаций с несколькими дисками: ваш инструмент моделирования выдаст ошибки и сообщит вам, что не так. В любом случае, отладка VHDL-кода с помощью синтезатора — плохая идея. - person Renaud Pacalet; 29.12.2015

Причина (вероятно) в том, что существует другой процесс или параллельное назначение, которое управляет (назначает) my_signal, поэтому просмотрите весь код или разместите его здесь для дальнейшего изучения.

Обратите внимание, что драйвер (назначить) может относиться к другому индексу; взгляните на этот ответ.

Кстати. вы можете удалить

else --remain the same
    my_signal(to_integer(unsigned(index))) 
    <= my_signal(to_integer(unsigned(index)));

поскольку my_signal будет сохранять текущее значение до тех пор, пока не будет задано новое.

person Morten Zilmer    schedule 27.12.2015
comment
Это было мое понимание ошибки, но я не вижу ничего другого, что присваивается my_signal (по крайней мере, не индексированный 4-битный вектор, я предполагаю, что некоторые заблуждения в этой сложности - моя проблема). Я добавил весь свой код, чтобы вы могли внимательно изучить его, если хотите. Тем временем я прочитаю ваш другой ответ. - person Thomas McKay-Smith; 28.12.2015