So verwenden Sie Konstanten und generische Karten in VHDL
Das Erstellen von Modulen ist eine großartige Möglichkeit, Code wiederzuverwenden, aber oft benötigen Sie dasselbe Modul mit kleineren Variationen in Ihrem gesamten Design. Dafür sind Generika und die generische Karte da. Es erlaubt Ihnen, bestimmte Teile des Moduls zur Kompilierzeit konfigurierbar zu machen.
Konstanten werden verwendet, wenn wir vermeiden möchten, dass immer wieder derselbe Wert eingegeben wird. Sie können zum Definieren von Bitbreiten von Signalvektoren zur Kompilierzeit verwendet werden, und sie können sogar auch auf generische Konstanten abgebildet werden. Konstanten können anstelle von Signalen und Variablen überall im Code verwendet werden, aber ihre Werte können nach der Kompilierzeit nicht mehr geändert werden.
Dieser Blogpost ist Teil der Reihe Basic VHDL Tutorials.
Im vorherigen Tutorial haben wir ein Multiplexer-Modul mit 4 Eingängen und einer Busbreite von 8 Bit erstellt. Was aber, wenn wir auch einen ähnlichen MUX mit einer anderen Busbreite benötigen? Ist die einzige Lösung, den Code in ein neues Modul zu kopieren und einzufügen und die Nummern zu ändern?
Zum Glück nein.
Es ist möglich, Konstanten in VHDL mit dieser Syntax zu erstellen:constant <constant_name> : <type> := <value>;
Konstanten können zusammen mit Signalen im deklarativen Teil einer VHDL-Datei oder zusammen mit Variablen in einem Prozess deklariert werden.
Konstanten können mithilfe von generic
über die Entität an ein Modul übergeben werden Stichwort. Die Syntax zum Erstellen einer Entität für ein Modul, das generische Konstanten akzeptiert, lautet:entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
Die Syntax zum Instanziieren eines generischen Moduls in einer anderen VHDL-Datei lautet:<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
Übung
In diesem Video-Tutorial lernen wir, wie man ein Modul mit generischen Konstanten in VHDL erstellt und instanziiert:
Der endgültige Code für die generische MUX Testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMapTb is end entity; architecture sim of T16_GenericMapTb is constant DataWidth : integer := 8; signal Sig1 : signed(DataWidth-1 downto 0) := x"AA"; signal Sig2 : signed(DataWidth-1 downto 0) := x"BB"; signal Sig3 : signed(DataWidth-1 downto 0) := x"CC"; signal Sig4 : signed(DataWidth-1 downto 0) := x"DD"; signal Sel : signed(1 downto 0) := (others => '0'); signal Output : signed(DataWidth-1 downto 0); begin -- An Instance of T16_GenericMux with architecture rtl i_Mux1 : entity work.T16_GenericMux(rtl) generic map(DataWidth => DataWidth) port map( Sel => Sel, Sig1 => Sig1, Sig2 => Sig2, Sig3 => Sig3, Sig4 => Sig4, Output => Output); -- Testbench process process is begin wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= "UU"; wait; end process; end architecture;
Der endgültige Code für das generische MUX Modul :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMux is generic(DataWidth : integer); port( -- Inputs Sig1 : in signed(DataWidth-1 downto 0); Sig2 : in signed(DataWidth-1 downto 0); Sig3 : in signed(DataWidth-1 downto 0); Sig4 : in signed(DataWidth-1 downto 0); Sel : in signed(1 downto 0); -- Outputs Output : out signed(DataWidth-1 downto 0)); end entity; architecture rtl of T16_GenericMux is begin process(Sel, Sig1, Sig2, Sig3, Sig4) is begin case Sel is when "00" => Output <= Sig1; when "01" => Output <= Sig2; when "10" => Output <= Sig3; when "11" => Output <= Sig4; when others => -- 'U', 'X', '-', etc. Output <= (others => 'X'); end case; end process; end architecture;
Das Wellenformfenster in ModelSim, nachdem wir auf Ausführen gedrückt und die Zeitachse vergrößert haben:
Analyse
Wir haben ein MUX-Modul mit einer konfigurierbaren Busbreite erstellt. Jetzt wird die Busbreite nur noch an einer Stelle in der Testbench-Datei angegeben. Wir können es leicht ändern, um einen MUX mit einer anderen Busbreite zu erstellen.
Wenn wir die Wellenform mit der aus dem vorherigen Tutorial vergleichen, können wir sehen, dass das Verhalten identisch ist. Das liegt daran, dass wir das Verhalten des Codes überhaupt nicht geändert haben.
Imbiss
- Konstanten können verwendet werden, um die Hartcodierung von Werten an mehreren Stellen zu vermeiden
- Generika können verwendet werden, um Module anpassungsfähiger zu machen
Weiter zum nächsten Tutorial »
VHDL
- So verwenden Sie eine Prozedur in einem Prozess in VHDL
- So verwenden Sie eine unreine Funktion in VHDL
- So verwenden Sie eine Funktion in VHDL
- So verwenden Sie eine Prozedur in VHDL
- So verwenden Sie Konstanten und generische Karten in VHDL
- So verwenden Sie die Port Map-Instanziierung in VHDL
- So verwenden Sie eine Case-When-Anweisung in VHDL
- So verwenden Sie signiert und unsigniert in VHDL
- So installieren Sie kostenlos einen VHDL-Simulator und -Editor
- PIC18-Mikrocontroller:Was er ist und wie er verwendet wird