Kazalo:

Basys3 FPGA digitalni avdio sintetizator: 5 korakov
Basys3 FPGA digitalni avdio sintetizator: 5 korakov

Video: Basys3 FPGA digitalni avdio sintetizator: 5 korakov

Video: Basys3 FPGA digitalni avdio sintetizator: 5 korakov
Video: FPGA#04 Implementar comunicación UART - camino a FPGA 2024, Julij
Anonim
Image
Image
Basys3 FPGA digitalni avdio sintetizator
Basys3 FPGA digitalni avdio sintetizator
Basys3 FPGA digitalni avdio sintetizator
Basys3 FPGA digitalni avdio sintetizator

Ta digitalni sintesajzer s sinusno tipkovnico sprejema uporabniške vnose prek vrste trenutnih stikal, postavljenih kot tipkovnica, in oddaja zvočni val skozi zvočnik. Na podlagi vnosov uporabnikov bo naprava ustvarila sinusne valove različnih frekvenc od C4 do C6. Uporabnik lahko vnese opombe od C4 do C6 (skupaj 25 opomb) in do štiri tipke hkrati - če pritisnete več kot štiri tipke, se bodo predvajali štirje najnižji toni.

Ta projekt sta naredila Ryan Morris in Mavis Tsoi za naš razred digitalnega oblikovanja Cal Poly CPE 133:)

1. korak: Teorija

Plošča FPGA lahko oddaja samo digitalne signale. Z drugimi besedami, lahko proizvaja le visoko (3,3 V) napetost ali nizko (0 V) napetost. Zvočni signali pa so analogni in imajo lahko neskončno veliko povečanja napetosti. Da bi to rešili, bomo za emulacijo analognega vala uporabili signal PWM (pulzno -širinska modulacija). Če ne veste, kaj je PWM, preverite to:

2. korak: Sestavine in orodja

  • Računalnik z nameščenim Vivadom
  • Uporabljali bomo Vivado različice 2017.2
  • Basys3 FPGA plošča
  • 25 mejnih stikal SPDT (uporabili smo jih)
  • 30 mostičnih žic (en konec moški, drugi konec ni pomemben), 12 palcev
  • Rezalniki žice
  • Odstranjevalci žice
  • Rezervna žica za spajkanje
  • Spajkalnik iz smolnega jedra
  • Spajkalnik
  • ¼”ženski avdio priključek
  • Ojačevalnik/zvočnik
  • Nekaj za pritrditev stikal (uporabili smo protoboard + leseno škatlo)

Korak: Namestitev ožičenja in strojne opreme

Namestitev ožičenja in strojne opreme
Namestitev ožičenja in strojne opreme
Namestitev ožičenja in strojne opreme
Namestitev ožičenja in strojne opreme
Namestitev ožičenja in strojne opreme
Namestitev ožičenja in strojne opreme

Arhitektura sistema

Glejte sliko 1: 25 razpoložljivih vhodov → Basys3 Board → ojačevalnik in zvočnik.

Izhod

Glejte sliko 2: Plošča Basys3 → 1/2 ženski avdio priključek → zvočnik (z ojačevalnikom)

Vnos

Priključki pmod na plošči Basys3 morajo biti priključeni na ozemljitev, da se vidi nizek vnos in ne bodo delovali pravilno, če ostanejo kot odprto vezje. Zaradi tega moramo uporabiti stikala SPDT za vse naše tipke za opombe. Stikalo SPDT v bistvu omogoča uporabniku preklapljanje med vezji, ko ga pritisnete, zato jih bomo uporabili kot naše "gumbe" za vnos nizkih (0V) ali visokih (3.3V) signalov na ploščo Basys3.

Vsako stikalo bo imelo NO (normalno odprt) priključek priključen na 3.3V, NC (normalno zaprt) priključek priključen na GND in COM (skupni) priključek priključen na vhod FPGA. Glej sliko 3.

Ker imamo 25 končnih stikal, si bodo vsi delili skupno 3.3V linijo in skupno linijo GND. Nato se signalna linija iz vsakega končnega stikala združi v skupine po 8 in priklopi na povezave pmod na plošči Basys3 z uporabo mostičkov, ki jih je mogoče zapreti, da zmanjšamo monumentalno zmešnjavo, ki jo bomo naredili. Glejte sliko 4 ali primer prvih osmih tipk.

4. korak: nastavitev VHDL (Vivado)

Nastavitev VHDL (Vivado)
Nastavitev VHDL (Vivado)
Nastavitev VHDL (Vivado)
Nastavitev VHDL (Vivado)

Generator sinusnih valov in generator PWM sta bila najprej preizkušena, da bi zagotovila, da naš koncept deluje, nato sta bila integrirana omejevalnik vhoda in seštevalnik amplitude/menjalnik. Podrobnosti o funkciji in V/I vsakega procesnega bloka so prikazane na sliki. Koda je prikazana spodaj, priložena pa je tudi kot datoteke VHD in txt. Če pride do razhajanj, pojdite z datotekami VHD.

BTW: Verjetno bi morali skrajšati vrstice, vendar se je izkazalo, da je vstavljanje kode v Instructables tudi zelo nadležno, zato razmik ni največji in ni poudarjanja sintakse. Če imate Vivado in želite slediti kodi, vam toplo priporočamo, da datoteko preprosto prenesete.

Najprej si oglejmo modul Generator sinusnih valov.

knjižnica IEEE; uporabite IEEE. STD_LOGIC_1164. ALL; uporabite IEEE. NUMERIC_STD. ALL; entiteta Wave_Generator je Port (Sprožilec: v STD_LOGIC; - Pritisk tipke Freq_Cnt: v STD_LOGIC_VECTOR (15 navzdol 0); - Vrednost števca = 100 MHz / (Opomba Frekvenca*64 delitev sinusnega vala) (zaokroži na najbližje število) - preimenuje iz Freq wavegenCLK: v STD_LOGIC; - Basys3 100MHz CLK WaveOut: ven STD_LOGIC_VECTOR (9 navzdol 0)); - podpisana amplituda valnega konca Wave_Generator; vedenje arhitekture Wave_Generator je signal i: celoštevilsko območje od 0 do 64: = 0; -indeks amplitude pomnilniške banke tipa memory_type je matrika (0 do 63) v celovitem razponu od -64 do 63; - ustvarite pomnilniško banko (ROM) za shranjevanje vrednosti amplitude- se ta RAM ali ROM samo sprašujeta … 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); - pomnilniška banka amplitud za začetek sinusnega valovanja (wavegenCLK, sprožilec) spremenljivka števca: brez podpisa (15 navzdol 0): = to_unsigned (0, 16); - števec delilnika ure, preimenovan iz count1 start if (rise_edge (wavegenCLK)) then if (Trigger = '1') then- tipka je pritisnjena counter: = counter + 1; če (števec = brez podpisa (Freq_Cnt)), potem - Freq_Cnt = 100 Mhz / (upoštevajte frekv. * 64 delitev sinusnega vala) - ponastavite števec in dodelite podatke o amplitudi izhodnemu števcu: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (do_signed (amplituda (i), 10)); - prirast i za naslednje branje i <= i + 1; - ponastavi i, če je bil zaključen en sinusni val, če (i = 63), potem je i <= 0; konec če; konec če; - (števec = brez podpisa (Freq_Cnt)) else- tipka ni pritisnjena- ponastavite izhod, indeks amplitude in števec WaveOut <= "0000000000"; i <= 0; števec: = to_unsigned (0, 16); -izhodna amplituda = -64, če se nota ne predvaja konec, če; - (Trigger = '1') konec if; - (rise_edge (CLK)) zaključni postopek; konec vedenjskega;

V Basys3 bomo ustvarili digitalni sinusni val z uporabo notranje ure in ROM -a. Ta ROM bo shranil 64 vrednosti, ki predstavljajo 64 amplitud na sinusnem valu. Glejte sliko 1. 64 vrednosti, ki jih uporabljamo, posnemajo sinusni val s precej dobro ločljivostjo.

Z uporabo notranje ure štejemo na vrednost, ki predstavlja urno hitrost, deljeno s frekvenco želenega vala in 64: Clk div = 100MHz / (Freq * 64) Vsakič, ko naš števec doseže to vrednost, pokličemo številko iz ROM in ga pošljite iz našega modula generatorja valov. Frekvenca našega valovanja bo odvisna od tega, kako hitro imenujemo te amplitude.

Imeli bomo 25 podmodulov, od katerih je vsak povezan z eno frekvenco/noto.

Tu je preostala koda, ki kliče module sinusnega valovanja:

knjižnica IEEE; uporabite IEEE. STD_LOGIC_1164. ALL; uporabite IEEE. NUMERIC_STD. ALL; entiteta Two_Octave_Synth je Port (CLK: v STD_LOGIC; O4: v STD_LOGIC_VECTOR (11 navzdol 0); O5: v STD_LOGIC_VECTOR (12 navzdol 0); izhod: out STD_LOGIC); konec Two_Octave_Synth; vedenje arhitekture Two_Octave_Synth je komponenta Wave_Generator je Port (Sprožilec: v STD_LOGIC; Freq_Cnt: v STD_LOGIC_VECTOR (15 navzdol 0); wavegenCLK: v STD_LOGIC; WaveOut: ven STD_LOGIC_VECTOR (9 navzdol); 9 navzdol) končna komponenta; --------------------------- izhodni signali iz generatorja valov ------------------ ----- signal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, Wave5, Wave5, Wave5, Wave5 WaveAs5, WaveB5, WaveC6: podpisano (9 navzdol 0); -------------------------------- za logiko izbire opombe -------------- ------ 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: brez podpisa (4 navzdol 0); signal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntC5, cntC5, cnt5: brez podpisa (4 navzdol 0); napaka signala: STD_LOGIC; ----------------------------------- za dodajanje sinusnih valov ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: podpisan (9 navzdol 0); -signali izhodnega signala modula generatorja valov WaveSum: STD_LOGIC_VECTOR (9 navzdol 0); -signal za seštete sinusne valove (kompliment 2 -512 do 511) pozitiven signal WaveSum: STD_LOGIC_VECTOR (9 navzdol 0); --značen od 0 do 1023, za uporabo v PWM generatorju ----------------------------------- 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: brez podpisa (9 downto 0): = to_unsigned (0, 10); Začni Note_C4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, podpisan (WaveOut) => WaveC4); --5973, 261,63 Hz Note_Cs4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, podpisan (WaveOut) => WaveCs4);-5638, 277,18 Hz Opomba_D4: Zemljevid vrat Wave_Generator (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, podpisan (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, podpisan (WaveOut) => WaveDs4);-5023, 311.13 Hz Opomba_E4: Zemljevid vrat Wave_Generator (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, podpisan (WaveOut) => WaveE4); --4741, 329,63 Hz Opomba_F4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, podpisan (WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, podpisan (WaveOut) => WaveFs4);-4224, 369,99 Hz Note_G4: Zemljevid vrat Wave_Generator (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, podpisan (WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, podpisan (WaveOut) => WaveGs4);-3763, 415.30 Hz Opomba_A4: Zemljevid vrat Wave_Generator (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, podpisan (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Zemljevid vrat Wave_Generator (Sprožilec => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, podpisan (WaveOut) => WaveAs4);-3352, 466,16 Hz Opomba_B4: Zemljevid vrat Wave_Generator (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, podpisan (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, podpisan (WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, podpisan (WaveOut) => WaveCs5);-2819, 554,37 Hz Opomba_D5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, podpisan (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, podpisan (WaveOut) => WaveDs5);-2512, 622,25 Hz Opomba_E5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, podpisan (WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, podpisan (WaveOut) => WaveF5); --2238, 698,46 Hz Note_Fs5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, podpisan (WaveOut) => WaveFs5);-2112, 739,99 Hz Opomba_G5: Zemljevid vrat Wave_Generator (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, podpisan (WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, podpisan (WaveOut) => WaveGs5);-1882, 830,61 Hz Opomba_A5: Zemljevid vrat Wave_Generator (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, podpisan (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Zemljevid vrat Wave_Generator (Sprožilec => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, podpisan (WaveOut) => WaveAs5);-1676, 932,33 Hz Opomba_B5: Zemljevid vrat Wave_Generator (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, podpisan (WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Zemljevid vrat Wave_Generator (Sprožilec => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, podpisan (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ logika izbire opombe ------------ 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; Izbira: proces (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) se začnejo, če (cntC6 = "00000") potem ---------------, če se ne generirajo signali Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; sicer, če je (O4 (0) = '1'), potem ------------------- opomba C4 je igrala Wave0 Wave0 Wave1 error1 Wave0 Wave1 Wave2 error2 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Napaka Wave2 Wave3 Wave0 Wave1 Wave2 Wave2 Wave3 Napaka Wave0 Wave2 Wave2 Wave2 Wave2 Wave Napaka Wave2 Wave3 Wave0 Wave1 Wave2 Wave2 Wave3 error3 Wave0 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 error Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 error <= '1'; zaključni primer; konec če; konec če; zaključni postopek; ------------- seštevalnik sinusnih valov -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- narediti sinusni val pozitiven za pwm --------------------- positiveWaveSum <= ne WaveSum (9) & WaveSum (8 downto 0); ------------- generator PWM --------------------- proces (CLK)-spremenljivo število: brez podpisa (1 navzdol 0): = to_unsigned (0, 2); začni, če (naraščajoči rob (CLK)) potem --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 Behavioral;

4 Izbirnik opomb Najbolj zapleten del tega projekta je izbira samo štirih frekvenc. To smo storili s celo vrsto stavkov IF in namesto spremenljivk smo uporabili signale, tako da je bil proces mogoče simulirati in odpraviti napake. Poskusili smo druge metode s spremenljivkami in zankami FOR, vendar smo naleteli na napake med izvajanjem. Tako smo se na koncu odločili, da pustimo pri miru, če bo delovalo. Ne popravljajte tistega, kar ni zlomljenega amirita?

Štirje izhodni valovi so označeni z Wave0, Wave1, Wave2, Wave3 - to je tisto, kar se bo sestavilo, da se oblikuje končni izhod.

Če pogledate kodo, boste videli kopico signalov z oznako C4, Cs4, D4, Ds4 itd. To so 5-bitni signali, ki sprejmejo ustrezen sprožilec iz O4 (oktava 4) ali O5 (oktava 5) in jih naredijo 5-bit za dodajanje.

Nato spremenljivke cntC4, cntCs4 itd predstavljajo, koliko not je bilo odigranih nižje od ciljne note, vključno s ciljno noto. Če se na primer predvajajo C4, E4, G4, A#4 in D5 (akord C9), bo cntC4 1, cntE4 2, cntG4 3 itd.

Potem, ko se igra nota, se preuči štetje za ciljno noto, da se ugotovi, do kje priključiti signal note. Na primer, če se igra nota D5 (kar pomeni, da je O5 (2) visoko) in je cntD5 3, potem se trenutno igrajo 3 note, pri čemer sta 2 noti nižji od D5, zato bomo val D5 priklopili na val 2 (tretji val štetje signala iz Wave0). Druga možnost je, če je cntD5 5, se trenutno predvaja 5 not, pri čemer so 4 note nižje od D5, zato bomo valD5 pustili viseti in z njim ne bomo ničesar storili.

Izjave IF se nato ponovijo, da pokrijejo primere za vseh 25 zapiskov.

Seštevalnik amplitude

Ko izberemo najnižje 4 valove, jih moramo sešteti. Razlog, da bomo skupaj dodali le štiri note, je, da ima ideja PWM, ki jo uporabljamo za svoj izhod, le določeno ločljivost, dokler PWM ne deluje prepočasi in zvočnik začne pobirati kvadratni val PWM. Na primer, če bi uporabili ločljivost 8192 (13 bitov), mora vsaka od teh 8192 točk ustrezati naraščajočemu robu vgrajene ure. Torej, 100MHz / 8192 = 12,2kHz, kar je v obsegu človeškega sluha.

Dejansko dodajanje amplitud je zelo preprosto, le prepričati se morate, da lahko deluje zelo hitro.

PWM izhod

Delovni cikel PWM bo predstavljal amplitudo našega izhodnega vala v tistem trenutku. Na primer, če imamo amplitudno območje od 0 do 128, bi bilo 0 0%obratovalnega cikla, 64 bi bilo 50%, 128 bi bilo 100%itd. Ta PWM bo deloval izjemno hitro (naš je 97,6 kHz), tako hitro, da zvočnik ne bo prepoznal posameznih kvadratnih valov in namesto tega pogledal povprečno napetost in ustvaril naš "analogni" signal.

Datoteka omejitev

Morda ste strojno opremo priključili drugače, zato se prepričajte, da se datoteka omejitev ujema.

5. korak: Prenosi kode

Spodaj je koda v formatu.txt in.vhd za Vivado. Wave_Generator je podmodul generatorja valov, Two_Octave_Synth pa zgornji modul z vsem ostalim.

Priporočena: