Sisukord:

Basys3 FPGA digitaalne helisüntesaator: 5 sammu
Basys3 FPGA digitaalne helisüntesaator: 5 sammu

Video: Basys3 FPGA digitaalne helisüntesaator: 5 sammu

Video: Basys3 FPGA digitaalne helisüntesaator: 5 sammu
Video: Basys 3 Introduction 2024, Juuli
Anonim
Image
Image
Basys3 FPGA digitaalne helisüntesaator
Basys3 FPGA digitaalne helisüntesaator
Basys3 FPGA digitaalne helisüntesaator
Basys3 FPGA digitaalne helisüntesaator

See digitaalne siinuslaine klaviatuuri süntesaator võtab kasutajate sisendeid mitmete hetkeliste lülitite kaudu, mis on paigutatud klaviatuurina, ja väljastab helilaine kõlari kaudu. Kasutaja sisendite põhjal genereerib seade erineva sagedusega siinuslaineid vahemikus C4 kuni C6. Kasutaja saab sisestada noote C4 kuni C6 (kokku 25 nooti) ja kuni neli klahvi korraga - kui vajutate rohkem kui nelja klahvi, mängitakse nelja madalaimat tooni.

Selle projekti tegid Ryan Morris ja Mavis Tsoi meie Cal Poly CPE 133 digitaalse disaini klassi jaoks:)

1. samm: teooria

FPGA -plaat saab väljastada ainult digitaalseid signaale. Teisisõnu, see võib toota ainult kõrge (3,3 V) pinget või madalat (0 V) pinget. Helisignaalid on aga analoogsed ja neil võib olla lõputult palju pinget. Selle vältimiseks kasutame analooglaine jäljendamiseks PWM (impulsi laiuse modulatsiooni) signaali. Kui te ei tea, mis on PWM, vaadake seda:

Samm: koostisosad ja tööriistad

  • Arvuti, millele on installitud Vivado
  • Kasutame Vivado versiooni 2017.2
  • Basys3 FPGA plaat
  • 25 SPDT piirilülitit (kasutasime neid)
  • 30 džemprijuhet (üks ots isane, teine ots pole oluline), 12 tolli
  • Traadilõikurid
  • Traadi eemaldajad
  • Varutraat jootmiseks
  • Vaigu-tuumaga jootma
  • Jootekolb
  • ¼”naissoost helipistik
  • Võimendi/kõlar
  • Midagi lülitite paigaldamiseks (kasutasime protoboardi + puidust kasti)

Samm: juhtmestiku ja riistvara seadistamine

Juhtmete ja riistvara seadistamine
Juhtmete ja riistvara seadistamine
Juhtmete ja riistvara seadistamine
Juhtmete ja riistvara seadistamine
Juhtmete ja riistvara seadistamine
Juhtmete ja riistvara seadistamine

Süsteemi arhitektuur

Vt joonis 1: 25 saadaolevat sisendit → Basys3 Board → võimendi ja kõlar.

Väljund

Vt joonis 2: Basys3 -plaat → 1/2 naissoost helipistik → Kõlar (võimendiga)

Sisend

Basys3 tahvli pmod -ühendused peavad olema madala sisendiga maaga ühendatud ja ei tööta korralikult, kui jätta lahti vooluahelana. Seetõttu peame kõigi märkmevõtmete jaoks kasutama SPDT -lülitit. SPDT -lüliti võimaldab kasutajal põhimõtteliselt lülituda vooluahelate vahel, nii et me kasutame neid oma “nuppudena”, et sisestada Basys3 tahvlile madalaid (0 V) või kõrgeid (3,3 V) signaale.

Igal lülitil on NO (tavaliselt avatud) klemm ühendatud 3.3V, NC (tavaliselt suletud) klemm ühendatud GND -ga ja COM (ühine) terminal on ühendatud FPGA sisendiga. Vt joonist 3.

Kuna meil on 25 piirlülitit, on neil kõigil ühine 3,3 V ja GND liin. Seejärel ühendatakse iga piirilüliti signaaliliin 8 -liikmelisteks rühmadeks ja ühendatakse Basys3 -plaadi pmod -ühendustega, kasutades tõmblukuga hüppajajuhtmeid, et minimeerida monumentaalset segadust. Vaadake joonist 4 või kaheksa esimese klahvi näidet.

4. samm: VHDL -i seadistamine (Vivado)

VHDL -i seadistamine (Vivado)
VHDL -i seadistamine (Vivado)
VHDL -i seadistamine (Vivado)
VHDL -i seadistamine (Vivado)

Siinuslainegeneraatorit ja PWM -generaatorit testiti kõigepealt, et veenduda meie kontseptsiooni toimimises, seejärel integreeriti sisendpiiraja ja amplituudi liitja/nihutaja. Iga protsessiploki funktsiooni ja I/O üksikasjad on näidatud joonisel. Kood on näidatud allpool, kuid on lisatud ka VHD- ja txt -failidena. Kui esineb lahknevusi, minge VHD -failidega.

BTW: me oleksime ilmselt pidanud oma read lühemaks muutma, kuid ka koodide manustamine Instructablesile osutus üsna tüütuks, nii et vahekaugus pole suurim ja süntaksi esiletõstmist pole. Kui teil on Vivado ja soovite koodi järgida, soovitame teil fail lihtsalt alla laadida.

Kõigepealt vaatame siinuslainegeneraatori moodulit.

raamatukogu IEEE; kasutage IEEE. STD_LOGIC_1164. ALL; kasutage IEEE. NUMERIC_STD. ALL; olem Wave_Generator on port (käivitaja: STD_LOGIC -s; - klahvivajutus Freq_Cnt: sisse STD_LOGIC_VECTOR (15 kuni 0); - loenduri väärtus = 100 MHz / (märkus Sagedus*64 siinuslaine jaotust) (ümardatud lähima numbrini) - ümbernimetatud sageduselt wavegenCLK: STD_LOGIC -is; - Basys3 100 MHz CLK WaveOut: väljas STD_LOGIC_VECTOR (9 kuni 0)); - Laineotsa Wave_Generator allkirjastatud amplituud; arhitektuur Wave_Generator käitumine on signaal i: täisarvude vahemik 0 kuni 64: = 0; -amplituudmälu panga tüüpi mälu_tüüp indeks on täismasside vahemik -64 kuni 63; - luua mälupank (ROM) amplituudiväärtuste hoidmiseks- kas see RAM või ROM lihtsalt mõtleb… signaali amplituud: mälu_tüüp: = (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); - amplituudi mälupank siinuslaine alguse protsessi jaoks (wavegenCLK, Trigger) muutuja loendur: signatuurita (15 kuni 0): = to_unsigned (0, 16); - kellajaguri loendur, ümbernimetatud loendist 1, algab (tõusev serv (wavegenCLK)), siis kui (käivitaja = '1'), siis- klahvi vajutatakse loendurile: = loendur + 1; kui (loendur = allkirjastamata (Freq_Cnt)) siis - Freq_Cnt = 100Mhz / (märkussagedus * 64 siinuslaine jaotust) - lähtestage loendur ja määrake amplituudi andmed väljundloendurile: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (allkirjastatud (amplituud (i), 10)); - juurdekasv i järgmiseks lugemiseks i <= i + 1; - lähtestage i, kui üks siinuslaine on lõpule viidud, kui (i = 63), siis i <= 0; lõpetada, kui; lõpetada, kui; - (loendur = allkirjastamata (Freq_Cnt)) else- klahvi ei vajutata- lähtestatakse väljund, amplituudiindeks ja loendur WaveOut <= "0000000000"; i <= 0; loendur: = allkirjastamata (0, 16); -väljundamplituud = -64, kui nooti ei esitata, lõpeb, kui; - (Päästik = '1') lõpp, kui; - (tõusev serv (CLK)) lõppprotsess; lõpp Käitumine;

Loome Basys3 -s digitaalse siinuslaine, kasutades sisemist kella ja ROM -i. See ROM salvestab siinuslainele 64 väärtust, mis esindavad 64 amplituudi. Vt joonis 1. 64 kasutatavat väärtust jäljendavad siinuslainet üsna hea eraldusvõimega.

Sisemise kella abil loeme väärtuseni, mis tähistab taktsagedust jagatuna soovitud laine sagedusega ja 64: Clk div = 100MHz / (Freq * 64) Iga kord, kui meie loendur selle väärtuse saavutab, helistame numbrile ROM ja saatke see meie lainegeneraatori moodulist välja. Meie laine sagedus sõltub sellest, kui kiiresti me neid amplituude nimetame.

Meil on 25 alammoodulit, millest igaüks on seotud ühe sageduse/noodiga.

Siin on ülejäänud kood, mis kutsub siinuslainegeneraatori mooduleid:

raamatukogu IEEE; kasutage IEEE. STD_LOGIC_1164. ALL; kasutage IEEE. NUMERIC_STD. ALL; olem Two_Octave_Synth on port (CLK: STD_LOGIC; O4: STD_LOGIC_VECTOR (11 kuni 0); O5: STD_LOGIC_VECTOR (12 kuni 0); output: out STD_LOGIC); end Two_Octave_Synth; arhitektuur Two_Octave_Synthi käitumine on komponent Wave_Generator on port (käivitaja: STD_LOGIC -s; Freq_Cnt: STD_LOGIC_VECTOR -is (15 kuni 0); wavegenCLK: STD_LOGIC -s; WaveOut: out STD_LOGIC_VECTOR (9 kuni 0)); lõppkomponent; --------------------------- väljundsignaalid lainegeneraatorist ------------------ ----- signaal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveE5, WaveE5, WaveE5, WaveE5 WaveAs5, WaveB5, WaveC6: allkirjastatud (9 kuni 0); -------------------------------- märkmete valiku loogika jaoks -------------- ------ signaal 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: allkirjastamata (4 kuni 0); signaal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntCs5, cntC5, cntC5: allkirjastamata (4 kuni 0); signaali viga: STD_LOGIC; ----------------------------------- siinuslainete lisamiseks ----------- --------------- signaal Wave0, Wave1, Wave2, Wave3: allkirjastatud (9 kuni 0); -signaalid lainegeneraatori mooduli väljundsignaalilt WaveSum: STD_LOGIC_VECTOR (9 kuni 0); -signaal summeeritud siinuslainete kohta (2 kompliment -512 kuni 511) signaal positiivneWaveSum: STD_LOGIC_VECTOR (9 kuni 0); -allkirjaga 0 kuni 1023, kasutamiseks PWM-generaatoris ----------------------------------- PWM-i genereerimiseks ------------------------------- signaali ping_length: unsigned (9 kuni 0): = allkirjata (positiivneWaveSum); -signaali väljalülitatud pikkus: allkirjastamata (6 kuni 0): = allkirjastamata (127, 7) -allkirjastamata (WAVE); signaal PWM: allkirjastamata (9 kuni 0): = allkirjastamata (0, 10); alusta Märkus_C4: Wave_Generator pordikaart (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveC4); --5973, 261,63 Hz Märkus_Cs4: Wave_Generator pordikaart (Päästik => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveCs4);-5638, 277,18 Hz Märkus_D4: Wave_Generator pordikaart (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveD4); --5321, 293,66 Hz Märkus_Ds4: Wave_Generator pordikaart (Päästik => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveDs4);-5023, 311,13 Hz Märkus_E4: Wave_Generator pordikaart (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveE4); --4741, 329,63 Hz Märkus_F4: Wave_Generator pordikaart (Päästik => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveF4); --4475, 349,23 Hz Märkus_Fs4: Wave_Generator pordikaart (Päästik => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveFs4);-4224, 369,99 Hz Märkus_G4: Wave_Generator pordikaart (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveG4); --3986, 392,00 Hz Märkus_Gs4: Wave_Generator pordikaart (Päästik => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveGs4);-3763, 415,30 Hz Märkus_A4: Wave_Generator pordikaart (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveA4); --3552, 440,00 Hz Märkus_As4: Wave_Generator pordikaart (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveAs4);-3352, 466,16 Hz Note_B4: Wave_Generator pordikaart (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Märkus_C5: Wave_Generator pordikaart (Päästik => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveC5); --2987, 523,25 Hz Märkus_Cs5: Wave_Generator pordikaart (Päästik => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveCs5);-2819, 554,37 Hz Märkus_D5: Wave_Generator pordikaart (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveD5); --2661, 587,33 Hz Märkus_Ds5: Wave_Generator pordikaart (Päästik => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveDs5);-2512, 622,25 Hz Märkus_E5: Wave_Generator pordikaart (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveE5); --2371, 659,25 Hz Märkus_F5: Wave_Generator pordikaart (Päästik => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveF5); --2238, 698,46 Hz Märkus_Fs5: Wave_Generator pordikaart (Päästik => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveFs5);-2112, 739,99 Hz Märkus_G5: Wave_Generator pordikaart (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveG5); --1994, 783,99 Hz Märkus_Gs5: Wave_Generator pordikaart (Päästik => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveGs5);-1882, 830,61 Hz Märkus_A5: Wave_Generator pordikaart (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveA5); --1776, 880,00 Hz Note_As5: Wave_Generator pordikaart (Päästik => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveAs5);-1676, 932,33 Hz Märkus_B5: Wave_Generator pordikaart (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveB5); --1582, 987,77 Hz Märkus_C6: Wave_Generator pordikaart (Päästik => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, allkirjastatud (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ noodivaliku loogika ------------ 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; Valik: protsess (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveG5, WaveE5, WaveE5 WaveB5, WaveC6) algavad, kui (cntC6 = "00000"), siis --------------- kui signaale ei genereerita Wave0 <= "0000000000"; Laine1 <= "0000000000"; Laine2 <= "0000000000"; Laine3 <= "0000000000"; muidu, kui (O4 (0) = '1') siis ------------------- märkus C4 mängis Wave0 Wave0 Wave1 viga Wave0 Wave1 Wave2 Wave0 Wave1 Wave2 Wave3 Wave3 Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 Wave1 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 laine viga Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 viga Wave0 Wave1 Wave2 Wave3 Wave0 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 Wave2 = LaineC6; Laine1 <= "0000000000"; Laine2 <= "0000000000"; Laine3 Laine1 <= LaineC6; Laine2 <= "0000000000"; Laine3 Laine2 <= LaineC6; Wave3 Wave3 viga Wave1 <= "0000000000"; Laine2 <= "0000000000"; Laine3 Laine2 <= "0000000000"; Wave3 Wave3 viga <= '1'; lõppjuhtum; lõpetada, kui; lõpetada, kui; protsessi lõpetamine; ------------- siinuslaine liitur -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- tehke siinuslaine pwm jaoks positiivseks --------------------- positiivneWaveSum <= ei WaveSum (9) & WaveSum (8 kuni 0); ------------- PWM-generaator --------------------- protsess (CLK)-muutujate arv: allkirjastamata (1 kuni 0): = allkirjastamata (0, 2); alusta, kui (tõusev serv (CLK)), siis --arv: = loe + 1; --if (loendus = allkirjastamata (4, 2)), siis --arv: = allkirjastamata (0, 2); --if (PWM = to_ if (PWM <ping_length), siis väljund <= '1'; muidu väljund <= '0'; lõpp, kui; PWM <= PWM + 1; ping_length <= allkirjastamata (positiivneWaveSum); --end kui; lõpetage kui; lõpetage protsess; lõpetage käitumine;

4 Märkmete valija Selle projekti kõige keerulisem osa on ainult nelja sageduse valimine. Tegime seda terve hulga IF -avaldustega ja kasutasime muutujate asemel signaale, et protsessi saaks simuleerida ja siluda. Proovisime muid meetodeid, kasutades muutujaid ja FOR-ahelaid, kuid sattusime käitusaja veadesse. Nii et lõpuks otsustasime, et kui see töötab, jätame selle rahule. Ärge parandage seda, mis pole purustatud amiriit?

Neli väljundlainet on märgistatud Wave0, Wave1, Wave2, Wave3 - need liidetakse lõpliku väljundi moodustamiseks.

Koodi vaadates näete hunnikut signaale siltidega C4, Cs4, D4, Ds4 jne. Need on 5-bitised signaalid, mis võtavad vastava päästiku O4 (oktaav 4) või O5 (oktaav 5) ja muudavad need Lisamiseks 5-bitine.

Järgmisena näitavad muutujad cntC4, cntCs4 jne, kui palju noote on mängitud sihtmärgist madalamal, kaasa arvatud sihtmärk. Näiteks kui mängitakse C4, E4, G4, A#4 ja D5 (C9 akord), siis cntC4 on 1, cntE4 on 2, cntG4 on 3 jne.

Seejärel, kui nooti mängitakse, kontrollitakse märkme arvu, et näha, kuhu noodisignaal ühendada. Näiteks kui mängitakse D5 nooti (mis tähendab, et O5 (2) on kõrge) ja cntD5 on 3, siis mängitakse praegu 3 nooti, 2 noodiga madalamal kui D5, nii et me ühendame laine D5 Wave2 -ga (kolmas laine) signaalide loendamine Wave'ilt0). Teise võimalusena, kui cntD5 on 5, siis mängitakse praegu 5 nooti, 4 nooti madalamal kui D5, seega jätame waveD5 lihtsalt rippuma ja ei tee sellega midagi.

IF -lauseid korratakse, et hõlmata kõigi 25 märkme juhtumeid.

Amplituudi liitja

Pärast nelja madalaima laine valimist peame need kokku panema. Põhjus, miks lisame ainult neli nooti, on see, et PWM -ideel, mida me oma väljundi jaoks kasutame, võib olla ainult teatud eraldusvõime, kuni PWM töötab liiga aeglaselt ja kõlar hakkab PWM -ruutlainet üles võtma. Näiteks kui kasutame eraldusvõimet 8192 (13 bitti), peab igaüks neist 8192 punktist vastama pardakella tõusvale servale. Niisiis, 100MHz / 8192 = 12,2kHz, mis jääb hästi inimese kuulmispiirkonda.

Amplituutide tegelik lisamine on ülilihtne, peate lihtsalt veenduma, et see suudab tõesti kiiresti töötada.

PWM väljund

PWM -i töötsükkel esindab meie väljundlaine amplituudi sel hetkel. Näiteks kui meil on amplituudivahemik 0 kuni 128, oleks 0 0%töötsükkel, 64 oleks 50%, 128 oleks 100%jne. See PWM töötab väga kiiresti (meie sagedus on 97,6 kHz), nii kiiresti, et kõlar ei tunne ära üksikuid ruutlaineid ja vaatab selle asemel keskmist pinget, luues meie analoogsignaali.

Piirangute fail

Võib -olla ühendasite riistvara erinevalt, seega veenduge, et piirangute fail sobiks kokku.

Samm: koodi allalaadimine

Allpool on Vivado jaoks kood.txt ja.vhd. Wave_Generator on lainegeneraatori alammoodul ja Two_Octave_Synth on tippmoodul koos kõige muuga.

Soovitan: