Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

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

Weiter zum nächsten Tutorial »


VHDL

  1. So verwenden Sie eine Prozedur in einem Prozess in VHDL
  2. So verwenden Sie eine unreine Funktion in VHDL
  3. So verwenden Sie eine Funktion in VHDL
  4. So verwenden Sie eine Prozedur in VHDL
  5. So verwenden Sie Konstanten und generische Karten in VHDL
  6. So verwenden Sie die Port Map-Instanziierung in VHDL
  7. So verwenden Sie eine Case-When-Anweisung in VHDL
  8. So verwenden Sie signiert und unsigniert in VHDL
  9. So installieren Sie kostenlos einen VHDL-Simulator und -Editor
  10. PIC18-Mikrocontroller:Was er ist und wie er verwendet wird