Sadržaj:

Basys3 FPGA digitalni audio sintetizator: 5 koraka
Basys3 FPGA digitalni audio sintetizator: 5 koraka

Video: Basys3 FPGA digitalni audio sintetizator: 5 koraka

Video: Basys3 FPGA digitalni audio sintetizator: 5 koraka
Video: Digital Audio Delay on an FPGA. 2024, Srpanj
Anonim
Image
Image
Basys3 FPGA digitalni audio sintetizator
Basys3 FPGA digitalni audio sintetizator
Basys3 FPGA digitalni audio sintetizator
Basys3 FPGA digitalni audio sintetizator

Ovaj digitalni sintesajzer tipkovnice s sinusnim valom prima korisničke unose putem niza trenutnih prekidača postavljenih poput tipkovnice i emitira audio val kroz zvučnik. Na temelju unosa korisnika, uređaj će generirati sinusne valove različitih frekvencija od C4 do C6. Korisnik može unijeti bilješke od C4 do C6 (ukupno 25 nota) i do četiri tipke istovremeno - ako se pritisne više od četiri tipke, svirat će se četiri najniža tona.

Ovaj projekt su uradili Ryan Morris i Mavis Tsoi za našu klasu digitalnog dizajna Cal Poly CPE 133:)

Korak 1: Teorija

FPGA ploča može izlaziti samo digitalne signale. Drugim riječima, može proizvesti samo visoki (3,3 V) napon ili nizak (0 V) napon. Međutim, audio signali su analogni i mogu imati beskonačno mnogo povećanja napona. Da bismo to zaobišli, upotrijebit ćemo PWM (pulsno -širinska modulacija) signal za emulaciju analognog vala. Ako ne znate što je PWM, pogledajte ovo:

Korak 2: Sastojci i alati

  • Računalo s instaliranim Vivadom
  • Koristit ćemo Vivado verziju 2017.2
  • Basys3 FPGA ploča
  • 25 graničnih sklopki SPDT (koristili smo ih)
  • 30 kratkospojnih žica (jedan kraj muški, drugi kraj nije bitan), 12 inča
  • Rezači žice
  • Skidači žica
  • Rezervna žica za lemljenje
  • Lemilo sa jezgrom od smole
  • Lemilica
  • ¼”ženski audio priključak
  • Pojačalo/zvučnik
  • Nešto za postavljanje prekidača (koristili smo protoboard + drvena kutija)

Korak 3: Postavljanje ožičenja i hardvera

Postavljanje ožičenja i hardvera
Postavljanje ožičenja i hardvera
Postavljanje ožičenja i hardvera
Postavljanje ožičenja i hardvera
Postavljanje ožičenja i hardvera
Postavljanje ožičenja i hardvera

Arhitektura sustava

Pogledajte sliku 1: 25 dostupnih ulaza → Basys3 ploča → pojačalo i zvučnik.

Izlaz

Pogledajte sliku 2: Basys3 ploča → 1/2 ženski audio priključak → zvučnik (s pojačalom)

Ulazni

Pmod veze na Basys3 ploči moraju biti spojene na masu kako bi se vidio nizak ulaz i neće raditi ispravno ako se ostavi kao otvoreni krug. Zbog toga moramo koristiti SPDT prekidače za sve naše tipke za bilješke. SPDT prekidač u osnovi omogućuje korisniku prebacivanje između krugova kada se pritisne, pa ćemo ih koristiti kao naše "gumbe" za unos niskih (0V) ili visokih (3.3V) signala na ploču Basys3.

Svaki prekidač će imati NO (normalno otvoren) priključak spojen na 3.3V, NC (normalno zatvoren) priključak spojen na GND i COM (zajednički) priključak spojen na FPGA ulaz. Pogledajte sliku 3.

Budući da imamo 25 krajnjih prekidača, svi će dijeliti zajedničku liniju od 3,3 V i zajedničku liniju GND. Zatim će se signalna linija sa svakog krajnjeg prekidača grupirati u grupe od 8 i spojiti na pmod veze na Basys3 ploči pomoću žica za spajanje koje se mogu preklopiti kako bi se smanjio monumentalni nered koji ćemo napraviti. Pogledajte sliku 4 ili primjer prvih osam tipki.

Korak 4: VHDL postavljanje (Vivado)

VHDL postavljanje (Vivado)
VHDL postavljanje (Vivado)
VHDL postavljanje (Vivado)
VHDL postavljanje (Vivado)

Generator sinusnog vala i PWM generator prvo su testirani kako bi bili sigurni da naš koncept funkcionira, a zatim su integrirani ograničivač ulaza i zbrojnik amplitude/mjenjač. Pojedinosti o funkciji i I/O svakom bloku procesa prikazane su na slici. Kod je prikazan u nastavku, ali također je priložen kao VHD i txt datoteke. Ako postoje odstupanja, idite s VHD datotekama.

BTW: Vjerojatno smo trebali skratiti retke, ali i umetanje koda u Instructables se pokazalo prilično neugodnim za rješavanje, pa razmak nije najveći i nema isticanja sintakse. Ako imate Vivado i želite slijediti kôd, toplo vam preporučujemo da preuzmete datoteku.

Prvo, pogledajmo modul Generator sinusnih valova.

knjižnica IEEE; koristite IEEE. STD_LOGIC_1164. ALL; koristiti IEEE. NUMERIC_STD. ALL; entitet Wave_Generator je Port (Okidač: u STD_LOGIC; - Pritisak tipke Freq_Cnt: u STD_LOGIC_VECTOR (15 do 0); - Vrijednost brojača = 100MHz / (Napomena Frekvencija*64 podjele sinusnog vala) (zaokruženo na najbliži broj) - preimenovano s Freq wavegenCLK: u STD_LOGIC; - Basys3 100MHz CLK WaveOut: van STD_LOGIC_VECTOR (9 do 0)); - Potpisana amplituda valnog kraja Wave_Generator; arhitektura Ponašanje Wave_Generatora je signal i: cjelobrojni raspon od 0 do 64: = 0; -indeks amplitude memorijske banke tipa memory_type je niz (0 do 63) cijelog raspona od -64 do 63; - stvoriti memorijsku banku (ROM) za držanje vrijednosti amplitude- pita li se ovaj RAM ili ROM … amplituda signala: memory_type: = (0, 7, 13, 19, 25, 30, 35, 40, 45, 49, 52, 55, 58, 60, 62, 63, 63, 63, 62, 60, 58, 55, 52, 49, 45, 40, 35, 30, 25, 19, 13, 7, 0, -7, -13, -19, -25, -30, -35, -40, -45, -49, -52, -55, -58, -60, -62, -63, -63, -63, -62, - 60, -58, -55, -52, -49, -45, -40, -35, -30, -25, -19, -13, -7); - amplitudna memorijska banka za početak procesa sinusnog vala (wavegenCLK, Trigger) varijabla brojač: unsigned (15 downto 0): = to_unsigned (0, 16); - brojač razdjelnika sata, preimenovan iz count1 begin if (rise_edge (wavegenCLK)) then if (Trigger = '1') then- tipka je pritisnuta counter: = counter + 1; if (brojač = bez potpisa (Freq_Cnt)) tada - Freq_Cnt = 100Mhz / (napomena učestalost * 64 podjele sinusnog vala) - resetirajte brojač i dodijelite podatke o amplitudi izlaznom brojaču: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (do_signed (amplituda (i), 10)); - prirast i za sljedeće čitanje i <= i + 1; - resetirati i ako je jedan sinusni val dovršen ako je (i = 63) tada je i <= 0; završi ako; završi ako; - (brojač = bez potpisa (Freq_Cnt)) else- tipka nije pritisnuta- resetirajte izlaz, indeks amplitude i brojač WaveOut <= "0000000000"; i <= 0; brojač: = to_unsigned (0, 16); -izlazna amplituda = -64 kada se ne svira nota; kraj ako; - (Trigger = '1') kraj if; - (rastući_rub (CLK)) završni proces; kraj Ponašanje;

Generirat ćemo digitalni sinusni val u Basys3 pomoću unutarnjeg sata i ROM -a. Ovaj ROM pohranit će 64 vrijednosti koje predstavljaju 64 amplitude na sinusnom valu. Pogledajte sliku 1. 64 vrijednosti koje koristimo oponašaju sinusni val s prilično dobrom rezolucijom.

Pomoću unutarnjeg sata računamo do vrijednosti koja predstavlja brzinu sata podijeljenu s frekvencijom vala koji želimo i 64: Clk div = 100MHz / (Freq * 64) Svaki put kada naš brojač dosegne tu vrijednost, zovemo broj iz ROM i poslati to iz našeg modula za generiranje valova. Učestalost našeg vala ovisit će o tome koliko brzo nazivamo te amplitude.

Imat ćemo 25 podmodula, svaki povezan s jednom frekvencijom/notom.

Evo preostalog koda koji poziva module Sine Wave Generator:

knjižnica IEEE; koristite IEEE. STD_LOGIC_1164. ALL; koristiti IEEE. NUMERIC_STD. ALL; entitet Two_Octave_Synth je Port (CLK: u STD_LOGIC; O4: u STD_LOGIC_VECTOR (11 prema dolje 0); O5: u STD_LOGIC_VECTOR (12 prema dolje 0); izlaz: van STD_LOGIC); kraj Two_Octave_Synth; arhitektura Ponašanje Two_Octave_Synth je komponenta Wave_Generator je Port (Okidač: u STD_LOGIC; Freq_Cnt: u STD_LOGIC_VECTOR (15 do 0); wavegenCLK: u STD_LOGIC; WaveOut: van STD_LOGIC_VECTOR (9 prema dolje); krajnja komponenta; --------------------------- izlazni signali iz generatora valova ------------------ ----- signal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveAs5, WaveB5, WaveC6: potpisano (9 do 0); ---------------------------------- za logiku odabira bilješke -------------- ------ signal C4, Cs4, D4, Ds4, E4, F4, Fs4, G4, Gs4, A4, As4, B4, C5, Cs5, D5, Ds5, E5, F5, Fs5, G5, Gs5, A5, As5, B5, C6: bez potpisa (4 do 0); signal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntF5, cntC5, cntC5, cnt5: unsigned (4 do 0); greška signala: STD_LOGIC; ----------------------------------- za dodavanje sinusnih valova ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: potpisan (9 prema dolje 0); --signali iz izlaznog signala modula Wave Generator WaveSum: STD_LOGIC_VECTOR (9 do 0); --signal za sumirane sinusne valove (kompliment 2 od -512 do 511) signal pozitivan WaveSum: STD_LOGIC_VECTOR (9 do 0); --značeno 0 do 1023, za uporabu u PWM generatoru ----------------------------------- za generiranje PWM ------------------------------- signal ping_length: unsigned (9 downto 0): = unsigned (positiveWaveSum); --signal off_length: unsigned (6 downto 0): = to_unsigned (127, 7) -unsigned (WAVE); signal PWM: bez znaka (9 do 0): = do_znaka (0, 10); početi Note_C4: Mapa porta Wave_Generator (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, potpisana (WaveOut) => WaveC4); --5973, 261.63 Hz Note_Cs4: Karta porta generatora talasa (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, potpisana (WaveOut) => WaveCs4);-5638, 277.18 Hz Note_D4: Mapa porta Wave_Generator (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, potpisano (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Karta porta Wave_Generator (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, potpisana (WaveOut) => WaveDs4);-5023, 311.13 Hz Note_E4: Karta porta Wave_Generator (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, potpisana (WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Karta porta Wave_Generator (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, potpisana (WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Karta porta Wave_Generator (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, potpisana (WaveOut) => WaveFs4);-4224, 369.99 Hz Note_G4: Karta porta Wave_Generator (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, potpisana (WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Karta porta Wave_Generator (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, potpisana (WaveOut) => WaveGs4);-3763, 415.30 Hz Note_A4: Mapa porta Wave_Generator (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, potpisano (WaveOut) => WaveA4); --3552, 440.00 Hz Note_As4: Karta porta Wave_Generator (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, potpisana (WaveOut) => WaveAs4);-3352, 466.16 Hz Note_B4: Mapa porta Wave_Generator (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, potpisano (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Napomena_C5: Karta porta Wave_Generator (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, potpisan (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Karta porta Wave_Generator (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, potpisana (WaveOut) => WaveCs5);-2819, 554.37 Hz Note_D5: Karta porta Wave_Generator (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, potpisana (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Karta porta Wave_Generator (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, potpisana (WaveOut) => WaveDs5);-2512, 622.25 Hz Note_E5: Mapa porta Wave_Generator (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, potpisano (WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Karta porta Wave_Generator (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, potpisana (WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Karta porta Wave_Generator (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, potpisana (WaveOut) => WaveFs5);-2112, 739.99 Hz Note_G5: Karta porta Wave_Generator (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, potpisana (WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Karta porta Wave_Generator (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, potpisana (WaveOut) => WaveGs5);-1882, 830.61 Hz Note_A5: Mapa porta Wave_Generator (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, potpisana (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Karta porta Wave_Generator (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, potpisana (WaveOut) => WaveAs5);-1676, 932.33 Hz Note_B5: Karta porta Wave_Generator (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, potpisana (WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Mapa porta Wave_Generator (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, potpisano (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ logika odabira bilješke ------------ C4 <= "0000" & O4 (0); Cs4 <= "0000" & O4 (1); D4 <= "0000" & O4 (2); Ds4 <= "0000" & O4 (3); E4 <= "0000" & O4 (4); F4 <= "0000" & O4 (5); Fs4 <= "0000" & O4 (6); G4 <= "0000" & O4 (7); Gs4 <= "0000" & O4 (8); A4 <= "0000" & O4 (9); As4 <= "0000" & O4 (10); B4 <= "0000" & O4 (11); C5 <= "0000" & O5 (0); Cs5 <= "0000" & O5 (1); D5 <= "0000" & O5 (2); Ds5 <= "0000" & O5 (3); E5 <= "0000" & O5 (4); F5 <= "0000" & O5 (5); Fs5 <= "0000" & O5 (6); G5 <= "0000" & O5 (7); Gs5 <= "0000" & O5 (8); A5 <= "0000" & O5 (9); As5 <= "0000" & O5 (10); B5 <= "0000" & O5 (11); C6 <= "0000" & O5 (12); cntC4 <= C4; cntCs4 <= C4 + Cs4; cntD4 <= C4 + Cs4 + D4; cntDs4 <= C4 + Cs4 + D4 + Ds4; cntE4 <= C4 + Cs4 + D4 + Ds4 + E4; cntF4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4; cntFs4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4; cntG4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4; cntGs4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4; cntA4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4; cntAs4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4; cntB4 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4; cntC5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5; cntCs5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5; cntD5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5; cntDs5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5; cntE5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5; cntF5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5; cntFs5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5; cntG5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5; cntGs5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5 + Gs5; cntA5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5 + Gs5 + A5; cntAs5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5 + Gs5 + A5 + As5; cntB5 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5 + Gs5 + A5 + As5 + B5; cntC6 <= C4 + Cs4 + D4 + Ds4 + E4 + F4 + Fs4 + G4 + Gs4 + A4 + As4 + B4 + C5 + Cs5 + D5 + Ds5 + E5 + F5 + Fs5 + G5 + Gs5 + A5 + As5 + B5 + C6; Odabir: proces (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) započinju ako (cntC6 = "00000") onda --------------- ako se ne generiraju signali Wave0 <= "0000000000"; Val1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; inace if (O4 (0) = '1') then ------------------- note C4 svira Wave0 Wave0 Wave1 error1 Wave0 Wave1 Wave2 error2 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Greška Wave2 Wave3 Wave0 Wave1 Wave2 Wave2 Wave3 Wave3 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave3 Wave2 Wave3 Wave2 Wave2 Wave2 Wave3 Wave2 Wave3 Wave2 Greška Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 Wave3 Wave3 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 = WaveC6; Val1 <= "0000000000"; Wave2 <= "0000000000"; Val3 val1 <= valC6; Wave2 <= "0000000000"; Val3 val2 <= valC6; Wave3 Greška Wave3 Wave1 <= "0000000000"; Wave2 <= "0000000000"; Val3 val2 <= "0000000000"; Wave3 Wave3 error <= '1'; završni slučaj; završi ako; završi ako; završetak procesa; ------------- zbrajač sinusnih valova -------------------- WaveSum <= STD_LOGIC_VECTOR (val0 + val1 + val2 + val3); --------- napraviti sinusni val pozitivan za pwm --------------------- positiveWaveSum <= nije WaveSum (9) & WaveSum (8 downto 0); ------------- PWM generator --------------------- proces (CLK)-varijabilni broj: bez potpisa (1 do 0): = to_unsigned (0, 2); započeti if (rastući_rub (CLK)) tada --count: = count + 1; --if (count = to_unsigned (4, 2)) then --count: = to_unsigned (0, 2); --if (PWM = to_ if (PWM <ping_length) then output <= '1'; else output <= '0'; end if; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end if; end if; end process; end Bihevioral;

4 Birač bilješki Najteži dio ovog projekta je odabir samo četiri frekvencije. Učinili smo to s cijelim lotta IF iskazima, a umjesto varijabli smo koristili signale kako bi se proces mogao simulirati i otkloniti pogreške. Pokušali smo s drugim metodama koristeći varijable i FOR petlje, ali smo naišli na pogreške tijekom izvođenja. Stoga smo na kraju odlučili da ćemo, ako uspije, ostaviti to na miru. Nemojte popravljati ono što nije slomljeni amirit?

Četiri izlazna vala označena su s Wave0, Wave1, Wave2, Wave3 - to je ono što će se zbrojiti u konačni izlaz.

Gledajući kôd, vidjet ćete hrpu signala označenih sa C4, Cs4, D4, Ds4 itd. To su 5-bitni signali koji preuzimaju odgovarajući okidač iz O4 (oktava 4) ili O5 (oktava 5) i čine ih 5-bitni za dodavanje.

Zatim varijable cntC4, cntCs4 itd. Predstavljaju koliko je nota odsvirano niže od ciljne note, uključujući ciljnu notu. Na primjer, ako se sviraju C4, E4, G4, A#4 i D5 (akord C9) cntC4 će biti 1, cntE4 će biti 2, cntG4 će biti 3 itd.

Zatim će se, kad god se svira nota, ispitati broj ciljne note kako bi se vidjelo gdje treba spojiti signal note. Na primjer, ako se svira nota D5 (što znači da je O5 (2) visoka) i cntD5 je 3, tada se trenutno sviraju 3 note, s 2 note niže od D5, pa ćemo spojiti valD5 na val 2 (treći val) brojanje signala iz vala0). Alternativno, ako je cntD5 5, tada se trenutno svira 5 nota, pri čemu su 4 note niže od D5, pa ćemo jednostavno ostaviti waveD5 da visi i nećemo ništa učiniti s njim.

Izjave IF se zatim ponavljaju kako bi se pokrili slučajevi za svih 25 nota.

Zbrojivač amplitude

Nakon što su odabrana 4 najniža vala, moramo ih zbrojiti. Razlog zašto ćemo dodati samo četiri note zajedno je taj što ideja PWM -a koju koristimo za svoj izlaz može imati samo određenu razlučivost sve dok PWM ne radi presporo i zvučnik će početi pokupiti kvadratni val PWM -a. Na primjer, ako bismo koristili rezoluciju od 8192 (13 bita), svaka od tih 8192 točaka mora odgovarati rastućem rubu ugrađenog sata. Dakle, 100MHz / 8192 = 12,2kHz, što je sasvim u rasponu ljudskog sluha.

Stvarno zbrajanje amplituda je super jednostavno, samo morate biti sigurni da može raditi jako brzo.

PWM izlaz

Radni ciklus PWM -a predstavljat će amplitudu našeg izlaznog vala u tom trenutku. Na primjer, ako imamo raspon amplituda od 0 do 128, 0 bi bilo 0%radni ciklus, 64 bi bilo 50%, 128 bi bilo 100%itd. Ovaj PWM će raditi izuzetno brzo (naš je 97,6 kHz), toliko brzo da zvučnik neće prepoznati pojedinačne kvadratne valove i umjesto toga pogledati prosječni napon, stvarajući naš "analogni" signal.

Datoteka ograničenja

Možda ste drukčije spojili svoj hardver pa samo provjerite podudara li se datoteka s ograničenjima.

Korak 5: Preuzimanje koda

Ispod je kôd, u.txt formatu i.vhd za Vivado. Wave_Generator je podmodul generatora valova, a Two_Octave_Synth je top modul sa svime ostalim.

Preporučeni: