Zuverlässigen Timer in VHDL bauen: Taktzyklen bis Stunden zählen
In früheren Tutorials nutzten wir wait for für Simulationsverzögerungen. In echten Designs unbrauchbar – echte Schaltungen lassen sich nicht anweisen zu pausieren. Praktischer Weg: Taktzyklen zählen.
Jedes digitale Design hat einen stabilen Takt bekannter Frequenz. Bei 100 MHz entsprechen 100 Mio. Takte einer Sekunde. Durch Zählen dieser Takte lassen sich Sekunden, Minuten, Stunden zuverlässig erzeugen.
Teil der Basic VHDL Tutorials Serie.
Implementierung: Zähler inkrementiert an jeder steigenden Taktflanke. Erreicht er den Taktfrequenz-Wert, ist eine Sekunde vergangen → Sekundenzähler inkrementieren. Analog für Minuten (nach 60 s) und Stunden (nach 60 min). Weitere Zähler für Tage/Wochen/Monate kettenartig anhängbar – begrenzt nur durch FPGA/ASIC-Ressourcen und Zählerbreite.
Längere Zähler verbrauchen mehr Logik und erhöhen Laufzeitverzögerung. Kritischer Pfad durch Zählerkette muss in Taktperiode passen, sonst Synthese-Fehler.
Übung: Timer implementieren
Testbench mit 10 Hz-Takt für schnelle Simulation. DUT gibt Seconds, Minutes, Hours aus.
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
constant ClockFrequencyHz : integer := 10;
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
i_Timer : entity work.T18_Timer(rtl)
generic map(ClockFrequencyHz => ClockFrequencyHz)
port map (Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours);
Clk <= not Clk after ClockPeriod / 2;
process is
begin
wait until rising_edge(Clk);
wait until rising_edge(Clk);
nRst <= '1';
wait;
end process;
end architecture;
Timer-Modul: Zählt Ticks, Sekunden, Minuten, Stunden; Reset bei nRst.
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;
Seconds : inout integer;
Minutes : inout integer;
Hours : inout integer
);
end entity;
architecture rtl of T18_Timer is
signal Ticks : integer;
begin
process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0;
else
if Ticks = ClockFrequencyHz - 1 then
Ticks <= 0;
if Seconds = 59 then
Seconds <= 0;
if Minutes = 59 then
Minutes <= 0;
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;
Wellenformen bestätigen: Seconds inkrementiert jeden Tick, Minutes nach 60 s, Hours nach 60 min.
Simulation: run 50 hr in ModelSim bei 10 Hz für handhabbare Laufzeit. Taktfrequenz in Testbench anzupassen ist gängige Strategie zur Beschleunigung.
In Hardware muss Zählerkette innerhalb einer Taktperiode abschließen. Mit wachsender Zählerbreite steigt Laufzeitverzögerung, kann Periode überschreiten → Timing-Violations. Exaktes Limit hängt von FPGA/ASIC-Familie und Taktrate ab.
Kernpunkte
- Zeitmessung in VHDL durch Taktzykluszählen.
- Testbench-Taktfrequenz senken beschleunigt Simulation ohne Designänderung.
Nächstes Tutorial: Erweiterte Timer-Features.
VHDL
- String-Listen in VHDL erstellen: Best Practices & Beispiel
- Tcl-gesteuerter Testbench für ein VHDL Code-Lock-Modul erstellen
- VHDL-Testbench-Simulation sauber beenden
- PWM-Controller in VHDL implementieren: Design, Simulation & FPGA-Demo
- Zufallszahlen in VHDL generieren: Von Uniform zu OSVVM
- Ein robuster VHDL-Ringpuffer-FIFO im Block-RAM entwerfen
- Selbstprüfenden VHDL-Testbench erstellen – Praxisleitfaden
- Dynamische verkettete Liste in VHDL mit Protected Types und Access-Pointern
- In-Prozess-Prozeduren für saubere VHDL-FSM-Entwürfe nutzen
- VHDL-Funktionen meistern: Praktischer Leitfaden für effizientes Design