Sadržaj:

Basys3 FPGA digitalni audio sintisajzer: 5 koraka
Basys3 FPGA digitalni audio sintisajzer: 5 koraka

Video: Basys3 FPGA digitalni audio sintisajzer: 5 koraka

Video: Basys3 FPGA digitalni audio sintisajzer: 5 koraka
Video: Basys 3 Board Keyboard Synthesizer Fun 2024, Juli
Anonim
Image
Image
Basys3 FPGA digitalni audio sintisajzer
Basys3 FPGA digitalni audio sintisajzer
Basys3 FPGA digitalni audio sintisajzer
Basys3 FPGA digitalni audio sintisajzer

Ovaj digitalni sintesajzer s tastaturom sinusnog talasa će primati unose korisnika putem niza trenutnih prekidača postavljenih poput tastature i emitovati audio talas kroz zvučnik. Na temelju unosa korisnika, uređaj će generirati sinusne valove različitih frekvencija od C4 do C6. Korisnik može unijeti note 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čunar sa instaliranim Vivadom
  • Koristit ćemo Vivado verziju 2017.2
  • Basys3 FPGA ploča
  • 25 graničnih prekidača SPDT (koristili smo ih)
  • 30 kratkospojnih žica (jedan kraj muški, drugi kraj nije bitan), 12 inča
  • Rezači žice
  • Strojevi za skidanje žice
  • Rezervna žica za lemljenje
  • Lemljenje sa jezgrom od smole
  • Lemilica
  • ¼”ženski audio priključak
  • Pojačalo/zvučnik
  • Nešto za postavljanje prekidača (koristili smo protoboard + drvenu kutiju)

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 sistema

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

Output

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

Ulaz

Pmod veze na Basys3 ploči moraju biti spojene na masu kako bi se vidio nizak ulaz i neće raditi ispravno ako se ostave kao otvoreni krug. Zbog toga moramo koristiti SPDT prekidače za sve naše tipke za bilješke. SPDT prekidač u osnovi dopušta korisniku da se prebacuje između krugova kada se pritisne, pa ćemo ih koristiti kao naše "tipke" 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 premosnih žica koje se mogu preklopiti kako bi se smanjio monumentalni nered koji ćemo napraviti. Pogledajte sliku 4 ili primjer prvih osam ključeva.

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 sabirač amplitude/mjenjač. Detalji o funkciji i U/I svakom procesnom bloku prikazani su na slici. Kôd je prikazan u nastavku, ali je priložen i kao VHD i txt datoteke. Ako postoje odstupanja, idite na VHD datoteke.

BTW: Vjerovatno smo trebali skratiti redove, ali i umetanje koda u Instructables se pokazalo prilično neugodnim za rješavanje, tako da 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.

biblioteka IEEE; koristite IEEE. STD_LOGIC_1164. ALL; koristiti IEEE. NUMERIC_STD. ALL; entitet Wave_Generator je Port (Okidač: u STD_LOGIC; - Pritisnite tipku 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 iz Freq wavegenCLK: u STD_LOGIC; - Basys3 100MHz CLK WaveOut: van STD_LOGIC_VECTOR (9 do 0)); - Potpisana amplituda talasnog kraja Wave_Generator; arhitektura Ponašanje Wave_Generator -a je signal i: cijeli broj od 0 do 64: = 0; -indeks amplitudne memorijske banke tipa memory_type je niz (0 do 63) cijelog raspona -64 do 63; - stvorite memorijsku banku (ROM) koja će držati 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 talasa (wavegenCLK, Trigger) brojač varijabli: 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 / (obratite pažnju na učestalost * 64 podjele sinusnog vala) - resetirajte brojač i dodijelite podatke o amplitudi izlaznom brojaču: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitude (i), 10)); - prirast i za sljedeće čitanje i <= i + 1; - resetirati i ako je završen jedan sinusni val ako je (i = 63) tada je i <= 0; end if; end if; - (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; - (Trigger = '1') kraj if; - (rastući_rub (CLK)) završni proces; end Behavioral;

Generirat ćemo digitalni sinusni val u Basys3 pomoću internog sata i ROM -a. Ovaj ROM će pohraniti 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.

Koristeći interni sat, računamo na vrijednost 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, pozivamo broj iz ROM -a i pošaljite 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 generatora sinusnog talasa:

biblioteka 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 note -------------- ------ 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, cnt5, cnt5, cnt5, cnt5: unsigned (4 do 0); greška signala: STD_LOGIC; ----------------------------------- za dodavanje sinusnih valova ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: potpisan (9 do 0); --signali iz izlaznog signala modula Wave Generator WaveSum: STD_LOGIC_VECTOR (9 do 0); --signal za sumirane sinusne valove (kompliment 2 -kompliment -512 do 511) signal pozitivan WaveSum: STD_LOGIC_VECTOR (9 do 0); --značeno 0 do 1023, za upotrebu 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); započ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: Mapa porta Wave_Generator (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, potpisano (WaveOut) => WaveCs4);-5638, 277.18 Hz Note_D4: Mapa porta Wave_Generator (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, potpisana (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Mapa porta Wave_Generator (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, potpisano (WaveOut) => WaveDs4);-5023, 311.13 Hz Note_E4: Mapa porta Wave_Generator (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, potpisano (WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Mapa porta Wave_Generator (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, potpisano (WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Mapa porta Wave_Generator (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, potpisano (WaveOut) => WaveFs4);-4224, 369.99 Hz Note_G4: Mapa porta Wave_Generator (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, potpisano (WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Mapa 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: Mapa 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 -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Mapa porta Wave_Generator (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, potpisan (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Mapa porta Wave_Generator (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, potpisana (WaveOut) => WaveCs5);-2819, 554.37 Hz Note_D5: Mapa porta Wave_Generator (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, potpisano (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Mapa 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: Mapa porta Wave_Generator (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, potpisano (WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Mapa porta Wave_Generator (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, potpisana (WaveOut) => WaveFs5);-2112, 739.99 Hz Note_G5: Mapa porta Wave_Generator (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, potpisano (WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Mapa 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, potpisano (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Mapa porta Wave_Generator (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, potpisano (WaveOut) => WaveAs5);-1676, 932.33 Hz Note_B5: Mapa porta Wave_Generator (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, potpisano (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, Wave5, Wave5 WaveB5, WaveC6) započinju ako (cntC6 = "00000") onda --------------- ako se ne generiraju signali Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; inace if (O4 (0) = '1') then ------------------- note C4 svira Wave0 Wave0 Wave1 error1 Wave0 Wave1 Wave2 error 2 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Greška Wave2 Wave3 Wave0 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Greška Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Greška Wave3 Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 error <= '1'; završni slučaj; end if; end if; završni proces; ------------- sabirač sinusnih valova -------------------- WaveSum <= STD_LOGIC_VECTOR (Talas0 + Talas1 + Talas2 + Talas3); --------- 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 Bihevioralni;

4 Selektor bilješki Najteži dio ovog projekta je odabir samo četiri frekvencije. Učinili smo to s čitavim nizom IF naredbi, a umjesto varijabli smo koristili signale tako da se proces može simulirati i otkloniti pogreške. Isprobali smo druge metode koristeći varijable i FOR petlje, ali smo naišli na greške pri izvođenju. Tako smo na kraju odlučili da ako uspije, ostavimo to na miru. Ne popravljajte ono što nije pokvaren amirit?

Četiri izlazna vala su označena kao Wave0, Wave1, Wave2, Wave3 - to je ono što će se zbrajati kako bi se formirao konačni izlaz.

Gledajući kod, 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 niže od ciljne note odsvirano, uključujući 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, prebrojati ciljna nota 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 Wave0). Alternativno, ako je cntD5 5, tada se trenutno svira 5 nota, sa 4 note niže od D5, pa ćemo jednostavno ostaviti waveD5 da visi i nećemo ništa raditi s njim.

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

Sabiranje 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 rezoluciju sve dok PWM ne radi presporo i zvučnik će početi pokupiti kvadratni val PWM -a. Na primjer, ako bismo koristili rezoluciju 8192 (13 bita), svaka od tih 8192 tačaka mora odgovarati rastućoj ivici ugrađenog sata. Dakle, 100MHz / 8192 = 12,2kHz, što je u granicama ljudskog sluha.

Stvarno dodavanje 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 da li se datoteka ograničenja podudara.

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 svim ostalim.

Preporučuje se: