Përmbajtje:

Sintetizuesi dixhital i audios Basys3 FPGA: 5 hapa
Sintetizuesi dixhital i audios Basys3 FPGA: 5 hapa

Video: Sintetizuesi dixhital i audios Basys3 FPGA: 5 hapa

Video: Sintetizuesi dixhital i audios Basys3 FPGA: 5 hapa
Video: FPGA Nexys A7 100T - Basic Audio Synthesizer 2024, Korrik
Anonim
Image
Image
Sintetizues audio audio Basys3 FPGA
Sintetizues audio audio Basys3 FPGA
Sintetizues audio audio Basys3 FPGA
Sintetizues audio audio Basys3 FPGA

Ky sintetizues dixhital i tastierës me valë sinusale do të marrë hyrjet e përdoruesit përmes një sërë ndërprerësish të çastit të vendosur si një tastierë dhe do të nxjerrë një valë audio përmes një altoparlanti. Bazuar në hyrjet e përdoruesit, pajisja do të gjenerojë valë sinus të frekuencave të ndryshme nga C4 në C6. Përdoruesi mund të fusë shënime nga C4 deri në C6 (gjithsej 25 shënime), dhe deri në katër çelësa në të njëjtën kohë - nëse shtypen më shumë se katër çelësa, do të luhen katër tonet më të ulëta.

Ky projekt u bë nga Ryan Morris dhe Mavis Tsoi për klasën tonë të Dizajnit dixhital Cal Poly CPE 133:)

Hapi 1: Teoria

Një bord FPGA mund të nxjerrë vetëm sinjale dixhitale. Me fjalë të tjera, ai mund të prodhojë vetëm një tension të lartë (3.3V) ose një tension të ulët (0V). Sidoqoftë, sinjalet audio janë analoge dhe mund të kenë pafundësisht shumë rritje të tensionit. Për ta shmangur këtë, ne do të përdorim një sinjal PWM (modulimi i gjerësisë së impulsit) për të imituar një valë analoge. Nëse nuk e dini se çfarë është PWM, shikoni këtë:

Hapi 2: Përbërësit dhe mjetet

  • Kompjuter me Vivado të instaluar
  • Ne do të përdorim versionin Vivado 2017.2
  • Bordi Basys3 FPGA
  • 25 çelësa limit SPDT (ne i përdorëm këto)
  • 30 tela kërcyes (njëri skaj mashkull, skaji tjetër nuk ka rëndësi), 12 inç
  • Preres telash
  • Zhveshëset e telave
  • Teli rezervë për bashkim
  • Saldues me bazë rrëshirë
  • Makine per ngjitjen e metalit
  • Jack”prizë audio femërore
  • Përforcues/altoparlant
  • Diçka për të montuar çelësat (ne përdorëm protoboard + kuti druri)

Hapi 3: Instalimet dhe instalimi i pajisjeve

Instalimet dhe instalimi i pajisjeve
Instalimet dhe instalimi i pajisjeve
Instalimet dhe instalimi i pajisjeve
Instalimet dhe instalimi i pajisjeve
Instalimet dhe instalimi i pajisjeve
Instalimet dhe instalimi i pajisjeve

Arkitektura e Sistemit

Shihni Figura 1: 25 hyrje të disponueshme → Basys3 Board → amplifikator & altoparlant.

Dalje

Shihni Figurën 2: Basys3 Board → 1/2 Femër Audio Jack → Altoparlant (me Amplifikator)

Hyrja

Lidhjet pmod në tabelën Basys3 duhet të lidhen me tokën për të parë një hyrje të ulët dhe nuk do të funksionojnë siç duhet nëse lihen si një qark i hapur. Për shkak të kësaj, ne duhet të përdorim çelsat SPDT për të gjithë çelësat tanë të shënimeve. Një ndërprerës SPDT në thelb i lejon përdoruesit të kalojë midis qarqeve kur shtypet, kështu që ne do t'i përdorim ato si "butonat" tanë për të futur sinjale të ulëta (0V) ose të larta (3.3V) në tabelën Basys3.

Çdo ndërprerës do të ketë terminalin NO (normalisht të hapur) të lidhur me 3.3V, terminalin NC (normalisht të mbyllur) të lidhur me GND dhe terminalin COM (të zakonshëm) të lidhur me hyrjen FPGA. Shih Figurën 3.

Për shkak se kemi 25 ndërprerës limit, të gjithë do të ndajnë një linjë të përbashkët 3.3V dhe një linjë të përbashkët GND. Pastaj, linja e sinjalit nga secili ndërprerës limit do të bashkohet në grupe prej 8 vetash dhe do të lidhet me lidhjet pmod në tabelën Basys3 duke përdorur tela të kërcyesit me zinxhirë për të minimizuar rrëmujën monumentale që do të bëjmë. Shihni Figurën 4 ose një shembull të tetë çelësave të parë.

Hapi 4: Konfigurimi i VHDL (Vivado)

Konfigurimi VHDL (Vivado)
Konfigurimi VHDL (Vivado)
Konfigurimi VHDL (Vivado)
Konfigurimi VHDL (Vivado)

Gjeneratori i valës sinus dhe gjeneratori PWM u testuan së pari për të siguruar që koncepti ynë funksionoi, pastaj kufizuesi i hyrjes dhe shtuesi/zhvendosësi i amplitudës u integruan. Detajet e funksionit dhe I/O të secilit bllok procesi janë siç tregohen në Figurë. Kodi është treguar më poshtë, por gjithashtu i bashkangjitur si skedarë VHD dhe txt. Nëse ka mospërputhje, shkoni me skedarët VHD.

BTW: ne ndoshta duhet t'i kishim bërë linjat tona më të shkurtra, por ngulitja e kodit në Instructables gjithashtu doli të ishte mjaft e bezdisshme për tu trajtuar, kështu që distanca nuk është më e madhja dhe nuk ka asnjë theksim sintaksor. Nëse keni Vivado dhe dëshironi të ndiqni kodin, ju rekomandojmë që thjesht të shkarkoni skedarin.

Së pari, le të shohim modulin e Gjeneratorit të Valës Sine.

biblioteka IEEE; përdorni IEEE. STD_LOGIC_1164. ALL; përdorni IEEE. NUMERIC_STD. ALL; entiteti Wave_Generator është Port (Shkaktuesi: në STD_LOGIC; - Shtypja kryesore Freq_Cnt: në STD_LOGIC_VECTOR (15 poshtë 0); - Vlera e numëruesit = 100MHz / (Shënim Frekuenca*64 Divizionet e Sine Wave) (raundi në numrin më të afërt) - riemërtohet nga Freq wavegenCLK: në STD_LOGIC; - Basys3 100MHz CLK WaveOut: jashtë STD_LOGIC_VECTOR (9 poshtë 0)); - Amplituda e nënshkruar e fundit të valës Wave_Generator; arkitektura Sjellja e Gjeneratorit të Valës është sinjali i: diapazoni i plotë 0 deri 64: = 0; -indeksi i tipit të kujtesës së amplitudës së bankës së kujtesës është një grup (0 deri në 63) i rangut të plotë -64 në 63; - krijoni një bankë memorie (ROM) për të mbajtur vlerat e amplitudës- a është kjo RAM apo ROM që thjesht po pyesin… amplituda e sinjalit: lloji i kujtesës: = (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); - banka e amplitudës së kujtesës për procesin e fillimit të valës sinusore (wavegenCLK, Trigger) numëruesi i ndryshueshëm: i panënshkruar (15 poshtë në 0): = në_nënshkruar (0, 16); - numëruesi i orës ndarës, i riemëruar nga numërimi 1 fillon nëse (buza_-ngritëse (wavegenCLK)) pastaj nëse (Shkakton = '1') atëherë- çelësi shtypet kundër: = kundër + 1; nëse (numëruesi = i panënshkruar (Freq_Cnt)) atëherë - Freq_Cnt = 100Mhz / (shënoni frekuencën * 64 ndarjet e valës sinusale) - rivendosni numëruesin dhe caktoni të dhënat e amplitudës në numëruesin e daljes: = në_nënshkruar (0, 16); WaveOut <= STD_LOGIC_VECTOR (nënshkruar me (amplituda (i), 10)); - rritje i për leximin tjetër i <= i + 1; - rivendosni i nëse një valë sinus është përfunduar nëse (i = 63) atëherë i <= 0; mbaron nëse; mbaron nëse; - (counter = pa shenjë (Freq_Cnt)) tjetër- çelësi nuk shtypet- rivendosni daljen, indeksin e amplitudës dhe numëruesin WaveOut <= "0000000000"; i <= 0; numërues: = të_nënshkruar (0, 16); -dalja e Amplituda = -64 kur asnjë notë nuk luhet në fund nëse; - (Shkakton = '1') fund nëse; - (skaji i ngritjes (CLK)) përfundimi i procesit; fund Sjellja;

Ne do të krijojmë një valë sinus dixhitale në Basys3 duke përdorur orën e brendshme dhe një ROM. Ky ROM do të ruajë 64 vlera që përfaqësojnë 64 amplituda në një valë sinus. Shih Figurën 1. 64 vlerat që ne përdorim imitojnë një valë sinus me rezolucion mjaft të mirë.

Duke përdorur orën e brendshme, ne llogarisim në një vlerë që përfaqëson shpejtësinë e orës të ndarë me frekuencën e valës që duam dhe 64: Clk div = 100MHz / (Freq * 64) Sa herë që numëruesi ynë arrin atë vlerë, ne thërrasim një numër nga ROM dhe dërgojeni atë nga moduli ynë i gjeneruesit të valëve. Frekuenca e valës sonë do të varet nga sa shpejt i quajmë këto amplituda.

Do të kemi 25 nën-module, secila të lidhura me një frekuencë/shënim.

Këtu është pjesa e mbetur e kodit që thërret modulet e Gjeneratorit të Valës Sine:

biblioteka IEEE; përdorni IEEE. STD_LOGIC_1164. ALL; përdorni IEEE. NUMERIC_STD. ALL; entiteti Two_Octave_Synth është Port (CLK: në STD_LOGIC; O4: në STD_LOGIC_VECTOR (11 poshtë 0); O5: në STD_LOGIC_VECTOR (12 poshtë 0); dalja: jashtë STD_LOGIC); fundi Dy_Oktava_Sinta; arkitektura Sjellja e Two_Octave_Synth është komponent Wave_Generator është Port (Shkaktar: në STD_LOGIC; Freq_Cnt: në STD_LOGIC_VECTOR (15 poshtë 0); wavegenCLK: në STD_LOGIC; WaveOut: jashtë STD_LOGIC_ (9) komponenti përfundimtar; --------------------------- sinjale dalëse nga gjeneratori i valëve ------------------ ----- sinjalizojnë WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveGs5, WaveA5, WaveAs5, WaveB5, WaveC6: nënshkruar (9 poshtë 0); -------------------------------- për logjikën e përzgjedhjes së shënimeve -------------- ------ sinjal 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: pa shenjë (4 në 0); sinjal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntF5, cntFs5, cntG5, cntGs5, cntA5, cntAs5, cntB5, cntC6: pa shenjë (4 në 0); gabimi i sinjalit: STD_LOGIC; ----------------------------------- për shtimin e valëve të sinusit ----------- --------------- sinjali Wave0, Wave1, Wave2, Wave3: nënshkruar (9 poshtë 0); -sinjale nga sinjali i daljes së modulit Wave Generator WaveSum: STD_LOGIC_VECTOR (9 në 0); --signal për valët e sinusit të përmbledhur (komplimenti i 2 -të -512 deri në 511) sinjal pozitivWaveSum: STD_LOGIC_VECTOR (9 poshtë 0); -pa nënshkruar 0 deri në 1023, për përdorim në gjeneratorin PWM ----------------------------------- për gjenerimin e PWM ------------------------------- sinjali i gjatësisë së pingut: pa shenjë (9 poshtë 0): = pa shenjë (positiveWaveSum); --signal off_length: i panënshkruar (6 poshtë 0): = i_nënshkruar (127, 7) -pa shenjë (WAVE); sinjal PWM: i panënshkruar (9 poshtë 0): = tek_i panënshkruar (0, 10); fillo Shënim_C4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveC4); --5973, 261.63 Hz Shënim_Cs4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveCs4);-5638, 277.18 Hz Shënim_D4: Harta e portit të Wave_Generator (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveD4); --5321, 293.66 Hz Shënim_Ds4: Harta e portit të Wave_Generator (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveDs4);-5023, 311.13 Hz Shënim_E4: Harta e portit të Wave_Generator (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveE4); --4741, 329.63 Hz Shënim_F4: Harta e portit të Wave_Generator (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveF4); --4475, 349.23 Hz Shënim_Fs4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveFs4);-4224, 369.99 Hz Shënim_G4: Harta e portit të Wave_Generator (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveG4); --3986, 392.00 Hz Shënim_Gs4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveGs4);-3763, 415.30 Hz Shënim_A4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveA4); --3552, 440.00 Hz Shënim_As4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveAs4);-3352, 466.16 Hz Shënim_B4: Harta e portit të Wave_Generator (Shkaktuesi => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveB4); --3164, 493.88 Hz ------------------------------------------------ ------------------------------------------------------ --------------------------- Shënim_C5: Harta e portit të Wave_Generator (Shkaktuesi => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, e nënshkruar (WaveOut) => WaveC5); --2987, 523.25 Hz Shënim_Cs5: Harta e portit të Wave_Generator (Shkaktuesi => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveCs5);-2819, 554.37 Hz Shënim_D5: Harta e portit të Wave_Generator (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveD5); --2661, 587.33 Hz Shënim_Ds5: Harta e portit të Wave_Generator (Shkakton => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveDs5);-2512, 622.25 Hz Shënim_E5: Harta e portit të Wave_Generator (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveE5); --2371, 659.25 Hz Shënim_F5: Harta e portit të Wave_Generator (Shkaktoni => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveF5); --2238, 698.46 Hz Shënim_Fs5: Harta e portit të Wave_Generator (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveFs5);-2112, 739.99 Hz Shënim_G5: Harta e portit të Wave_Generator (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveG5); --1994, 783.99 Hz Shënim_Gs5: Harta e portit të Wave_Generator (Shkaktuesi => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveGs5);-1882, 830.61 Hz Shënim_A5: Harta e portit të Wave_Generator (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveA5); --1776, 880.00 Hz Shënim_As5: Harta e portit të Wave_Generator (Shkaktuesi => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveAs5);-1676, 932.33 Hz Shënim_B5: Harta e portit të Wave_Generator (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveB5); --1582, 987.77 Hz Shënim_C6: Harta e portit të Wave_Generator (Shkaktuesi => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, nënshkruar (WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ logjika e përzgjedhjes së shënimeve ------------ 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; Përzgjedhja: Procesi (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveGs5, WaveA5, WaveAs5, WaveB5, WaveC6) fillojnë nëse (cntC6 = "00000") pastaj --------------- nëse nuk krijohen sinjale Wave0 <= "0000000000"; Vala1 <= "0000000000"; Vala2 <= "0000000000"; Vala3 <= "0000000000"; përndryshe nëse (O4 (0) = '1') atëherë ------------------- shënimi C4 ka luajtur Wave0 Wave0 Wave1 error Wave0 Wave1 Wave2 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 Wave1 Wave2 Wave3 gabim Wave0 < = WaveC6; Vala1 <= "0000000000"; Vala2 <= "0000000000"; Vala3 Vala1 <= ValaC6; Vala2 <= "0000000000"; Vala3 Vala2 <= ValaC6; Gabim Wave3 Wave3 Wave1 <= "0000000000"; Vala2 <= "0000000000"; Vala3 Vala2 <= "0000000000"; Wave3 Gabim Wave3 <= '1'; rasti përfundimtar; mbaron nëse; mbaron nëse; përfundimi i procesit; ------------- shtues i valëve të sinusit -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- bëjeni valën e sinusit pozitiv për pwm --------------------- pozitiveWaveSum <= jo WaveSum (9) & WaveSum (8 poshtë në 0); ------------- Gjenerator PWM --------------------- proces (CLK)-numër i ndryshueshëm: i panënshkruar (1 në 0): = të_nënshkruar (0, 2); filloni nëse (buza_ -ngritëse (CLK)) atëherë -numëroni: = numëroni + 1; --if (numëroni = të_nënshkruar (4, 2)) pastaj-numëroni: = të_nënshkruar (0, 2); nëse nëse; përfundoj nëse; përfundoj procesin; përfundoj Sjelljen;

4 Përzgjedhës i Shënimeve Pjesa më e ndërlikuar e këtij projekti është përzgjedhja e vetëm katër frekuencave. Ne e bëmë atë me një deklaratë të tërë lotta IF, dhe përdorëm sinjale në vend të variablave në mënyrë që procesi të simulohet dhe të korrigjohet. Ne provuam metoda të tjera duke përdorur variabla dhe sythe FOR, por hasëm në gabime të kohës së ekzekutimit. Kështu, në fund, vendosëm që nëse funksionon, do ta lëmë vetëm. Mos e rregulloni atë që nuk është amirit i thyer?

Katër valët dalëse janë etiketuar Wave0, Wave1, Wave2, Wave3 - këto janë ato që do të shtohen së bashku për të formuar daljen përfundimtare.

Duke parë kodin, do të shihni një mori sinjalesh të etiketuar C4, Cs4, D4, Ds4, etj. Këto janë sinjale 5-bit që marrin shkasin përkatës nga O4 (oktava 4) ose O5 (oktava 5) dhe i bëjnë ato 5-bit për të shtuar.

Më tej, ndryshoret cntC4, cntCs4, etj përfaqësojnë sa shënime më të ulëta se shënimi i synuar janë luajtur, përfshirë shënimin e synuar. Për shembull, nëse luhen C4, E4, G4, A#4 dhe D5 (korda C9) cntC4 do të jetë 1, cntE4 do të jetë 2, cntG4 do të jetë 3, etj.

Pastaj, sa herë që luhet një notë, numërimi për shënimin e synuar do të shqyrtohet për të parë se ku të lidhë sinjalin e shënimit. Për shembull, nëse luhet nota D5 (që do të thotë O5 (2) është e lartë) dhe cntD5 është 3, atëherë aktualisht janë duke u luajtur 3 nota, me 2 nota më të ulëta se D5, kështu që ne do të lidhim waveD5 me Wave2 (vala e tretë numërimi i sinjalit nga Wave0). Përndryshe, nëse cntD5 është 5, atëherë aktualisht janë duke luajtur 5 nota, me 4 nota më të ulëta se D5, kështu që ne do ta lëmë valën5 të varur dhe nuk do të bëjmë asgjë me të.

Deklaratat IF përsëriten pastaj për të mbuluar rastet për të 25 shënimet.

Adplitude Adder

Pasi zgjidhen 4 valët më të ulëta, duhet t'i shtojmë së bashku. Arsyeja që ne do të shtojmë vetëm katër shënime së bashku është sepse ideja PWM që ne po përdorim për daljen tonë mund të ketë vetëm një rezolutë të caktuar derisa PWM të funksionojë shumë ngadalë dhe altoparlanti të fillojë të marrë valën katrore PWM. Për shembull, nëse do të përdorim një rezolucion prej 8192 (13 bit), secila prej atyre 8192 pikave duhet të korrespondojë me një skaj në rritje të orës në bord. Pra, 100MHz / 8192 = 12.2kHz, e cila është mirë brenda kufirit të dëgjimit njerëzor.

Shtimi aktual i amplitudave është super i thjeshtë, thjesht duhet të siguroheni që mund të funksionojë vërtet shpejt.

Dalja e PWM

Cikli i punës i PWM do të përfaqësojë amplituda e valës sonë të prodhimit në atë moment. Për shembull, nëse kemi një diapazon amplituda prej 0 deri në 128, 0 do të ishte një cikël pune 0%, 64 do të ishte 50%, 128 do të ishte 100%, etj. Ky PWM do të funksionojë jashtëzakonisht shpejt (yni është 97.6 kHz), aq shpejt sa altoparlanti nuk do të njohë valët individuale katrore dhe në vend të kësaj do të shikojë tensionin mesatar, duke krijuar sinjalin tonë "analog".

Skedari i Kufizimeve

Ju mund ta keni lidhur pajisjen tuaj ndryshe, prandaj sigurohuni që skedari i kufizimeve të përputhet.

Hapi 5: Shkarkimet e Kodit

Më poshtë është kodi, si në formatin.txt ashtu edhe.vhd për Vivado. Wave_Generator është nën-moduli i gjeneratorit të valëve, dhe Two_Octave_Synth është moduli kryesor me gjithçka tjetër.

Recommended: