Sisällysluettelo:

Basys3 FPGA Digital Audio Synthesizer: 5 vaihetta
Basys3 FPGA Digital Audio Synthesizer: 5 vaihetta

Video: Basys3 FPGA Digital Audio Synthesizer: 5 vaihetta

Video: Basys3 FPGA Digital Audio Synthesizer: 5 vaihetta
Video: Digital Audio Delay on an FPGA. 2024, Heinäkuu
Anonim
Image
Image
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer

Tämä digitaalinen siniaaltonäppäimistön syntetisaattori ottaa käyttäjän syötteet näppäimistön tapaan asetettujen hetkellisten kytkimien kautta ja lähettää ääniaallon kaiuttimen kautta. Käyttäjän antamien tietojen perusteella laite tuottaa eri taajuuksien siniaaltoja C4: stä C6: een. Käyttäjä voi syöttää nuotteja C4: stä C6: een (yhteensä 25 nuottia) ja enintään neljä näppäintä samanaikaisesti - jos painetaan enemmän kuin neljää näppäintä, soitetaan neljä alinta ääntä.

Tämän projektin tekivät Ryan Morris ja Mavis Tsoi Cal Poly CPE 133 Digital Design -luokallemme:)

Vaihe 1: Teoria

FPGA -kortti voi lähettää vain digitaalisia signaaleja. Toisin sanoen se voi tuottaa vain korkean (3,3 V) tai matalan (0 V) jännitteen. Kuitenkin audiosignaalit ovat analogisia ja niissä voi olla äärettömän monta jänniteaskelta. Tämän kiertämiseksi käytämme PWM -signaalia (pulssileveysmodulaatio) analogisen aallon emuloimiseksi. Jos et tiedä mitä PWM on, tutustu tähän:

Vaihe 2: Ainesosat ja työkalut

  • Tietokone, johon on asennettu Vivado
  • Käytämme Vivado -versiota 2017.2
  • Basys3 FPGA -levy
  • 25 SPDT -rajakytkintä (käytimme näitä)
  • 30 hyppyjohtoa (toinen pää uros, toinen pää ei ole väliä), 12 tuumaa
  • Lankaleikkurit
  • Langanpoistimet
  • Varalanka juottamiseen
  • Hartsi-ydin juote
  • Juotin
  • ¼”naarasääniliitäntä
  • Vahvistin/kaiutin
  • Jotain kytkinten kiinnittämiseen (käytimme protoboardia + puulaatikkoa)

Vaihe 3: Johdotus ja laitteiston asennus

Johdotus ja laitteiston asennus
Johdotus ja laitteiston asennus
Johdotus ja laitteiston asennus
Johdotus ja laitteiston asennus
Johdotus ja laitteiston asennus
Johdotus ja laitteiston asennus

Järjestelmäarkkitehtuuri

Katso kuva 1: 25 käytettävissä olevaa tuloa → Basys3 -kortti → vahvistin ja kaiutin.

Lähtö

Katso kuva 2: Basys3 -kortti → 1/2 tuuman naarasliitin → Kaiutin (vahvistimella)

Syöttö

Basys3 -kortin pmod -liitännät on liitettävä maahan, jotta tulo on heikko, eivätkä ne toimi kunnolla, jos ne jätetään avoimeksi piiriksi. Tästä syystä meidän on käytettävä SPDT -kytkimiä kaikissa muistiinpanoissamme. SPDT -kytkimen avulla käyttäjä voi periaatteessa vaihtaa piirien välillä, kun niitä painetaan, joten käytämme niitä "painikkeina" syöttääksesi matalan (0 V) tai korkean (3,3 V) signaalin Basys3 -kortille.

Jokaisessa kytkimessä on NO (normaalisti avattu) -liitin, joka on kytketty 3,3 V: iin, NC (normaalisti suljettu) -liitin ja GND ja COM (yhteinen) -liitin, joka on kytketty FPGA -tuloon. Katso kuva 3.

Koska meillä on 25 rajakytkintä, niillä kaikilla on yhteinen 3.3V -linja ja yhteinen GND -linja. Sitten kunkin rajakytkimen signaalilinja niputetaan 8 hengen ryhmiin ja kytketään Basys3 -kortin pmod -liitäntöihin vetoketjullisilla hyppyjohdoilla minimoidaksemme tekemämme monumentaalisen sotkun. Katso kuva 4 tai esimerkki kahdeksasta ensimmäisestä näppäimestä.

Vaihe 4: VHDL -asennus (Vivado)

VHDL -asennus (Vivado)
VHDL -asennus (Vivado)
VHDL -asennus (Vivado)
VHDL -asennus (Vivado)

Siniaaltogeneraattoria ja PWM -generaattoria testattiin ensin varmistaaksemme, että konseptimme toimi, minkä jälkeen tulorajoitin ja amplitudin lisäys/vaihdin integroitiin. Kunkin prosessilohkon toiminnon ja I/O: n yksityiskohdat on esitetty kuvassa. Koodi näkyy alla, mutta myös liitteenä VHD- ja txt -tiedostoina. Jos eroja on, siirry VHD -tiedostojen kanssa.

BTW: meidän olisi luultavasti pitänyt lyhentää rivejämme, mutta Instructables -koodin upottaminen osoittautui myös melko ärsyttäväksi käsitellä, joten väli ei ole suurin eikä syntaksin korostusta ole. Jos sinulla on Vivado ja haluat seurata koodia, suosittelemme, että lataat tiedoston.

Katsotaan ensin Sine Wave Generator -moduulia.

kirjasto IEEE; käytä IEEE. STD_LOGIC_1164. ALL; käytä IEEE. NUMERIC_STD. ALL; entiteetti Wave_Generator on portti (liipaisin: STD_LOGIC -tilassa; - näppäimen painallus Freq_Cnt: kohdassa STD_LOGIC_VECTOR (15 - 0); - laskuri -arvo = 100 MHz / (huomautustaajuus*64 siniaalto -osiota) (pyöristetään lähimpään numeroon) - nimetty uudelleen Freq wavegenCLK: in STD_LOGIC; - Basys3 100MHz CLK WaveOut: out STD_LOGIC_VECTOR (9 - 0)); - Aallonpään Wave_Generatorin allekirjoitettu amplitudi; arkkitehtuuri Wave_Generatorin käyttäytyminen on signaali i: kokonaislukualue 0-64: = 0; -amplitudimuistipankkityypin indeksi memory_type on matriisi (0-63) kokonaislukualueella -64-63; - Luo muistipankki (ROM) amplitudiarvojen pitämiseksi- onko tämä RAM tai ROM vain ihmettelevä … signaalin amplitudi: muistityyppi: = (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); - amplitudimuistipankki siniaaltojen aloitusprosessille (wavegenCLK, Trigger) muuttujalaskuri: unsigned (15 downto 0): = to_unsigned (0, 16); - kellonjakajalaskuri, joka on nimetty uudelleen lukumäärästä 1, alkaa jos (nouseva reuna (wavegenCLK)) sitten, jos (liipaisin = '1') sitten- näppäintä painetaan laskuri: = laskuri + 1; jos (laskuri = allekirjoittamaton (Freq_Cnt)) sitten - Freq_Cnt = 100Mhz / (huomaa taajuus * 64 siniaaltoa) - nollaa laskuri ja määritä amplituditiedot lähtölaskurille: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (allekirjoitettu (amplitudi (i), 10)); - lisäys i seuraavaa lukua varten i <= i + 1; - nollaa i, jos yksi siniaalto on suoritettu, jos (i = 63) niin i <= 0; loppu Jos; loppu Jos; - (laskuri = allekirjoittamaton (Freq_Cnt)) else- näppäintä ei paineta- nollaa lähtö, amplitudi-indeksi ja laskuri WaveOut <= "0000000000"; i <= 0; laskuri: = allekirjoittamaton (0, 16); --lähtöamplitudi = -64, kun mitään nuottia ei soiteta, loppuu, jos; - (Liipaisin = '1') loppu, jos; - (nouseva reuna (CLK)) lopetusprosessi; lopeta käyttäytyminen;

Luo digitaalinen siniaalto Basys3: ssa käyttämällä sisäistä kelloa ja ROM -levyä. Tämä ROM tallentaa 64 arvoa, jotka edustavat 64 amplitudia siniaaltoon. Katso kuva 1. Käyttämämme 64 arvoa emuloivat siniaaltoa melko hyvällä resoluutiolla.

Laskemme sisäisen kellon avulla arvoon, joka edustaa kellon nopeuden jaettuna haluamamme aallon taajuudella ja 64: Clk div = 100MHz / (Freq * 64) Joka kerta, kun laskurimme saavuttaa tämän arvon, soitamme numeron ROM ja lähetä se ulos aaltogeneraattorimoduulistamme. Aaltomme taajuus riippuu siitä, kuinka nopeasti kutsumme näitä amplitudeja.

Meillä on 25 alimoduulia, joista jokainen liittyy yhteen taajuuteen/nuottiin.

Tässä on jäljellä oleva koodi, joka kutsuu siniaaltogeneraattorimoduuleja:

kirjasto IEEE; käytä IEEE. STD_LOGIC_1164. ALL; käytä IEEE. NUMERIC_STD. ALL; entiteetti Two_Octave_Synth on portti (CLK: STD_LOGIC; O4: STD_LOGIC_VECTOR (11 - 0); O5: STD_LOGIC_VECTOR (12 downto 0); output: out STD_LOGIC); end Two_Octave_Synth; arkkitehtuuri Two_Octave_Synthin käyttäytyminen on komponentti Wave_Generator on Port (Laukaus: STD_LOGIC; Freq_Cnt: STD_LOGIC_VECTOR (15 downto 0); wavegenCLK: in STD_LOGIC; WaveOut: out STD_LOGIC_VECTOR (9 downto 0)); päätyosa; --------------------------- lähtösignaalit aaltogeneraattorista ------------------ ----- signaali WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveW5, WaveE5, WaveE5, WaveE5 WaveAs5, WaveB5, WaveC6: allekirjoitettu (9 - 0); -------------------------------- nuotinvalintalogiikalle -------------- ------ signaali 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: allekirjoittamaton (4 - 0); signaali cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntCs5, cntC5, cntC5, cntC5: allekirjoittamaton (4 - 0); signaalivirhe: STD_LOGIC; ----------------------------------- siniaaltojen lisäämiseksi ----------- --------------- signaali Wave0, Wave1, Wave2, Wave3: allekirjoitettu (9-0); -signaalit Wave Generator -moduulin lähtösignaalista WaveSum: STD_LOGIC_VECTOR (9-0); -signaali yhteenlasketuille siniaalloille (2: n kohteliaisuus -512-511) signaali positiivinenWaveSum: STD_LOGIC_VECTOR (9 -0); -ei allekirjoitettu 0-1023, käytettäväksi PWM-generaattorissa ----------------------------------- PWM-generaattoriin ------------------------------- signaalin ping_length: unsigned (9 downto 0): = unsigned (positiivinenWaveSum); --signal off_length: unsignedal (6 downto 0): = to_unsigned (127, 7) -unsigned (WAVE); signaali PWM: unsigned (9 to 0): = to_unsigned (0, 10); aloita Huomautus_C4: Wave_Generator -porttikartta (Liipaisin => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveC4); --5973, 261,63 Hz Huomautus_Cs4: Wave_Generator -porttikartta (Liipaisin => O4 (1), Taajuus_Cnt => X "1606", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveCs4);-5638, 277,18 Hz Huomautus_D4: Wave_Generator -porttikartta (Liipaisin => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveD4); --5321, 293,66 Hz Note_Ds4: Wave_Generator -porttikartta (Laukaisija => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveDs4);-5023, 311,13 Hz Note_E4: Wave_Generator -porttikartta (Käynnistin => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveE4); --4741, 329,63 Hz Huomautus_F4: Wave_Generator -porttikartta (Liipaisin => O4 (5), Taajuus_Cnt => X "117B", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Wave_Generator -porttikartta (Liipaisin => O4 (6), Taajuus_Cnt => X "1080", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveFs4);-4224, 369,99 Hz Huomautus_G4: Wave_Generator -porttikartta (Käynnistin => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveG4); --3986, 392,00 Hz Note_Gs4: Wave_Generator -porttikartta (Liipaisin => O4 (8), Taajuus_Cnt => X "0EB3", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveGs4);-3763, 415,30 Hz Huomautus_A4: Wave_Generator -porttikartta (Käynnistin => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Wave_Generator -porttikartta (Liipaisin => O4 (10), Taajuus_Cnt => X "0D18", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveAs4);-3352, 466,16 Hz Huomautus_B4: Wave_Generator -porttikartta (Liipaisin => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Huomautus_C5: Wave_Generator -porttikartta (Liipaisin => O5 (0), Taajuus_Cnt => X "0BAB", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Wave_Generator -porttikartta (Laukaisija => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveCs5);-2819, 554,37 Hz Note_D5: Wave_Generator -porttikartta (Liipaisin => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveD5); --2661, 587,33 Hz Note_Ds5: Wave_Generator -porttikartta (Laukaisija => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveDs5);-2512, 622,25 Hz Note_E5: Wave_Generator -porttikartta (Liipaisin => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveE5); --2371, 659,25 Hz Huomautus_F5: Wave_Generator -porttikartta (Laukaisija => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveF5); --2238, 698,46 Hz Huomautus_Fs5: Wave_Generator -porttikartta (Liipaisin => O5 (6), Taajuus_Cnt => X "0840", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveFs5);-2112, 739,99 Hz Huomautus_G5: Wave_Generator -porttikartta (Käynnistin => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveG5); --1994, 783,99 Hz Note_Gs5: Wave_Generator -porttikartta (Liipaisin => O5 (8), Taajuus_Cnt => X "075A", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveGs5);-1882, 830,61 Hz Huomautus_A5: Wave_Generator -porttikartta (Liipaisin => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveA5); --1776, 880,00 Hz Note_As5: Wave_Generator -porttikartta (Liipaisin => O5 (10), Taajuus_Cnt => X "068C", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveAs5);-1676, 932,33 Hz Huomautus_B5: Wave_Generator -porttikartta (Liipaisin => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveB5); --1582, 987,77 Hz Huomautus_C6: Wave_Generator -porttikartta (Liipaisin => O5 (12), Taajuus_Cnt => X "05D6", wavegenCLK => CLK, allekirjoitettu (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ nuotinvalintalogiikka ------------ 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; Valinta: prosessi (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveG5, WaveE5, WaveE5 WaveB5, WaveC6) alkavat, jos (cntC6 = "00000") sitten --------------- jos signaaleja ei synny Wave0 <= "0000000000"; Aalto1 <= "0000000000"; Aalto2 <= "0000000000"; Aalto3 <= "0000000000"; muuten jos (O4 (0) = '1') ------------------- huomautus C4 pelasi Wave0 Wave0 Wave1 -virheen Wave0 Wave1 Wave2 virheen Wave0 Wave1 Wave2 Wave3 -virheen Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 Wave1 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave1 Wave2 Wave1 Wave2 Wave Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 -virhe Wave0 Wave1 Wave2 Wave3 Wave1 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave = WaveC6; Aalto1 <= "0000000000"; Aalto2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Aalto2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 -virhe Wave1 <= "0000000000"; Aalto2 <= "0000000000"; Aalto3 Aalto2 <= "0000000000"; Wave3 Wave3 -virhe <= '1'; päätykotelo; loppu Jos; loppu Jos; lopeta prosessi; ------------- siniaaltolisäin -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- tee siniaalto positiiviseksi pwm: lle --------------------- positiivinenWaveSum <= ei WaveSum (9) & WaveSum (8 to 0); ------------- PWM-generaattori --------------------- prosessi (CLK)-muuttujien lukumäärä: allekirjoittamaton (1-0): = allekirjoittamaton (0, 2); aloita jos (nouseva reuna (CLK)) sitten --count: = count + 1; --if (count = allekirjoittamattomille (4, 2)) sitten-count: = allekirjoittamattomille (0, 2); --if (PWM = to_ if (PWM <ping_length) sitten ulostulo <= '1'; else output <= '0'; end if; PWM <= PWM + 1; ping_length <= unsigned (positiivinenWaveSum); --end jos; lopeta jos; lopeta prosessi; lopeta käyttäytyminen;

4 Huomautusvalitsin Tämän projektin hankalin osa on vain neljän taajuuden valitseminen. Teimme sen monilla IF -lausekkeilla ja käytimme signaaleja muuttujien sijasta, jotta prosessia voidaan simuloida ja korjata. Kokeilimme muita menetelmiä käyttämällä muuttujia ja FOR-silmukoita, mutta törmäsimme ajonaikaisiin virheisiin. Joten lopulta päätimme, että jos se toimii, jätämme sen rauhaan. Älä korjaa sitä, mikä ei ole rikki amirite?

Neljä lähtöaaltoa on merkitty Wave0, Wave1, Wave2, Wave3 - nämä lisätään yhteen lopullisen lähdön muodostamiseksi.

Koodia tarkasteltaessa näet joukon signaaleja, joissa on merkintä C4, Cs4, D4, Ds4 jne. Nämä ovat 5-bittisiä signaaleja, jotka ottavat vastaavan laukaisimen O4 (oktaavi 4) tai O5 (oktaavi 5) ja tekevät niistä 5-bittinen lisäystä varten.

Seuraavaksi muuttujat cntC4, cntCs4 jne. Osoittavat, kuinka monta tavoitemuusia pienempää nuottia on soitettu, mukaan lukien tavoitetote. Jos esimerkiksi soitetaan C4, E4, G4, A#4 ja D5 (C9 -sointu), cntC4 on 1, cntE4 on 2, cntG4 on 3 jne.

Sitten aina, kun nuotti soitetaan, kohdenuotin määrä tutkitaan, jotta näet, mihin nuotin signaali kytketään. Jos esimerkiksi soitetaan D5 -nuottia (mikä tarkoittaa, että O5 (2) on korkea) ja cntD5 on 3, tällä hetkellä soitetaan 3 nuottia, joista 2 on pienempi kuin D5, joten kiinnitämme wave W5 aaltoon2 (kolmas aalto) signaalin laskeminen aallosta0). Vaihtoehtoisesti, jos cntD5 on 5, tällä hetkellä soitetaan 5 nuottia, 4 nuottia alempana kuin D5, joten jätämme vain waveD5: n roikkumaan emmekä tee sille mitään.

IF -lausunnot toistetaan kattamaan kaikkien 25 setelin tapaukset.

Amplitudin lisäys

Kun alin 4 aaltoa on valittu, meidän on lisättävä ne yhteen. Syy siihen, että lisäämme vain neljä nuottia yhteen, on se, että PWM -ideallamme, jota käytämme tuotoksessamme, voi olla vain tietty resoluutio, kunnes PWM toimii liian hitaasti ja kaiutin alkaa poimia PWM -neliöaaltoa. Jos esimerkiksi käytämme resoluutiota 8192 (13 bittiä), jokaisen näistä 8192 pisteestä on vastattava sisäisen kellon nousevaa reunaa. Joten, 100 MHz / 8192 = 12,2 kHz, mikä on hyvin ihmisen kuuloalueella.

Amplitudien lisäys on erittäin yksinkertaista, sinun on vain varmistettava, että se voi toimia todella nopeasti.

PWM -lähtö

PWM: n käyttöjakso edustaa lähtöaaltomme amplitudia sillä hetkellä. Jos esimerkiksi amplitudialueemme on 0–128, 0 olisi 0%: n käyttöjakso, 64 olisi 50%, 128 olisi 100%jne. Tämä PWM toimii erittäin nopeasti (meillä on 97,6 kHz), niin nopeasti, että kaiutin ei tunnista yksittäisiä neliöaaltoja ja katsoo sen sijaan keskimääräistä jännitettä ja luo "analogisen" signaalimme.

Rajoitustiedosto

Olet saattanut kytkeä laitteiston eri tavalla, joten varmista vain, että rajoitustiedosto vastaa toisiaan.

Vaihe 5: Koodin lataukset

Alla on koodi.txt -muodossa ja.vhd Vivadolle. Wave_Generator on aaltogeneraattorin alimoduuli ja Two_Octave_Synth on ylempi moduuli kaiken muun kanssa.

Suositeltava: