INHOUDSOPGAWE:

Basys3 FPGA Digital Audio Synthesizer: 5 stappe
Basys3 FPGA Digital Audio Synthesizer: 5 stappe

Video: Basys3 FPGA Digital Audio Synthesizer: 5 stappe

Video: Basys3 FPGA Digital Audio Synthesizer: 5 stappe
Video: A FPGA Based MIDI Synthesizer! 2024, Julie
Anonim
Image
Image
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer

Hierdie digitale sinusgolf -klawerbord -sintetiseerder neem die gebruiker se insette via 'n reeks kortstondige skakelaars soos 'n sleutelbord en stuur 'n klankgolf deur 'n luidspreker. Op grond van gebruikersinvoer, sal die toestel sinusgolwe van verskillende frekwensies van C4 tot C6 genereer. Die gebruiker kan notas invoer van C4 tot C6 (25 note in totaal) en tot vier sleutels tegelyk - as meer as vier sleutels ingedruk word, word die vier laagste klanke gespeel.

Hierdie projek is gedoen deur Ryan Morris en Mavis Tsoi vir ons Cal Poly CPE 133 Digital Design -klas:)

Stap 1: Teorie

'N FPGA -bord kan slegs digitale seine stuur. Met ander woorde, dit kan slegs 'n hoë (3.3V) spanning of 'n lae (0V) spanning produseer. Die klankseine is egter analoog en kan oneindig baie spanningsverhogings hê. Om dit te vermy, gebruik ons 'n PWM (pulswydte modulasie) sein om 'n analoog golf na te boots. As u nie weet wat PWM is nie, kyk hier:

Stap 2: Bestanddele en gereedskap

  • Rekenaar met Vivado geïnstalleer
  • Ons gebruik Vivado weergawe 2017.2
  • Basys3 FPGA Board
  • 25 SPDT Limit Switches (ons het dit gebruik)
  • 30 springdrade (een kant mannetjie, ander kant maak nie saak nie), 12 duim
  • Draadknipper
  • Draadstroppers
  • Spaardraad vir soldeer
  • Hars-kern soldeer
  • Soldeerbout
  • ¼”vroulike klankaansluiting
  • Versterker/luidspreker
  • Iets om die skakelaars aan te sit (ons het protoboard + houtkas gebruik)

Stap 3: Bedrading en hardeware -opstelling

Bedrading en hardeware -opstelling
Bedrading en hardeware -opstelling
Bedrading en hardeware -opstelling
Bedrading en hardeware -opstelling
Bedrading en hardeware -opstelling
Bedrading en hardeware -opstelling

Stelsel argitektuur

Sien Figuur 1: 25 beskikbare insette → Basys3 Board → versterker en luidspreker.

Uitset

Sien figuur 2: Basys3 -bord → 1/2 vroulike klankaansluiting → luidspreker (met versterker)

Invoer

Die pmod -verbindings op die Basys3 -bord moet aan die aarde gekoppel word om 'n lae inset te sien en sal nie behoorlik funksioneer as dit as 'n oop kring gelaat word nie. As gevolg hiervan moet ons SPDT -skakelaars vir al ons notasleutels gebruik. Met 'n SPDT -skakelaar kan die gebruiker basies tussen kringe skakel as hy gedruk word, so ons sal dit as ons 'knoppies' gebruik om lae (0V) of hoë (3.3V) seine na die Basys3 -bord in te voer.

Elke skakelaar sal die NO (normaalweg oop) aansluiting hê wat gekoppel is aan 3.3V, NC (normaal gesluit) aansluiting gekoppel aan GND, en COM (gemeenskaplike) aansluiting gekoppel aan die FPGA -ingang. Sien Figuur 3.

Omdat ons 25 eindskakelaars het, deel hulle almal 'n gemeenskaplike 3.3V -lyn en 'n gemeenskaplike GND -lyn. Dan word die seinlyn van elke eindskakelaar in groepe van 8 saamgebind en verbind met die pmod -verbindings op die Basys3 -bord met ritssluitende draaddrade om die monumentale gemors wat ons maak, tot die minimum te beperk. Sien Figuur 4 of 'n voorbeeld van die eerste agt sleutels.

Stap 4: VHDL -opstelling (Vivado)

VHDL -opstelling (Vivado)
VHDL -opstelling (Vivado)
VHDL -opstelling (Vivado)
VHDL -opstelling (Vivado)

Die sinusgolfopwekker en PWM -kragopwekker is eers getoets om seker te maak dat ons konsep werk, en daarna is die insetbeperking en amplitude -opteller/-verskakelaar geïntegreer. Besonderhede van die funksie en I/O van elke prosesblok is soos in die figuur getoon. Die kode word hieronder getoon, maar ook aangeheg as VHD- en txt -lêers. As daar afwykings is, gebruik die VHD -lêers.

BTW: ons moes waarskynlik ons reëls korter gemaak het, maar die inbedding van kode op Instructables was ook baie irriterend om te hanteer, dus die spasiëring is nie die grootste nie en daar is geen sintaksisverhoging nie. As u Vivado het en die kode wil volg, beveel ons u sterk aan om die lêer net af te laai.

Kom ons kyk eers na die Sine Wave Generator -module.

biblioteek IEEE; gebruik IEEE. STD_LOGIC_1164. ALL; gebruik IEEE. NUMERIC_STD. ALL; entiteit Wave_Generator is Port (Trigger: in STD_LOGIC; - Sleutel druk Freq_Cnt: in STD_LOGIC_VECTOR (15 afwaarts tot 0); - Tellerwaarde = 100MHz / (Let op frekwensie*64 afdelings van Sine Wave) (rond tot naaste nummer) - hernoem van Freq wavegenCLK: in STD_LOGIC; - Basys3 100MHz CLK WaveOut: uit STD_LOGIC_VECTOR (9 tot 0)); - Getekende amplitude van golfeinde Wave_Generator; argitektuur Gedrag van Wave_Generator is sein i: heelgetal reeks 0 tot 64: = 0; -indeks van amplitude geheue bank tipe memory_type is skikking (0 tot 63) van heelgetal reeks -64 tot 63; - skep geheue bank (ROM) om amplitudewaardes te hou- wonder hierdie RAM of ROM net … sein 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 geheue bank vir sinusgolf begin proses (wavegenCLK, Trigger) veranderlike teller: ongetekend (15 afwaarts tot 0): = tot_ontekend (0, 16); - klok verdeler teller, hernoem van count1 begin as (rising_edge (wavegenCLK)) dan as (Trigger = '1') dan- sleutel word teller ingedruk: = teller + 1; as (teller = ongeteken (Freq_Cnt)) dan - Freq_Cnt = 100Mhz / (let op freq * 64 afdelings van die sinusgolf) - stel die teller terug en ken amplitude -data toe aan die uitseteller: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitude (i), 10)); - verhoog i vir volgende lesing i <= i + 1; - reset i as een sinusgolf voltooi is as (i = 63) dan i <= 0; eindig as; eindig as; - (counter = unsigned (Freq_Cnt)) else- sleutel word nie ingedruk nie- reset uitset, amplitude-indeks en teller WaveOut <= "0000000000"; ek <= 0; teller: = aan_onderteken (0, 16); -uitvoer Amplitude = -64 wanneer geen noot gespeel word nie; - (Sneller = '1') eindig as; - (stygende_rand (CLK)) eindproses; einde Gedrag;

Ons sal 'n digitale sinusgolf in die Basys3 genereer deur die interne klok en 'n ROM te gebruik. Hierdie ROM sal 64 waardes stoor wat 64 amplitudes op 'n sinusgolf verteenwoordig. Sien Figuur 1. Die 64 waardes wat ons gebruik, boots 'n sinusgolf na met 'n redelike goeie resolusie.

Deur die interne klok te gebruik, tel ons tot 'n waarde wat die kloksnelheid voorstel gedeel deur die frekwensie van die golf wat ons wil hê en 64: Clk div = 100MHz / (Freq * 64) Elke keer as ons teller die waarde bereik, bel ons 'n nommer van die ROM en stuur dit uit ons golfgenerator module. Die frekwensie van ons golf sal afhang van hoe vinnig ons hierdie amplitudes noem.

Ons sal 25 submodules hê, elk met een frekwensie/noot.

Hier is die res van die kode wat die Sine Wave Generator -modules noem:

biblioteek IEEE; gebruik IEEE. STD_LOGIC_1164. ALL; gebruik IEEE. NUMERIC_STD. ALL; entiteit Two_Octave_Synth is Poort (CLK: in STD_LOGIC; O4: in STD_LOGIC_VECTOR (11 afwaarts tot 0); O5: in STD_LOGIC_VECTOR (12 afwaarts na 0); uitset: uit STD_LOGIC); beëindig Two_Octave_Synth; argitektuur Behavioral of Two_Octave_Synth is component Wave_Generator is Port (Trigger: in STD_LOGIC; Freq_Cnt: in STD_LOGIC_VECTOR (15 downto 0); wavegenCLK: in STD_LOGIC; WaveOut: out STD_LOGIC_VECTOR (9 downto 0)); eindkomponent; --------------------------- uitsetseine van golfgenerator ------------------ ----- sein WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, W5, W5, W5, W5, WaveAs5, WaveB5, WaveC6: onderteken (9 tot 0); -------------------------------- vir die kies van logika -------------- ------ sein 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: ongetekend (4 tot 0); sein cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cnt5, cnt5, cnt5, cnt5, cnt5, cnt5, cnt5s: ongetekend (4 tot 0); seinfout: STD_LOGIC; ----------------------------------- vir die toevoeging van sinusgolwe ----------- --------------- sein Wave0, Wave1, Wave2, Wave3: onderteken (9 tot 0); -seine van Wave Generator-module se uitsetsein WaveSum: STD_LOGIC_VECTOR (9 tot 0); -sein vir opgesomde sinusgolwe (2 se kompliment -512 tot 511) sein positiefWaveSum: STD_LOGIC_VECTOR (9 tot 0); -ondertekend 0 tot 1023, vir gebruik in PWM-generator ----------------------------------- vir die opwekking van PWM ------------------------------- sein ping_length: unsigned (9 downto 0): = unsigned (positiveWaveSum); -signaal af_lengte: ongetekend (6 afwaarts tot 0): = aan_onderteken (127, 7) -ongeteken (WAVE); sein PWM: ongetekend (9 afwaarts tot 0): = tot_onderteken (0, 10); begin Note_C4: Wave_Generator -poortkaart (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, onderteken (WaveOut) => WaveC4); --5973, 261,63 Hz Note_Cs4: Wave_Generator-poortkaart (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, ondertekend (WaveOut) => WaveCs4);-5638, 277,18 Hz Nota_D4: Wave_Generator -poortkaart (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, onderteken (WaveOut) => WaveD4); --5321, 293,66 Hz Nota_Ds4: Wave_Generator-poortkaart (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, ondertekend (WaveOut) => WaveDs4);-5023, 311,13 Hz Nota_E4: Wave_Generator -poortkaart (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, onderteken (WaveOut) => WaveE4); --4741, 329,63 Hz Nota_F4: Wave_Generator-poortkaart (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, geteken (WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Wave_Generator-poortkaart (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, ondertekend (WaveOut) => WaveFs4);-4224, 369,99 Hz Note_G4: Wave_Generator -poortkaart (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, onderteken (WaveOut) => WaveG4); --3986, 392,00 Hz Note_Gs4: Wave_Generator-poortkaart (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, ondertekend (WaveOut) => WaveGs4);-3763, 415,30 Hz Nota_A4: Wave_Generator -poortkaart (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, onderteken (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Wave_Generator-poortkaart (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, ondertekend (WaveOut) => WaveAs4);-3352, 466,16 Hz Nota_B4: Wave_Generator -poortkaart (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, onderteken (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Nota_C5: Wave_Generator-poortkaart (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, geteken (WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Wave_Generator-poortkaart (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, ondertekend (WaveOut) => WaveCs5);-2819, 554,37 Hz Nota_D5: Wave_Generator -poortkaart (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, onderteken (WaveOut) => WaveD5); --2661, 587,33 Hz Nota_Ds5: Wave_Generator-poortkaart (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, ondertekend (WaveOut) => WaveDs5);-2512, 622,25 Hz Nota_E5: Wave_Generator -poortkaart (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, onderteken (WaveOut) => WaveE5); --2371, 659,25 Hz Nota_F5: Wave_Generator-poortkaart (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, geteken (WaveOut) => WaveF5); --2238, 698,46 Hz Note_Fs5: Wave_Generator-poortkaart (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, ondertekend (WaveOut) => WaveFs5);-2112, 739,99 Hz Note_G5: Wave_Generator -poortkaart (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, onderteken (WaveOut) => WaveG5); --1994, 783,99 Hz Nota_Gs5: Wave_Generator-poortkaart (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, ondertekend (WaveOut) => WaveGs5);-1882, 830,61 Hz Nota_A5: Wave_Generator -poortkaart (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, onderteken (WaveOut) => WaveA5); --1776, 880,00 Hz Note_As5: Wave_Generator-poortkaart (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, ondertekend (WaveOut) => WaveAs5);-1676, 932,33 Hz Nota_B5: Wave_Generator -poortkaart (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, onderteken (WaveOut) => WaveB5); --1582, 987,77 Hz Nota_C6: Wave_Generator-poortkaart (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, onderteken (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ let op seleksie logika ------------ 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; Keuring: proses (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) begin as (cntC6 = "00000") dan --------------- as geen seine gegenereer word nie Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; anders as (O4 (0) = '1') dan ------------------- noot C4 gespeel Wave0 Wave0 Wave1 fout Wave0 Wave1 Wave2 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave0 Wave1 Wave2 Wave1 Wave2 Wave1 Wave Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave3 fout Wave0 Wave1 Wave2 Wave0 Wave1 Wave1 W2 Wave1 Wave2 Wave = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 -fout Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 fout <= '1'; eindsaak; eindig as; eindig as; einde proses; ------------- sinusgolfadder -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- maak sinusgolf positief vir pwm --------------------- positiveWaveSum <= nie WaveSum (9) & WaveSum (8 tot 0); ------------- PWM kragopwekker --------------------- proses (CLK)-veranderlike telling: ongetekend (1 tot 0): = aan_onderteken (0, 2); begin as (rising_edge (CLK)) dan --count: = count + 1; -if (count = to_unsigned (4, 2)) then --count: = to_unsigned (0, 2); --if (PWM = tot_ if (PWM <ping_length) dan output <= '1'; anders output <= '0'; end if; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end as; einde as; einde proses; beëindig Gedrag;

4 Notaskieser Die moeilikste deel van hierdie projek is om slegs vier frekwensies te kies. Ons het dit met baie IF -stellings gedoen, en ons het seine in plaas van veranderlikes gebruik, sodat die proses gesimuleer en ontfout kan word. Ons het ander metodes probeer met behulp van veranderlikes en FOR-lusse, maar het hardloop-foute teëgekom. Uiteindelik het ons besluit dat as dit werk, ons dit met rus sal laat. Maak nie reg wat nie 'n gebreekte amiriet is nie?

Die vier uitsetgolwe het die naam Wave0, Wave1, Wave2, Wave3 - dit is wat bymekaar gevoeg sal word om die finale uitset te vorm.

As u na die kode kyk, sien u 'n klomp seine met die naam C4, Cs4, D4, Ds4, ens. Dit is 5-bis seine wat die ooreenstemmende sneller van O4 (oktaaf 4) of O5 (oktaaf 5) neem en dit maak 5-bis vir byvoeging.

Vervolgens verteenwoordig die veranderlikes cntC4, cntCs4, ens, hoeveel note laer as die doelnoot gespeel is, insluitend die teiken noot. As C4, E4, G4, A#4 en D5 byvoorbeeld gespeel word (C9 -akkoord) sal cntC4 1 wees, cntE4 2, cntG4 3, ens.

Elke keer as 'n noot gespeel word, word die telling vir die doelnoot ondersoek om te sien waarheen u die nootsein moet koppel. Byvoorbeeld, as D5 noot gespeel word (wat beteken dat O5 (2) hoog is) en cntD5 3 is, word daar tans 3 note gespeel, met 2 note laer as D5, so ons sal golf D5 aan Wave2 (die derde golf) koppel seintelling vanaf Wave0). As alternatief, as cntD5 5 is, word daar tans 5 note gespeel, met 4 note laer as D5, sodat ons waveD5 net laat hang en niks daarmee doen nie.

Die IF -stellings word dan herhaal om die gevalle vir al 25 aantekeninge te dek.

Amplitude -opteller

Nadat die laagste 4 golwe gekies is, moet ons dit byvoeg. Die rede waarom ons net vier note bymekaar sal voeg, is omdat die PWM -idee wat ons vir ons uitset gebruik, slegs 'n sekere resolusie kan hê totdat die PWM te stadig loop en die luidspreker die PWM -vierkantgolf sal begin optel. As ons byvoorbeeld 'n resolusie van 8192 (13 bit) gebruik, moet elkeen van die 8192 punte ooreenstem met 'n stygende rand van die ingeboude klok. Dus, 100MHz / 8192 = 12,2kHz, wat goed binne die bereik van menslike gehoor is.

Die werklike byvoeging van die amplitudes is super eenvoudig; u moet net seker maak dat dit baie vinnig kan werk.

PWM -uitset

Die PWM se dienssiklus verteenwoordig die amplitude van ons uitsetgolf op daardie oomblik. Byvoorbeeld, as ons 'n amplitude bereik van 0 tot 128 het, sal 0 'n 0%dienssiklus wees, 64 50%, 128 100%, ens. Hierdie PWM sal baie vinnig werk (ons s'n is 97,6 kHz), so vinnig dat die spreker nie die individuele vierkantgolwe sal herken nie, maar eerder na die gemiddelde spanning kyk en ons 'analoog' sein skep.

Beperkingslêer

Miskien het u u hardeware anders aangeskakel, dus maak seker dat die beperkingslêer ooreenstem.

Stap 5: Kode -aflaai

Hieronder is die kode, beide in.txt -formaat en.vhd vir Vivado. Wave_Generator is die submodule van die golfgenerator, en Two_Octave_Synth is die boonste module met al die ander.

Aanbeveel: