Na kursach z projektowania logicznego wszyscy dowiedzieliśmy się, że można zminimalizować funkcję logiczną, na przykład za pomocą mapy Karnaugh lub algorytmu Quine – McCluskey . Dowiedzieliśmy się również, że wartości „Don't Care” zwiększają potencjał minimalizacji.
Na przykład weź plik rejestru. write_address
I write_data
sygnały naprawdę nie ma znaczenia, gdy write_enable
sygnał jest '0'
. Dlatego należy im przypisać wartość „Don't Care”, aby umożliwić więcej optymalizacji w logice napędzającej te sygnały (tj. Nie w samym pliku rejestru).
Jaki jest prawidłowy sposób określenia takich wartości „Don't Care” w VHDL, aby pozwolić narzędziu syntezującemu więcej miejsca na możliwe optymalizacje?
Do tej pory znalazłem następujące rzeczy, które mogą być odpowiednie. Ale nie jestem pewien, jakie są zalety i wady każdego podejścia:
- Po prostu nie przypisuje sygnału. Wygląda na to, że może działać. Okazało się jednak, że nie działa, gdy chcesz zdefiniować pewnego rodzaju „stałą nic nie rób”
record
, ponieważ stałe zapisu muszą być w pełni określone (przynajmniej tak mówi mi Modelsim). std_logic_1164
Pakiet definiuje wartość'-' -- Don't care
dlastd_ulogic
. Wygląda na to, że jest to semantycznie poprawny wybór wyraźnego „nie przejmuj się”, ale nigdy nie widziałem, aby był używany nigdzie (z wyjątkiem niepowiązanychcase?
konstrukcji VHDL-2008 ).- Modeleim używa tej wartości
'X'
do wyświetlania niezdefiniowanych sygnałów. Nie jestem jednak pewien, czy narzędzia do syntezy rozumieją jawne'X'
przypisanie jako „nie przejmuj się”.
Oto uproszczony fragment kodu dla wyjaśnienia, w którym zainicjowałem sygnały „nie przejmuj się” '-'
.
Jak widać, sygnał control.reg_write_address
może mieć 3 różne wartości: "----"
, instruction(11 downto 8);
i instruction(3 downto 0);
. Teraz spodziewam się, że zostanie to zsyntetyzowane do multipleksera 2-wejściowego, jeśli '-'
zostanie zinterpretowane jako „nie obchodzi”. Gdybym zainicjował sygnał (others => '0')
zamiast '-'
, narzędzie musiałoby wygenerować 3-wejściowy multiplekser.
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
iwrite_data
? Jakiej optymalizacji oczekujesz?