Generatore di Onda Quadra Parametrikabile in VHDL
Generatore di Onda Quadra Sintetizzabile in VHDL
Di seguito un'implementazione pulita e parametrikabile usando un approccio basato su contatore. Supporta la regolazione della frequenza in tempo reale tramite una porta di ingresso e include un reset sincrono attivo alto.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity square_wave_gen is generic ( CLK_FREQ_HZ : positive := 50_000_000; -- Frequenza orologio in ingresso CNT_WIDTH : positive := 24 -- Larghezza contatore (periodo massimo) ); port ( clk : in std_logic; rst_n : in std_logic; -- Reset sincrono attivo basso freq_hz : in positive range 1 to CLK_FREQ_HZ/2; -- Frequenza di uscita wave_out : out std_logic ); end entity square_wave_gen; architecture rtl of square_wave_gen is constant MAX_CNT : natural := CLK_FREQ_HZ / 2; -- Semi-periodo massimo a 1 Hz signal half_period : natural range 1 to MAX_CNT; signal ctr : natural range 0 to MAX_CNT; begin -- Calcolo combinatorio semi-periodo (sintetizza come divisore o LUT) half_period <= CLK_FREQ_HZ / (2 * freq_hz); process (clk) begin if rising_edge(clk) then if rst_n = '0' then ctr <= 0; wave_out <= '0'; elsif ctr = half_period - 1 then ctr <= 0; wave_out <= not wave_out; else ctr <= ctr + 1; end if; end if; end process; end architecture rtl; Note di Progettazione
- Generici:
CLK_FREQ_HZeCNT_WIDTHlo rendono portabile su diversi domini di orologio (es. 50 MHz, 100 MHz, 125 MHz). - Frequenza in Tempo Reale: l'ingresso
freq_hzconsente riconfigurazione dinamica (es. da CPU, UART, DIP switch). Range vincolato a valori validi. - Reset Attivo Basso:
rst_nsegue la convenzione FPGA comune; sincrono per chiusura di temporizzazione. - Ciclo di Lavoro 50%: Il contatore commuta l'uscita a
half_period→ onda quadra simmetrica. - Nessun Latch: Completamente sincrono, singolo processo a singolo orologio.
- Utilizzo Risorse: ~1 registro contatore + comparatore + addizionatore + 1 FF. Minimi LUT/FF.
Snippet di Testbench
-- Stimolo: clk 50 MHz, genera 1 kHz → 10 kHz → 100 kHz freq_hz <= 1_000; wait for 5 ms; freq_hz <= 10_000; wait for 5 ms; freq_hz <= 100_000; wait for 5 ms; Errori Comuni da Evitare
- Usare
std_logic_vectorper la frequenza senza conversioneunsigned. - Codificare in modo fisso la frequenza di orologio (usare generico).
- Reset asincrono senza gestione CDC adeguata.
- Dimenticare il confronto
half_period - 1(off-by-one → errore di frequenza). - Non vincolare il range
freq_hz→ sintesi inferisce divisore enorme.
Estensioni
- Aggiungere generico/ingresso
duty_cycleper PWM (contatori separati alto/basso). - Aggiungere
phase_offsetper generazione multifase. - Usare slice DSP per divisione se
CLK_FREQ_HZè grande e il range dinamico è ampio.