Как я могу указать сигналы «не заботятся» в VHDL?

В курсах Logic Design мы все узнали, что можно свести к минимуму логическую функцию, например, используя карту Карно или алгоритм Quine-McCluskey . Мы также узнали, что «Не заботьтесь» значения увеличивают потенциал минимизации.

Например, возьмите файл регистра. Сигналы write_address и write_data не отображают действительно, когда сигнал write_enable '0' , Таким образом, им должно быть присвоено значение «Не заботь», чтобы обеспечить большую оптимизацию в логике вождения этих сигналов (т. Е. Не в самом файле регистра).

Каков правильный способ указать такие значения «Не заботьтесь» в VHDL, чтобы позволить инструменту синтеза больше возможностей для возможных оптимизаций?


До сих пор я нашел следующие вещи, которые могут быть подходящими. Но я не совсем уверен, какие плюсы и минусы каждого подхода:

  • Просто не назначать сигнал. Кажется, это может сработать. Однако я обнаружил, что это не сработает, если вы хотите определить «не делать ничего постоянного» некоторого типа record, так как необходимы константы записи (как минимум Modelsim говорит мне об этом).
  • Пакет std_logic_1164 определяет значение '-' -- Don't care для std_ulogic. Похоже, что это семантически правильный выбор для явного «не волнует», но я никогда не видел, чтобы он использовался где-нибудь (кроме несвязанного VHDL-2008 case?).
  • Modelsim использует значение 'X' для отображения неопределенных сигналов. Однако я не уверен, что инструменты синтеза понимают явное выражение 'X' как «не заботятся».

Вот упрощённый фрагмент кода для уточнения, где я инициализировал сигналы, которые не заботятся, с помощью '-'.

Как вы можете видеть, сигнал control.reg_write_address может иметь 3 разных значения: "----", instruction(11 downto 8); и instruction(3 downto 0);. Теперь я ожидаю, что это будет синтезировано для 2-х входного мультиплексора, если '-' интерпретируется как «не волнует». Если бы я инициализировал сигнал с помощью (others => '0') вместо '-', инструмент должен был бы генерировать 3-х входный мультиплексор.

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

package mytypes is
    type control_signals_t is record
        write_enable  : std_logic;
        write_address : std_ulogic_vector(3 downto 0);
        read_address  : std_ulogic_vector(3 downto 0);
    end record;

    -- All members of this constant must be fully specified.
    -- So it's not possible to simply not assign a value.
    constant CONTROL_NOP : control_signals_t := (
        write_enable  => '0',
        write_address => (others => '-'),
        read_address  => (others => '-')
    );
end package;

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

entity control_unit is
    port(
        instruction : in  std_ulogic_vector(15 downto 0);
        write_data  : out std_ulogic_vector(15 downto 0);
        ctrl        : out control_signals_t
    );
end entity;

architecture rtl of control_unit is
begin
    decode_instruction : process(instruction) is
    begin
        -- Set sensible default values that do nothing.
        -- Especially all "write_enable" signals should be '0'.
        -- Everything else is mostly irrelevant (don't care).
        ctrl       <= CONTROL_NOP;
        write_data <= (others => '-');

        if instruction(15 downto 12) = "1100" then
            -- Load 8 bit of data into the register file
            ctrl.write_enable  <= '1';
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
            ctrl.write_address <= instruction(11 downto 8);
        elsif instruction(15 downto 8) = "11111001" then
            -- Load 4 bit of data into the register file
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
            ctrl.write_address <= instruction(3 downto 0);
        elsif instruction(15 downto 8) = "10110101" then
            -- Read from the register file. Don't use the write signals at all.
            ctrl.read_address <= instruction(3 downto 0);
        end if;
    end process;
end architecture;
9 голосов | спросил Fritz 16 PMpWed, 16 Apr 2014 22:13:44 +040013Wednesday 2014, 22:13:44

2 ответа


8

Я оставлю это эксперту LRM, чтобы предоставить более подробный ответ, но, к слову, ваш подход должен быть действительным - я провел быстрый тест с недавней версией Quartus и обрабатывал '-', как и предполагалось, - сгенерированная логика уменьшается, как ожидалось, когда выход по умолчанию равен '-' ('X' тоже работает, кстати). Подробнее о подходах, которые вы указали:

  • Не назначать сигнал на самом деле не вариант для вашего примера, конечно, если вы не хотите защелки. Если это процесс с тактовой частотой, вам немного лучше, но вы все равно получите возможность, где вам могут понадобиться. Может быть, мне не хватает ваших намерений здесь.

  • '-', как было отмечено ранее, является, пожалуй, лучшим вариантом, как по смысловым, так и по практическим причинам.

  • Зависит от того, что вы подразумеваете под «undefined». 'X' технически «неизвестен». 'U' для неинициализированных сигналов, которые ModelSim отображается как "X" для шестнадцатеричных представлений. 'X', похоже, работает, хотя, как я уже отмечал выше.

Другой альтернативой было бы сделать оптимизацию самостоятельно и удалить один случай из проверки:

if instruction(15 downto 8) = "11111001" then
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
else
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
end if;

У этого есть существенные недостатки (в основном связанные с ясностью кода), хотя я бы выбрал более идеальное решение.

Кстати, '-' также обычно используется с std_match(), который я хотел бы использовать для вашего декодирования, например:

if std_match(instruction(15 downto 8), "1100----") then

Хотя в этот момент вам, вероятно, лучше всего использовать case?.

ответил fru1tbat 17 PMpThu, 17 Apr 2014 18:27:16 +040027Thursday 2014, 18:27:16
5

Вкратце: это законный VHDL, и он обычно поддерживается инструментами синтеза.

Однако довольно необычно видеть, что он используется. Я действительно не знаю, почему. Ваш код кажется мне хорошим примером того, когда было бы целесообразно его использовать.

Однако существует один недостаток , о котором следует знать: при синтезе функции, управляющие выходами, где не заботятся, могут быть разными между циклами синтеза. Это делает синтез менее детерминированным. Если вы выбрали выходные данные, которые не были учтены (по ошибке), это может затруднить поиск ошибки.

Поддержка инструментов

По крайней мере, следующие инструменты будут принимать, не заботятся и не используют возможности оптимизации:

  • Xilinx (см .: «Руководство пользователя XST»)
  • Altera (ref .: «Рекомендуемые стили кодирования HDL»)
  • Synplify (см .: «Справочное руководство Synplify»)

Xilinx и Altera будут обрабатывать '-' и 'X' как не заботится, Synplify будет обрабатывать те и более того 'U' и 'W' (слабый), так как все равно.

ответил Carl 6 AM00000030000000331 2014, 03:00:03

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132