Як я можу вказати сигнали "не байдуже" у VHDL?


11

На курсах логічного дизайну ми всі дізналися, що можна мінімізувати логічну функцію, наприклад, використовуючи карту Карно або алгоритм Quine – McCluskey . Ми також дізналися, що значення "Небайдуже" збільшують потенціал мінімізації.

Наприклад, візьміть файл реєстру. write_addressІ write_dataсигнали на насправді не має значення , коли write_enableсигнал '0'. Таким чином, їм слід призначити значення "Небайдуже", щоб дозволити більше оптимізації в логіці, що рухає цими сигналами (тобто не в самому файлі реєстру).

Який правильний спосіб вказати такі значення "Небайдуже" у VHDL, щоб забезпечити інструменту синтезу більше місця для можливих оптимізацій?


Поки що я знайшов такі речі, які можуть бути підходящими. Але я не дуже впевнений, які плюси і мінуси кожного підходу:

  • Просто не призначаючи сигнал. Здається, це могло б спрацювати. Однак я виявив, що він не працює, коли потрібно визначити якийсь recordтип "не робити нічого постійного" , оскільки константи запису потрібно повністю вказати (принаймні, так говорить мені Модельсім).
  • std_logic_1164Пакет визначає значення '-' -- Don't careдля std_ulogic. Це виглядає так, що це семантично правильний вибір для явного "байдуже", але я ніколи не бачив, щоб він використовувався ніде (за винятком споріднених case?конструкцій VHDL-2008 ).
  • 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;

Не могли б ви детальніше зупинитися на тому, що ви намагаєтесь зробити write_addressі з write_data? Яку оптимізацію ви очікуєте провести?
fru1tbat

Я сподіваюся, що приклад дозволяє зрозуміти, чого я хочу досягти.
Фріц

Відповіді:


9

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

  • Звичайно, якщо не призначити сигнал, це не варіант для вашого прикладу, якщо ви не хочете засувок. Якщо це синхронізований процес, вам трохи краще, але ви все одно отримаєте можливість там, де вони вам не знадобляться. Можливо, я пропускаю тут ваш намір.

  • '-'як було зазначено раніше, мабуть, найкращий варіант як з семантичних, так і з практичних причин.

  • Залежить від того, що ви маєте на увазі під "невизначеним". '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?.


6

Коротше кажучи: це законний VHDL і зазвичай підтримується інструментами синтезу.

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

Однак є один недолік, про який слід пам’ятати: при синтезі функції, що керують виходами, де не задіяно байдуже, можуть бути різними між циклами синтезу. Це робить синтез менш детермінованим. Якщо виводи, визначені як небайдужі, використовуються (помилково), це може ускладнити пошук помилки.

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

Принаймні наступні інструменти прийматимуть небайдужі та використовуватимуть можливості оптимізації:

  • Xilinx (посилання: "Посібник користувача XST")
  • Altera (посилання: "Рекомендовані стилі кодування HDL")
  • Синхронізувати (посилання: "Синхронізувати довідник")

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


1
У мене було ще одне застосування цього недоліку. Код працював в симуляції, але не на FPGA, тому що мій код виглядає ось так: if signal = '1' then a; else b; end if;. На жаль, signalне було 1або 0а -. Тож у симуляції elseгілка була виконана, але в апаратному відношенні -виявилася така 1, тож справжня гілка була виконана ...
Фріц

Так, у мене були подібні помилки проходження моделювання, але найчастіше в моєму випадку є 'U's, поширені на початку моделювання, які використовуються, що призводить до того, що якийсь elseблок коду виконується. Було б чудово, якби умовні умови можна було якось зробити для розповсюдження 'U's, подібно до поведінки паралельних булевих виразів.
Карл

Після того, як я виявив цю помилку, я переконався, що завжди пишу щось подібне if signal = '1' then output <= '1'; elsif signal='0' then output <= '0'; else output <= '-'; end if;. І я додав наступні до всіх регістрів і пам'яті: assert not is_X(write_enable) report "we=" & str(A_write_enable) severity ERROR;і if write_enable = '1' then assert not is_X(write_addr) report "write_addr=str(write_addr) severity ERROR; end if;. Плюс те саме для write_data. Разом це повинно наздогнати майже всі ці помилки.
Фріц

Це спосіб, але це для мене занадто багатослівний. Я б хотів, щоб ця можливість була в межах мови VHDL.
Карл

1
Ну так, VHDL - трохи багатослівний, але це лише спосіб VHDL. : D З іншого боку, це також дуже явно, і не робить "чорної магії" за моєю спиною, що мені здається досить приємним (пор. Дзен Пітона "Явне краще, ніж неявне").
Фріц
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.