In questo breve articolo, descriverò una tecnica semplice quanto efficace per generare una forma d'onda arbitraria e periodica. Per fare ciò dobbiamo prendere in esame i sintetizzatori digitali.
Partiamo da una considerazione: una forma d'onda è l'espressione di una funzione nel dominio del tempo. Se pensiamo ad una sinusoide, ad esempio, la funzione sarà: sin(wt); per wt (omega * T) che va da 0 a 2 PI.
(Onde sinusoidali)
(Onde triangolari)
(Onda a Dente di Sega)
Come possiamo realizzare attraverso un circuito elettronico una simile funzione?
La risposta più immediata è: creiamo una tabella ROM (Read Only Memory) al cui interno siamo presenti tutti i valori della funzione matematica desiderata e, poi, estraiamo uno per volta tali valori fino al completamento di un periodo temporale preimpostato, convertiamo i valori numerici in un segnale analogico (es. mediante un DAC - Digital to Analog Converter) e ...avremo ottenuto la nostra forma d'onda sintetica.
Nella realtà avremo bisogno di un Circuito Integrato dedicato (ASSP - Application Specific Standard Circuit) oppure potremo realizzare il sintetizzatore di forme d'onda mediante un circuito integrato programmabile (es. un FPGA - Field Programmable Gate Array).
Nelle prossime immagini vediamo lo schema di una implementazione su FPGA:
(FPGA Top - Click per ingrandire)
(Blocco DPRAM su FPGA - Click per ingrandire)
Il circuito DDS si basa sul principio dell'Accumulatore di Fase, tale accumulatore può agevolmente essere implementato in linguaggio VHDL (VLSI Hardware Description Language) ...di cui Vi riporto il codice:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity PHASE_ACC is
Port ( clock : in STD_LOGIC;
reset : in STD_LOGIC;
load : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (31 downto 0);
addr : out STD_LOGIC_VECTOR (10 downto 0));
end PHASE_ACC;
architecture Behavioral of PHASE_ACC is
signal phase_accum : STD_LOGIC_VECTOR (31 downto 0);
signal phase_delta : STD_LOGIC_VECTOR (31 downto 0);
begin
process (clock, reset)
begin
if reset='1' then
addr <= (others => '0');
elsif clock='1' and clock'event then
addr <= phase_accum (31 downto 21);
end if;
end process;
process (clock, load)
begin
if load = '1' then
phase_delta <= data;
elsif clock='0' and clock'event then
phase_accum <= phase_accum + phase_delta;
end if;
end process;
end Behavioral;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity PHASE_ACC is
Port ( clock : in STD_LOGIC;
reset : in STD_LOGIC;
load : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (31 downto 0);
addr : out STD_LOGIC_VECTOR (10 downto 0));
end PHASE_ACC;
architecture Behavioral of PHASE_ACC is
signal phase_accum : STD_LOGIC_VECTOR (31 downto 0);
signal phase_delta : STD_LOGIC_VECTOR (31 downto 0);
begin
process (clock, reset)
begin
if reset='1' then
addr <= (others => '0');
elsif clock='1' and clock'event then
addr <= phase_accum (31 downto 21);
end if;
end process;
process (clock, load)
begin
if load = '1' then
phase_delta <= data;
elsif clock='0' and clock'event then
phase_accum <= phase_accum + phase_delta;
end if;
end process;
end Behavioral;
Ma come è possibile generare una sinusoide?
Semplice, quardiamo questa funzione in codice ANSI C:
/* load a sine wave in FPGA wavetable*/
void load_sine(void) {
const float pi = 3.141592f;
float phase_vector = 0.0f;
float phase_delta = 0.0f;
unsigned int i; //generic counter
/* reset DPRAM address generator */
WriteEXB(0x01, 0x02); //bit 0, addr 2
phase_delta = (2.0f * pi) / 2048.0f;
for (i=0; i<2048; i++) {
WriteEXB((unsigned char)(round(sin(phase_vector) * 127.5f)
void load_sine(void) {
const float pi = 3.141592f;
float phase_vector = 0.0f;
float phase_delta = 0.0f;
unsigned int i; //generic counter
/* reset DPRAM address generator */
WriteEXB(0x01, 0x02); //bit 0, addr 2
phase_delta = (2.0f * pi) / 2048.0f;
for (i=0; i<2048; i++) {
WriteEXB((unsigned char)(round(sin(phase_vector) * 127.5f)
+ 127.0f), 0x01);
phase_vector = phase_vector + phase_delta;
}
return;
}
phase_vector = phase_vector + phase_delta;
}
return;
}
Tornerò prossimamanete a parlare delle applicazioni del DDS ...adesso sono in partenza, nuove avventure mi attendono.
Qui Pianeta Terra, un mondo analogico... a presto!