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_addressI write_datasygnały naprawdę nie ma znaczenia, gdy write_enablesygnał 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_1164Pakiet definiuje wartość'-' -- Don't caredlastd_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_addressmoż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_addressiwrite_data? Jakiej optymalizacji oczekujesz?