In Logic Design-Kursen haben wir alle gelernt, dass es möglich ist, eine Logikfunktion zu minimieren, beispielsweise mithilfe einer Karnaugh-Karte oder des Quine-McCluskey-Algorithmus . Wir haben auch erfahren, dass "Don't Care" -Werte das Minimierungspotential erhöhen.
Nehmen Sie zum Beispiel eine Registerdatei. Die write_address
und write_data
Signale spielen keine Rolle, wann das write_enable
Signal ist '0'
. Daher sollte ihnen ein "Don't Care" -Wert zugewiesen werden, um weitere Optimierungen in der Logik zu ermöglichen, die diese Signale steuert (dh nicht in der Registerdatei selbst).
Wie können solche "Don't Care" -Werte in VHDL korrekt angegeben werden, damit das Synthesewerkzeug mehr Raum für mögliche Optimierungen bietet?
Bisher habe ich die folgenden Dinge gefunden, die geeignet sein könnten. Ich bin mir jedoch nicht sicher, welche Vor- und Nachteile die einzelnen Ansätze haben:
- Das Signal einfach nicht zuweisen. Dies scheint zu funktionieren. Ich habe jedoch festgestellt, dass es nicht funktioniert, wenn Sie eine Art "Nichts tun-Konstante" definieren möchten
record
, da Datensatzkonstanten vollständig angegeben werden müssen (zumindest Modelsim sagt es mir). - Das
std_logic_1164
Paket definiert den Wert'-' -- Don't care
fürstd_ulogic
. Dies scheint die semantisch korrekte Wahl für ein explizites "egal" zu sein, aber ich habe noch nie gesehen, dass es irgendwo verwendet wird (außer in den nicht verwandten VHDL-2008-case?
Konstrukten). - Modelsim verwendet den Wert
'X'
, um undefinierte Signale anzuzeigen. Ich bin mir jedoch nicht sicher, ob Synthesewerkzeuge eine explizite'X'
Zuordnung als "egal" verstehen .
Hier ist ein stark vereinfachtes Code-Snippet zur Verdeutlichung, mit dem ich die nicht interessierenden Signale initialisiert habe '-'
.
Wie Sie sehen können, das Signal control.reg_write_address
kann drei verschiedene Werte annehmen: "----"
, instruction(11 downto 8);
und instruction(3 downto 0);
. Jetzt würde ich erwarten, dass dies zu einem Multiplexer mit 2 Eingängen synthetisiert wird, wenn dies '-'
als "egal" interpretiert wird. Hätte ich das Signal (others => '0')
stattdessen mit initialisiert '-'
, müsste das Tool stattdessen einen Multiplexer mit 3 Eingängen erzeugen.
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
und tun möchtenwrite_data
? Welche Optimierung erwarten Sie?