Talaan ng mga Nilalaman:

Basys3 FPGA Digital Audio Synthesizer: 5 Hakbang
Basys3 FPGA Digital Audio Synthesizer: 5 Hakbang

Video: Basys3 FPGA Digital Audio Synthesizer: 5 Hakbang

Video: Basys3 FPGA Digital Audio Synthesizer: 5 Hakbang
Video: AMD Xilinx Arty A7, Artix 7 FPGA Evaluation Board - Getting Started 2024, Hulyo
Anonim
Image
Image
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer

Ang digital sine wave keyboard synthesizer na ito ay kukuha ng mga input ng gumagamit sa pamamagitan ng isang serye ng mga pansamantalang switch na inilatag tulad ng isang keyboard at naglalabas ng isang audio wave sa pamamagitan ng isang speaker. Batay sa mga pag-input ng gumagamit, bubuo ang aparato ng mga sine alon ng iba't ibang mga frequency mula C4 hanggang C6. Maaaring maglagay ang gumagamit ng mga tala mula sa C4 hanggang sa C6 (kabuuang 25 tala), at hanggang sa apat na mga key nang sabay - kung higit sa apat na mga pindutan ang pinindot, ang apat na pinakamababang tono ay tutugtugin.

Ang proyektong ito ay ginawa ni Ryan Morris at Mavis Tsoi para sa aming klase ng Cal Poly CPE 133 Digital Design:)

Hakbang 1: Teorya

Ang isang FPGA board ay maaari lamang maglabas ng mga digital signal. Sa madaling salita, makakagawa lamang ito ng isang mataas (3.3V) boltahe o isang mababang (0V) boltahe. Gayunpaman, ang mga audio signal ay analog at maaaring magkaroon ng walang hanggan maraming mga pagtaas sa boltahe. Upang maiikot ito, gagamit kami ng isang signal ng PWM (pulse width modulation) na tularan ang isang analog na alon. Kung hindi mo alam kung ano ang PWM, suriin ito:

Hakbang 2: Mga Sangkap at Tool

  • Computer na may naka-install na Vivado
  • Gagamitin namin ang Vivado bersyon 2017.2
  • Basys3 FPGA Board
  • 25 SPDT Limit Switches (ginamit namin ito)
  • 30 mga jumper wires (isang dulo ng lalaki, ibang dulo ay hindi mahalaga), 12 pulgada
  • Mga pamutol ng wire
  • Mga striper ng wire
  • Spare wire para sa paghihinang
  • Resin-core Solder
  • Panghinang
  • ¼”babaeng audio jack
  • Amplifier / speaker
  • Isang bagay upang mai-mount ang mga switch (gumamit kami ng protoboard + kahon na gawa sa kahoy)

Hakbang 3: Pag-setup ng Mga Kable at Hardware

Mga Pag-setup ng Kable at Hardware
Mga Pag-setup ng Kable at Hardware
Mga Pag-setup ng Kable at Hardware
Mga Pag-setup ng Kable at Hardware
Mga Pag-setup ng Kable at Hardware
Mga Pag-setup ng Kable at Hardware

System Architecture

Tingnan ang Larawan 1: 25 magagamit na mga input → Basys3 Board → amplifier at speaker.

Paglabas

Tingnan ang Larawan 2: Basys3 Board → 1/2 Babae Audio Jack → Speaker (na may Amplifier)

Input

Ang mga koneksyon ng pmod sa board ng Basys3 ay dapat na konektado sa ground upang makita ang isang mababang input at hindi gagana nang maayos kung naiwan bilang isang bukas na circuit. Dahil dito, kailangan naming gumamit ng mga switch ng SPDT para sa lahat ng aming mga note key. Karaniwang pinapayagan ng isang switch ng SPDT ang gumagamit na lumipat sa pagitan ng mga circuit kapag pinindot, kaya gagamitin namin ang mga ito bilang aming "mga pindutan" upang mag-input ng mababa (0V) o mataas (3.3V) na mga signal sa board ng Basys3.

Ang bawat switch ay magkakaroon ng HINDI (karaniwang binuksan) na terminal na konektado sa 3.3V, NC (karaniwang sarado) na terminal na konektado sa GND, at COM (karaniwang) terminal na konektado sa input ng FPGA. Tingnan ang Larawan 3.

Dahil mayroon kaming 25 limit switch, magbabahagi silang lahat ng isang karaniwang linya ng 3.3V at isang karaniwang linya ng GND. Pagkatapos, ang linya ng signal mula sa bawat limitasyon ng switch ay mai-iipon sa mga pangkat ng 8 at mai-hook up sa mga koneksyon sa pmod sa board ng Basys3 gamit ang mga zippable jumper wires upang i-minimize ang napakalaking kaguluhan na gagawin namin. Tingnan ang Larawan 4 o isang halimbawa ng unang walong mga susi.

Hakbang 4: Pag-setup ng VHDL (Vivado)

Pag-set up ng VHDL (Vivado)
Pag-set up ng VHDL (Vivado)
Pag-set up ng VHDL (Vivado)
Pag-set up ng VHDL (Vivado)

Ang sine wave generator at PWM generator ay unang sinubukan upang matiyak na gumana ang aming konsepto, pagkatapos ang input limiter at amplitude adder / shifter ay isinama. Ang mga detalye ng pagpapaandar at I / O ng bawat proseso ng block ay tulad ng ipinakita sa Larawan. Ang code ay ipinapakita sa ibaba, ngunit naka-attach din bilang VHD at txt file. Kung may mga pagkakaiba, sumama sa mga file ng VHD.

BTW: marahil ay dapat nating gawing mas maikli ang aming mga linya ngunit ang pag-embed ng code sa Mga Instructionable ay naging nakakainis na makitungo, kaya't ang spacing ay hindi ang pinakadakilang at walang pag-highlight ng syntax. Kung mayroon kang Vivado at nais na sundin ang code, lubos naming inirerekumenda na i-download mo lamang ang file.

Una, tingnan natin ang module ng Sine Wave Generator.

library IEEE; gamitin ang IEEE. STD_LOGIC_1164. ALL; gamitin ang IEEE. NUMERIC_STD. ALL; entity Wave_Generator ay Port (Trigger: sa STD_LOGIC; - Key press Freq_Cnt: sa STD_LOGIC_VECTOR (15 hanggang 0); - Counter value = 100MHz / (Frequency ng Tandaan * 64 Mga Dibisyon ng Sine Wave) (bilog sa pinakamalapit na num) - pinalitan ng pangalan mula sa Freq wavegenCLK: sa STD_LOGIC; - Basys3 100MHz CLK WaveOut: labas ng STD_LOGIC_VECTOR (9 hanggang 0)); - Naka-sign amplitude ng wave end Wave_Generator; arkitektura Pag-uugali ng Wave_Generator ay signal i: saklaw ng integer 0 hanggang 64: = 0; - index ng amplitude memory bank type memory_type ay array (0 hanggang 63) ng saklaw ng integer -64 hanggang 63; - Lumikha ng memory bank (ROM) upang magkaroon ng mga halaga ng amplitude - nagtataka lang ang RAM o ROM na ito… signal amplitude: 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); - amplitude memory bank para sa pagsisimula ng proseso ng sine wave (wavegenCLK, Trigger) variable counter: unsigned (15 downto 0): = to_unsigned (0, 16); - clock divider counter, pinalitan ng pangalan mula sa count1 magsimula kung (tumataas_edge (wavegenCLK)) pagkatapos kung (Trigger = '1') pagkatapos - ang key ay pinindot na counter: = counter + 1; kung (counter = unsigned (Freq_Cnt)) pagkatapos - Freq_Cnt = 100Mhz / (note freq * 64 na mga dibisyon ng sine wave) - i-reset ang counter at magtalaga ng data ng amplitude sa output counter: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitude (i), 10)); - dagdagan i para sa susunod na pagbabasa i <= i + 1; - I-reset i kung ang isang alon ng sine ay nakumpleto kung (i = 63) pagkatapos ay i <= 0; tapusin kung; tapusin kung; - (counter = unsigned (Freq_Cnt)) iba pa - ang key ay hindi pinindot - i-reset ang output, amplitude index, at counter WaveOut <= "0000000000"; ako <= 0; counter: = to_unsigned (0, 16); --output Amplitude = -64 kapag walang tala ang na-play end kung; - (Trigger = '1') magtatapos kung; - (tumataas na_edge (CLK)) na proseso ng pagtatapos; wakasan ang Pag-uugali;

Lilikha kami ng isang digital sine wave sa Basys3 sa pamamagitan ng paggamit ng panloob na orasan at isang ROM. Ang ROM na ito ay mag-iimbak ng 64 na halaga na kumakatawan sa 64 amplitude sa isang sine wave. Tingnan ang Larawan 1. Ang 64 na halagang ginagamit namin ay tularan ang isang sine alon na may mahusay na resolusyon.

Gamit ang panloob na orasan, binibilang namin ang isang halaga na kumakatawan sa bilis ng orasan na hinati sa dalas ng alon na gusto namin at 64: Clk div = 100MHz / (Freq * 64) Sa tuwing maaabot ng aming counter ang halagang iyon, tumatawag kami ng isang numero mula sa ang ROM at ipadala iyon sa aming module ng generator ng alon. Ang dalas ng aming alon ay nakasalalay sa kung gaano kabilis natin tawagan ang mga amplitude na ito.

Magkakaroon kami ng 25 mga sub-module, bawat isa ay naiugnay sa isang dalas / tala.

Narito ang natitirang code na tumatawag sa mga module ng Sine Wave Generator:

library IEEE; gamitin ang IEEE. STD_LOGIC_1164. ALL; gamitin ang IEEE. NUMERIC_STD. ALL; ang entity na Two_Octave_Synth ay Port (CLK: sa STD_LOGIC; O4: sa STD_LOGIC_VECTOR (11 hanggang 0); O5: sa STD_LOGIC_VECTOR (12 hanggang 0); output: out STD_LOGIC); tapusin ang Dalawang_Octave_Synth; ang arkitekturang Pag-uugali ng Dalawang_Octave_Synth ay bahagi ng Wave_Generator ay Port (Trigger: sa STD_LOGIC; Freq_Cnt: sa STD_LOGIC_VECTOR (15 pababa sa 0); pagtatapos bahagi; --------------------------- signal ng output mula sa generator ng alon ------------------ ----- signal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveFs,aveve WaveAs5, WaveB5, WaveC6: nilagdaan (9 hanggang 0); ---- para sa tala ng pagpili ng tala ------------ ------ 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: hindi pinirmahan (4 hanggang 0); signal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntF5, cnt55, cntF5, cnt5, cnt5, cnt5: unsigned (4 hanggang 0); signal error: STD_LOGIC; ----------------------------------- para sa pagdaragdag ng sine waves ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: naka-sign (9 hanggang 0); - mga signal mula sa signal ng output ng module ng Wave Generator na WaveSum: STD_LOGIC_VECTOR (9 hanggang 0); --signal para sa summed sine waves (2's papuri -512 hanggang 511) positibong signalWaveSum: STD_LOGIC_VECTOR (9 hanggang 0); --disenyo 0 hanggang 1023, para magamit sa generator ng PWM ----------------------------------- para sa pagbuo ng PWM ------------------------------ signal ping_length: unsigned (9 hanggang 0): = unsigned (positiveWaveSum); --signal off_length: unsigned (6 downto 0): = to_unsigned (127, 7) - unsigned (WAVE); signal PWM: unsigned (9 downto 0): = to_unsigned (0, 10); simulan ang Note_C4: Wave_Generator port map (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, naka-sign (WaveOut) => WaveC4); --5973, 261.63 Hz Note_Cs4: Wave_Generator port map (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, naka-sign (WaveOut) => WaveCs4); - 5638, 277.18 Hz Note_D4: Wave_Generator port map (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, naka-sign (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Wave_Generator port map (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, naka-sign (WaveOut) => WaveDs4); - 5023, 311.13 Hz Note_E4: Wave_Generator port map (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, naka-sign (WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Wave_Generator port map (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, naka-sign (WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Wave_Generator port map (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, naka-sign (WaveOut) => WaveFs4); - 4224, 369.99 Hz Note_G4: Wave_Generator port map (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, naka-sign (WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Wave_Generator port map (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, naka-sign (WaveOut) => WaveGs4); - 3763, 415.30 Hz Note_A4: Wave_Generator port map (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, naka-sign (WaveOut) => WaveA4); --3552, 440.00 Hz Note_As4: Wave_Generator port map (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, naka-sign (WaveOut) => WaveAs4); - 3352, 466.16 Hz Note_B4: Wave_Generator port map (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, naka-sign (WaveOut) => WaveB4); --3164, 493.88 Hz -------------------------------------------- ---- --------------------------- Note_C5: Wave_Generator port map (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, nilagdaan (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Wave_Generator port map (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, naka-sign (WaveOut) => WaveCs5); - 2819, 554.37 Hz Note_D5: Wave_Generator port map (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, naka-sign (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Wave_Generator port map (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, naka-sign (WaveOut) => WaveDs5); - 2512, 622.25 Hz Note_E5: Wave_Generator port map (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, naka-sign (WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Wave_Generator port map (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, naka-sign (WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Wave_Generator port map (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, naka-sign (WaveOut) => WaveFs5); - 2112, 739.99 Hz Note_G5: Wave_Generator port map (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, naka-sign (WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Wave_Generator port map (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, naka-sign (WaveOut) => WaveGs5); - 1882, 830.61 Hz Note_A5: Wave_Generator port map (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, naka-sign (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Wave_Generator port map (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, naka-sign (WaveOut) => WaveAs5); - 1676, 932.33 Hz Note_B5: Wave_Generator port map (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, naka-sign (WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Wave_Generator port map (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, naka-sign (WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ tala ng pagpili ng lohika ------------ 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; Pinili: proseso (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave W5,5 WaveB5, WaveC6) magsimula kung (cntC6 = "00000") pagkatapos ay ------------- kung walang mga signal na nabuo Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; kung hindi man (O4 (0) = '1') pagkatapos ------------------- tandaan C4 nilalaro Wave0 Wave0 Wave1 error Wave0 Wave1 Wave2 error Wave0 Wave1 Wave2 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 Wave3 Wave3 Wave2 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 Wave2 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave3 Wave = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 error Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Error sa Wave3 Wave3 <= '1'; kaso ng pagtatapos; tapusin kung; tapusin kung; proseso ng pagtatapos; ------------- sine wave adder -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- gawing positibo ang sine wave para sa pwm --------------------- positiveWaveSum <= hindi WaveSum (9) & WaveSum (8 hanggang 0); ------------- PWM generator --------------------- proseso (CLK) --Variable count: unsigned (1 downto 0): = to_unsigned (0, 2); simulan kung (tumataas_edge (CLK)) pagkatapos --count: = count + 1; --kung (count = to_unsigned (4, 2)) pagkatapos --count: = to_unsigned (0, 2); --kung (PWM = to_ kung (PWM <ping_length) pagkatapos ay output <= '1'; iba pa ang output <= '0'; tapusin kung; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end kung; tapusin kung; tapusin ang proseso; tapusin ang Pag-uugali;

4 Note Selector Ang pinakahirapang bahagi ng proyektong ito ay ang pagpili ng apat na frequency lamang. Ginawa namin ito sa isang buong pahayag ng lotta KUNG, at gumamit kami ng mga signal sa halip na mga variable upang ang proseso ay maaaring gayahin at ma-debug. Sinubukan namin ang iba pang mga pamamaraan gamit ang mga variable at PARA sa mga loop, ngunit tumakbo sa mga error sa run-time. Kaya, sa huli, napagpasyahan namin na kung gagana ito, iiwan namin itong mag-isa. Huwag ayusin kung ano ang hindi nasirang amirite?

Ang apat na alon ng output ay may label na Wave0, Wave1, Wave2, Wave3 - ito ang idaragdag na magkasama upang mabuo ang pangwakas na output.

Sa pagtingin sa code, makikita mo ang isang bungkos ng mga signal na may label na C4, Cs4, D4, Ds4, atbp. Ito ang 5-bit signal na kukuha ng kaukulang gatilyo mula sa O4 (oktaba 4) o O5 (oktaba 5) at gawin ang mga ito 5-bit para sa pagdaragdag.

Susunod na mga variable ng cntC4, cntCs4, atbp ay kumakatawan sa kung gaano karaming mga tala na mas mababa kaysa sa target na tala ang na-play, kasama na ang target na tala. Halimbawa, kung ang C4, E4, G4, A # 4, at D5 ay nilalaro (C9 chord) cntC4 ay magiging 1, ang cntE4 ay magiging 2, ang cntG4 ay magiging 3, atbp.

Pagkatapos, tuwing nilalaro ang isang tala, ang bilang para sa target na tala ay susuriin upang makita kung saan ilalagay ang signal ng tala. Halimbawa pagbibilang ng signal mula sa Wave0). Bilang kahalili, kung ang cntD5 ay 5, kung gayon mayroong kasalukuyang 5 tala na nilalaro, na may 4 na tala na mas mababa sa D5, kaya iiwan lamang namin ang waveD5 na nakabitin at hindi gagawa ng anumang bagay dito.

Ang mga pahayag na KUNG pagkatapos ay paulit-ulit upang masakop ang mga kaso para sa lahat ng 25 tala.

Amplitude Adder

Matapos mapili ang pinakamababang 4 na alon kailangan nating idagdag ang mga ito nang magkasama. Ang kadahilanan ay magdaragdag lamang kami ng apat na tala nang magkasama ay dahil ang ideyang PWM na ginagamit namin para sa aming output ay maaari lamang magkaroon ng isang tiyak na resolusyon hanggang sa masyadong mabagal ang pagpapatakbo ng PWM at magsisimulang kunin ng speaker ang PWM square wave. Halimbawa, kung gagamit kami ng isang resolusyon ng 8192 (13 bit), ang bawat isa sa mga 8192 na puntos na iyon ay dapat na tumutugma sa isang tumataas na gilid ng onboard na orasan. Kaya, 100MHz / 8192 = 12.2kHz, na nasa loob ng saklaw ng pandinig ng tao.

Ang tunay na pagdaragdag ng mga amplitude ay napakasimple, tiyakin mo lamang na maaari itong tumakbo nang napakabilis.

PWM Output

Ang siklo ng tungkulin ng PWM ay kumakatawan sa amplitude ng aming output wave sa instant na iyon. Halimbawa, kung mayroon tayong saklaw ng amplitude na 0 hanggang 128, 0 ay isang 0% na cycle ng tungkulin, 64 ay magiging 50%, 128 ay 100%, atbp. Ang PWM na ito ay tatakbo nang napakabilis (ang atin ay 97.6 kHz), napakabilis na hindi makikilala ng nagsasalita ang mga indibidwal na square square at sa halip ay tumingin sa average na boltahe, na lumilikha ng aming signal na "analog".

Mga Pinipigilan na File

Maaaring nai-hook mo ang iyong hardware nang iba, kaya siguraduhin lamang na ang mga hadlang na file ay tumutugma.

Hakbang 5: Mga Pag-download ng Code

Nasa ibaba ang code, kapwa sa format na.txt at.vhd para sa Vivado. Ang Wave_Generator ay ang sub-module ng generator generator, at ang Two_Octave_Synth ang nangungunang module sa lahat ng iba pa.

Inirerekumendang: