So erstellen Sie einen Timer in VHDL
In früheren Tutorials haben wir den wait for
verwendet Anweisung, um die Zeit in der Simulation zu verzögern. Aber was ist mit Produktionsmodulen? Die wait for
Aussage kann dafür nicht verwendet werden. Das funktioniert nur in der Simulation, weil wir den Elektronen in einem Stromkreis nicht einfach sagen können, dass sie für eine bestimmte Zeit pausieren sollen. Wie können wir also die Zeit in einem Designmodul im Auge behalten?
Die Antwort ist einfach das Zählen von Taktzyklen. Jedes digitale Design hat Zugriff auf ein Taktsignal, das mit einer festen, bekannten Frequenz schwingt. Wenn wir also wissen, dass die Taktfrequenz 100 MHz beträgt, können wir eine Sekunde messen, indem wir hundert Millionen Taktzyklen zählen.
Dieser Blogpost ist Teil der Reihe Basic VHDL Tutorials.
Um Sekunden in VHDL zu zählen, können wir einen Zähler implementieren, der die Anzahl der verstreichenden Taktperioden zählt. Wenn dieser Zähler den Wert der Taktfrequenz erreicht, beispielsweise 100 Millionen, wissen wir, dass eine Sekunde vergangen ist und es Zeit ist, einen weiteren Zähler zu erhöhen. Nennen wir dies den Sekundenzähler.
Um die Minuten zu zählen, können wir einen weiteren Minutenzähler implementieren, der nach Ablauf von 60 Sekunden hochzählt. Auf ähnliche Weise können wir einen Stundenzähler zum Zählen von Stunden erstellen, der nach Ablauf von 60 Minuten erhöht wird.
Wir können diesen Ansatz auch zum Zählen von Tagen, Wochen und Monaten fortsetzen. Wir sind durch die verfügbaren physischen Ressourcen in der zugrunde liegenden Technologie sowie durch die Länge des Zählers im Verhältnis zur Taktfrequenz begrenzt.
Je länger die Zähler werden, desto mehr Ressourcen werden natürlich verbraucht. Aber es wird auch langsamer reagieren, weil die Ereigniskette länger wird.
Übung
In diesem Video-Tutorial lernen wir, wie man ein Timer-Modul in VHDL erstellt:
Der endgültige Code für die Timer-Testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_TimerTb is end entity; architecture sim of T18_TimerTb is -- We're slowing down the clock to speed up simulation time constant ClockFrequencyHz : integer := 10; -- 10 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal Seconds : integer; signal Minutes : integer; signal Hours : integer; begin -- The Device Under Test (DUT) i_Timer : entity work.T18_Timer(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours); -- Process for generating the clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Take the DUT out of reset nRst <= '1'; wait; end process; end architecture;
Der endgültige Code für das Timer-Modul :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T18_Timer is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; -- Negative reset Seconds : inout integer; Minutes : inout integer; Hours : inout integer); end entity; architecture rtl of T18_Timer is -- Signal for counting clock periods signal Ticks : integer; begin process(Clk) is begin if rising_edge(Clk) then -- If the negative reset signal is active if nRst = '0' then Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0; else -- True once every second if Ticks = ClockFrequencyHz - 1 then Ticks <= 0; -- True once every minute if Seconds = 59 then Seconds <= 0; -- True once every hour if Minutes = 59 then Minutes <= 0; -- True once a day if Hours = 23 then Hours <= 0; else Hours <= Hours + 1; end if; else Minutes <= Minutes + 1; end if; else Seconds <= Seconds + 1; end if; else Ticks <= Ticks + 1; end if; end if; end if; end process; end architecture;
Die Wellenform wurde auf Seconds
vergrößert Signal:
Die Wellenform wurde auf Minutes
vergrößert Signal:
Die Wellenform wurde auf Hours
vergrößert Signal:
Analyse
Um eine 50-Stunden-Simulation auszuführen, haben wir den Befehl run 50 hr
gegeben in der ModelSim-Konsole. 50 Stunden sind eine wirklich lange Simulation, und deshalb mussten wir die Taktfrequenz in der Testbench auf 10 Hz senken. Hätten wir es bei 100 MHz belassen, hätte die Simulation Tage gedauert. Solche Anpassungen sind manchmal notwendig, damit wir ein Design simulieren können.
Wir haben mit der rechten Maustaste auf die Zeitleiste in der Wellenform geklickt und „Grid, Timeline &Cursor Control“ ausgewählt. Als wir die Zeiteinheit von ns auf Sekunden, Minuten und Stunden änderten, konnten wir sehen, dass der Timer tatsächlich in Echtzeit arbeitete.
Die Zeit des Timers ist wegen des Zurücksetzens des Moduls zu Beginn der Simulation leicht von der Simulationszeit versetzt. Es ist in der ersten Wellenform sichtbar, wo die 60-Sekunden-Markierung auf der Zeitachse kurz vor dem Übergang des Sekundensignals auf 0 liegt.
Beachten Sie, dass in der Simulation die Zählerwerte in Nullzeit an der steigenden Flanke der Uhr aktualisiert werden. In der realen Welt benötigt der Zählerwert einige Zeit, um sich vom ersten Bit des Zählers bis zum letzten auszubreiten. Wenn wir die Länge der Zähler erhöhen, verbrauchen wir die verfügbare Zeit einer Taktperiode.
Wenn die kumulierte Länge aller kaskadierten Zähler zu lang wird, wird nach der Kompilierung ein Fehler im Place-and-Route-Schritt erzeugt. Wie lange ein Zähler implementiert werden kann, bevor er die gesamte Taktperiode verbraucht, hängt von der FPGA- oder ASIC-Architektur und der Taktrate ab.
Eine erhöhte Taktgeschwindigkeit bedeutet, dass die Zählerkette länger wird. Es bedeutet auch, dass die Taktperiode kürzer ist, wodurch die Zählerkette noch weniger Zeit zum Abschließen hat.
Imbiss
- Die Zeitmessung in VHDL-Modulen erfolgt durch Zählen von Taktzyklen
- Das Senken der Taktfrequenz in der Testbench beschleunigt die Simulation
Weiter zum nächsten Tutorial »
VHDL
- So erstellen Sie eine Liste von Zeichenfolgen in VHDL
- So erstellen Sie eine Tcl-gesteuerte Testbench für ein VHDL-Code-Sperrmodul
- So stoppen Sie die Simulation in einer VHDL-Testbench
- So erstellen Sie einen PWM-Controller in VHDL
- So generieren Sie Zufallszahlen in VHDL
- So erstellen Sie einen Ringpuffer-FIFO in VHDL
- So erstellen Sie eine selbstüberprüfende Testbench
- So erstellen Sie eine verknüpfte Liste in VHDL
- So verwenden Sie eine Prozedur in einem Prozess in VHDL
- So verwenden Sie eine Funktion in VHDL