Innholdsfortegnelse:

Basys3 FPGA Digital Audio Synthesizer: 5 trinn
Basys3 FPGA Digital Audio Synthesizer: 5 trinn

Video: Basys3 FPGA Digital Audio Synthesizer: 5 trinn

Video: Basys3 FPGA Digital Audio Synthesizer: 5 trinn
Video: Digital Audio Delay on an FPGA. 2024, November
Anonim
Image
Image
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer
Basys3 FPGA Digital Audio Synthesizer

Denne digitale sinusbølge -tastaturet synthesizer vil ta brukerinnganger via en serie øyeblikksbrytere lagt ut som et tastatur og sende ut en lydbølge gjennom en høyttaler. Basert på brukerinnganger vil enheten generere sinusbølger med forskjellige frekvenser fra C4 til C6. Brukeren kan legge inn notater fra C4 til C6 (25 noter totalt) og opptil fire taster samtidig - hvis du trykker på mer enn fire taster, spilles de fire laveste tonene.

Dette prosjektet ble utført av Ryan Morris og Mavis Tsoi for vår Cal Poly CPE 133 Digital Design -klasse:)

Trinn 1: Teori

Et FPGA -kort kan bare sende ut digitale signaler. Med andre ord kan den bare produsere en høy (3,3V) spenning eller en lav (0V) spenning. Lydsignaler er imidlertid analoge og kan ha uendelig mange trinn i spenning. For å komme rundt dette, vil vi bruke et PWM -signal (pulsbreddemodulering) for å etterligne en analog bølge. Hvis du ikke vet hva PWM er, sjekk dette ut:

Trinn 2: Ingredienser og verktøy

  • Datamaskin med Vivado installert
  • Vi bruker Vivado versjon 2017.2
  • Basys3 FPGA Board
  • 25 SPDT -grensebrytere (vi brukte disse)
  • 30 hoppetråder (den ene enden, den andre enden spiller ingen rolle), 12 tommer
  • Avbitertang
  • Wire strippere
  • Reservetråd for lodding
  • Harpiks-kjerne loddetinn
  • Loddejern
  • ¼”kvinnelig lydkontakt
  • Forsterker/høyttaler
  • Noe å montere bryterne på (vi brukte protoboard + trekasse)

Trinn 3: Kabling og maskinvareoppsett

Kabling og maskinvareoppsett
Kabling og maskinvareoppsett
Kabling og maskinvareoppsett
Kabling og maskinvareoppsett
Kabling og maskinvareoppsett
Kabling og maskinvareoppsett

system arkitektur

Se Figur 1: 25 tilgjengelige innganger → Basys3 Board → forsterker og høyttaler.

Produksjon

Se figur 2: Basys3 -kort → 1/2 kvinnelig lydkontakt → høyttaler (med forsterker)

Inngang

PMOD -tilkoblingene på Basys3 -kortet må være koblet til bakken for å se en lav inngang og vil ikke fungere skikkelig hvis den blir igjen som en åpen krets. På grunn av dette må vi bruke SPDT -brytere for alle notatnøklene våre. En SPDT -bryter lar i utgangspunktet brukeren bytte mellom kretser når den trykkes, så vi vil bruke dem som våre "knapper" for å legge inn lave (0V) eller høye (3.3V) signaler til Basys3 -kortet.

Hver bryter vil ha NO (normalt åpnet) terminal koblet til 3.3V, NC (normalt lukket) terminal koblet til GND, og COM (vanlig) terminal koblet til FPGA -inngang. Se figur 3.

Fordi vi har 25 grensebrytere, vil de alle dele en felles 3.3V -linje og en felles GND -linje. Deretter vil signallinjen fra hver grensebryter settes sammen i grupper på 8 og kobles til pmod -tilkoblingene på Basys3 -kortet ved hjelp av glidelåsstrikk for å minimere det monumentale rotet vi lager. Se figur 4 eller et eksempel på de første åtte tastene.

Trinn 4: VHDL -oppsett (Vivado)

VHDL -oppsett (Vivado)
VHDL -oppsett (Vivado)
VHDL -oppsett (Vivado)
VHDL -oppsett (Vivado)

Sinusbølgeneratoren og PWM -generatoren ble først testet for å sikre at konseptet vårt fungerte, deretter ble inngangsbegrenseren og amplitudeadder/-skifteren integrert. Detaljer om funksjonen og I/O for hver prosessblokk er som vist på figuren. Koden er vist nedenfor, men også vedlagt som VHD- og txt -filer. Hvis det er avvik, gå med VHD -filene.

BTW: vi burde sannsynligvis ha gjort linjene våre kortere, men kodeinnbygging på Instructables viste seg også å være ganske irriterende å håndtere, så avstanden er ikke den største, og det er ingen syntaksmarkering. Hvis du har Vivado og vil følge koden, anbefaler vi deg å bare laste ned filen.

La oss først se på Sine Wave Generator -modulen.

bibliotek IEEE; bruk IEEE. STD_LOGIC_1164. ALL; bruk IEEE. NUMERIC_STD. ALL; enhet Wave_Generator er Port (utløser: i STD_LOGIC; - Tastetrykk Freq_Cnt: i STD_LOGIC_VECTOR (15 ned til 0); - Telleverdi = 100MHz / (Merk frekvens*64 divisjoner av Sine Wave) (runde til nærmeste nummer) - omdøpt fra Freq wavegenCLK: i STD_LOGIC; - Basys3 100MHz CLK WaveOut: ut STD_LOGIC_VECTOR (9 ned til 0)); - Signert amplitude av bølgeenden Wave_Generator; arkitektur Behavioral of Wave_Generator er signal i: heltallsområde 0 til 64: = 0; -indeks for amplitude minne banktype memory_type er array (0 til 63) med heltallsområde -64 til 63; - lag minnebank (ROM) for å holde amplitudeverdier- lurer denne RAM eller ROM på … signalamplitude: 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-minnebank for sinusbølge begynner prosess (wavegenCLK, Trigger) variabel teller: usignert (15 ned til 0): = to_unsigned (0, 16); - klokke divider teller, omdøpt fra count1 begynner hvis (rising_edge (wavegenCLK)) deretter hvis (Trigger = '1') da- tasten trykkes teller: = teller + 1; hvis (teller = usignert (Freq_Cnt)) så - Freq_Cnt = 100Mhz / (merk frekv * 64 divisjoner av sinusbølgen) - tilbakestill teller og tilordne amplitude data til utgangsteller: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitude (i), 10)); - økning i for neste lesing i <= i + 1; - tilbakestill i hvis en sinusbølge er fullført hvis (i = 63) så i <= 0; slutt om; slutt om; - (teller = usignert (Freq_Cnt)) else- tasten trykkes ikke- tilbakestill utgang, amplitudeindeks og teller WaveOut <= "0000000000"; i <= 0; teller: = to_unsigned (0, 16); -Output Amplitude = -64 når ingen notater spilles, slutter hvis; - (Utløser = '1') ende hvis; - (stigende_kant (CLK)) sluttprosess; slutt Behavioral;

Vi vil generere en digital sinusbølge i Basys3 ved å bruke den interne klokken og en ROM. Denne ROM -en vil lagre 64 verdier som representerer 64 amplituder på en sinusbølge. Se figur 1. De 64 verdiene vi bruker etterligner en sinusbølge med ganske god oppløsning.

Ved å bruke den interne klokken, teller vi til en verdi som representerer klokkehastigheten dividert med frekvensen til bølgen vi vil ha og 64: Clk div = 100MHz / (Freq * 64) Hver gang telleren når den verdien, ringer vi et tall fra ROM -en og send den ut av bølgegeneratoren. Frekvensen av bølgen vår vil avhenge av hvor fort vi kaller disse amplituder.

Vi vil ha 25 delmoduler, hver knyttet til en frekvens/note.

Her er resten av koden som kaller Sine Wave Generator -modulene:

bibliotek IEEE; bruk IEEE. STD_LOGIC_1164. ALL; bruk IEEE. NUMERIC_STD. ALL; enhet Two_Octave_Synth er Port (CLK: i STD_LOGIC; O4: i STD_LOGIC_VECTOR (11 ned til 0); O5: i STD_LOGIC_VECTOR (12 ned til 0); utgang: ut STD_LOGIC); avslutte Two_Octave_Synth; arkitektur Behavioral of Two_Octave_Synth er komponent Wave_Generator er port (utløser: i STD_LOGIC; Freq_Cnt: i STD_LOGIC_VECTOR (15 ned til 0); wavegenCLK: i STD_LOGIC; WaveOut: ut STD_LOGIC_VECTOR (9 ned til 0)); sluttkomponent; --------------------------- utgangssignaler fra bølgegenerator ------------------ ----- signal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave5, Wave5, Wave5, Wave5 WaveAs5, WaveB5, WaveC6: signert (9 ned til 0); -------------------------------- for notatvalglogikk -------------- ------ 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: usignert (4 ned til 0); signal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntAs, cnt5, cnt5, cnt5, cnt5, cnt5, cnt5s: usignert (4 ned til 0); signalfeil: STD_LOGIC; ------------------------------------ for å legge til sinusbølger ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: signert (9 ned til 0); -signaler fra Wave Generator-modulens utgangssignal WaveSum: STD_LOGIC_VECTOR (9 ned til 0); -signal for oppsummerte sinusbølger (2s kompliment -512 til 511) signal positiveWaveSum: STD_LOGIC_VECTOR (9 ned til 0); --tegnet 0 til 1023, for bruk i PWM-generator ----------------------------------- for generering av PWM ------------------------------- signal ping_length: unsigned (9 downto 0): = unsigned (positiveWaveSum); --signal off_length: unsigned (6 downto 0): = to_unsigned (127, 7) -unsigned (WAVE); signal PWM: usignert (9 ned til 0): = to_unsigned (0, 10); begynne Note_C4: Wave_Generator -portkart (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, signert (WaveOut) => WaveC4); --5973, 261,63 Hz Note_Cs4: Wave_Generator-portkart (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, signert (WaveOut) => WaveCs4);-5638, 277,18 Hz Note_D4: Wave_Generator -portkart (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, signert (WaveOut) => WaveD4); --5321, 293,66 Hz Note_Ds4: Wave_Generator-portkart (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, signert (WaveOut) => WaveDs4);-5023, 311,13 Hz Note_E4: Wave_Generator -portkart (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, signert (WaveOut) => WaveE4); --4741, 329,63 Hz Note_F4: Wave_Generator-portkart (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, signert (WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Wave_Generator-portkart (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, signert (WaveOut) => WaveFs4);-4224, 369,99 Hz Note_G4: Wave_Generator -portkart (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, signert (WaveOut) => WaveG4); --3986, 392,00 Hz Note_Gs4: Wave_Generator-portkart (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, signert (WaveOut) => WaveGs4);-3763, 415,30 Hz Note_A4: Wave_Generator -portkart (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, signert (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Wave_Generator-portkart (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, signert (WaveOut) => WaveAs4);-3352, 466,16 Hz Note_B4: Wave_Generator -portkart (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, signert (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Wave_Generator-portkart (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, signert (WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Wave_Generator-portkart (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, signert (WaveOut) => WaveCs5);-2819, 554,37 Hz Note_D5: Wave_Generator -portkart (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, signert (WaveOut) => WaveD5); --2661, 587,33 Hz Note_Ds5: Wave_Generator-portkart (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, signert (WaveOut) => WaveDs5);-2512, 622,25 Hz Note_E5: Wave_Generator -portkart (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, signert (WaveOut) => WaveE5); --2371, 659,25 Hz Note_F5: Wave_Generator-portkart (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, signert (WaveOut) => WaveF5); --2238, 698,46 Hz Note_Fs5: Wave_Generator-portkart (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, signert (WaveOut) => WaveFs5);-2112, 739,99 Hz Note_G5: Wave_Generator -portkart (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, signert (WaveOut) => WaveG5); --1994, 783,99 Hz Note_Gs5: Wave_Generator-portkart (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, signert (WaveOut) => WaveGs5);-1882, 830,61 Hz Note_A5: Wave_Generator -portkart (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, signert (WaveOut) => WaveA5); --1776, 880,00 Hz Note_As5: Wave_Generator-portkart (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, signert (WaveOut) => WaveAs5);-1676, 932,33 Hz Note_B5: Wave_Generator -portkart (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, signert (WaveOut) => WaveB5); --1582, 987,77 Hz Note_C6: Wave_Generator-portkart (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, signert (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ notatvalglogikk ------------ 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; Utvalg: prosess (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) begynner hvis (cntC6 = "00000") deretter --------------- hvis ingen signaler blir generert Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; ellers hvis (O4 (0) = '1') så ------------------- note C4 spilt Wave0 Wave0 Wave1 feil Wave0 Wave1 Wave2 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave0 Wave1 Wave2 Wave3 feil Wave2 Wave1 Wave2 Wave1 Wave2 Wave Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave1 Wave2 Wave0 Wave1 Wave2 Wave3 feil Wave0 Wave2 Wave1 Wave2 Wave = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 feil Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 feil <= '1'; slutt saken; slutt om; slutt om; avslutte prosessen; ------------- sinusbølgeadder -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- gjør sinusbølge positiv for pwm --------------------- positiveWaveSum <= ikke WaveSum (9) & WaveSum (8 ned til 0); ------------- PWM generator --------------------- prosess (CLK)-variabelt antall: usignert (1 ned til 0): = to_unsigned (0, 2); begynne hvis (stigende_kant (CLK)) deretter --count: = count + 1; --if (count = to_unsigned (4, 2)) deretter --count: = to_unsigned (0, 2); --if (PWM = to_ if (PWM <ping_length) deretter output <= '1'; ellers output <= '0'; slutt hvis; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end hvis; ende hvis; avslutte prosess; avslutte Behavioral;

4 Note Selector Den vanskeligste delen av dette prosjektet er å velge bare fire frekvenser. Vi gjorde det med en hel del IF -setninger, og vi brukte signaler i stedet for variabler slik at prosessen kan simuleres og feilsøkes. Vi prøvde andre metoder ved å bruke variabler og FOR-løkker, men løp inn i kjøretidsfeil. Så til slutt bestemte vi oss for at hvis det fungerer, lar vi det være i fred. Ikke fikser det som ikke er ødelagt amiritt?

De fire utgangsbølgene er merket Wave0, Wave1, Wave2, Wave3 - dette er det som vil bli lagt sammen for å danne den endelige utgangen.

Når du ser på koden, ser du en haug med signaler merket C4, Cs4, D4, Ds4, etc. Dette er 5-bits signaler som tar den tilsvarende utløseren fra O4 (oktav 4) eller O5 (oktav 5) og lager dem 5-bit for å legge til.

Deretter representerer cntC4, cntCs4, osv. Variablene hvor mange noter lavere enn målnoten som er spilt, inkludert målnoten. For eksempel, hvis C4, E4, G4, A#4 og D5 spilles (C9 -akkord) vil cntC4 være 1, cntE4 vil være 2, cntG4 være 3, etc.

Når en notat spilles, vil tellingen for målnoten bli undersøkt for å se hvor du skal koble notatsignalet til. For eksempel, hvis D5 -notat spilles (som betyr at O5 (2) er høyt) og cntD5 er 3, blir det for øyeblikket spilt 3 notater, med 2 toner lavere enn D5, så vi vil koble waveD5 til Wave2 (den tredje bølgen signal teller fra Wave0). Alternativt, hvis cntD5 er 5, spilles det for øyeblikket 5 notater, med 4 noter lavere enn D5, så vi lar bare waveD5 henge og ikke gjøre noe med det.

IF -uttalelsene gjentas deretter for å dekke sakene for alle 25 notatene.

Amplitude Adder

Etter at de laveste 4 bølgene er valgt, må vi legge dem sammen. Grunnen til at vi bare legger til fire notater sammen er fordi PWM -ideen vi bruker for utgangen vår, bare kan ha en viss oppløsning til PWM går for sakte og høyttaleren begynner å plukke opp PWM -firkantbølgen. For eksempel, hvis vi skulle bruke en oppløsning på 8192 (13 bit), må hvert av disse 8192 punktene tilsvare en stigende kant på den innebygde klokken. Så, 100MHz / 8192 = 12,2kHz, som er godt innenfor rekkevidden av menneskelig hørsel.

Selve tillegget av amplituder er superenkelt, du må bare sørge for at den kan kjøre veldig fort.

PWM -utgang

PWMs driftssyklus vil representere amplituden til utgangsbølgen vår i det øyeblikket. For eksempel, hvis vi har et amplitudeområde på 0 til 128, vil 0 være en 0%driftssyklus, 64 ville være 50%, 128 ville være 100%, etc. Denne PWM vil kjøre ekstremt fort (vår er 97,6 kHz), så raskt at høyttaleren ikke vil gjenkjenne de enkelte firkantbølgene og i stedet se på gjennomsnittsspenningen og skape vårt "analoge" signal.

Begrensningsfil

Du kan ha koblet maskinvaren annerledes, så bare pass på at begrensningsfilen stemmer overens.

Trinn 5: Nedlasting av kode

Nedenfor er koden, både i.txt -format og.vhd for Vivado. Wave_Generator er bølgegeneratorundermodulen, og Two_Octave_Synth er toppmodulen med alt annet.

Anbefalt: