Indholdsfortegnelse:

Basys3 FPGA Digital Audio Synthesizer: 5 trin
Basys3 FPGA Digital Audio Synthesizer: 5 trin

Video: Basys3 FPGA Digital Audio Synthesizer: 5 trin

Video: Basys3 FPGA Digital Audio Synthesizer: 5 trin
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 -tastatur -synthesizer tager brugerindgange via en række øjeblikkelige kontakter, der er lagt ud som et tastatur og udsender en lydbølge gennem en højttaler. Baseret på brugerinput vil enheden generere sinusbølger med forskellige frekvenser fra C4 til C6. Brugeren kan indtaste noter fra C4 op til C6 (25 noter i alt) og op til fire taster på samme tid - hvis der trykkes på mere end fire taster, afspilles de fire laveste toner.

Dette projekt blev udført af Ryan Morris og Mavis Tsoi til vores Cal Poly CPE 133 Digital Design -klasse:)

Trin 1: Teori

Et FPGA -kort kan kun udsende digitale signaler. Med andre ord kan den kun producere en høj (3,3V) spænding eller en lav (0V) spænding. Lydsignaler er imidlertid analoge og kan have uendeligt mange trin i spænding. For at komme uden om dette vil vi bruge et PWM (pulsbreddemodulation) signal til at efterligne en analog bølge. Hvis du ikke ved, hvad PWM er, skal du tjekke dette:

Trin 2: Ingredienser og værktøjer

  • Computer med Vivado installeret
  • Vi bruger Vivado version 2017.2
  • Basys3 FPGA Board
  • 25 SPDT Limit Switches (vi brugte disse)
  • 30 springtråde (den ene ende han, den anden ende er ligegyldig), 12 tommer
  • Trådskærere
  • Wire strippere
  • Reservetråd til lodning
  • Harpiks-kernelodning
  • Loddekolbe
  • ¼”kvindelig lydstik
  • Forstærker/højttaler
  • Noget at montere kontakterne på (vi brugte protoboard + trækasse)

Trin 3: Kabelføring og hardwareopsætning

Kabelføring og hardwareopsætning
Kabelføring og hardwareopsætning
Kabelføring og hardwareopsætning
Kabelføring og hardwareopsætning
Kabelføring og hardwareopsætning
Kabelføring og hardwareopsætning

Systemarkitektur

Se figur 1: 25 tilgængelige input → Basys3 Board → forstærker og højttaler.

Produktion

Se figur 2: Basys3 -kort → 1/2 kvindelig lydstik → Højttaler (med forstærker)

Input

PMOD -forbindelserne på Basys3 -kortet skal forbindes til jorden for at se et lavt input og fungerer ikke korrekt, hvis de efterlades som et åbent kredsløb. På grund af dette er vi nødt til at bruge SPDT -switche til alle vores notataster. En SPDT -switch giver i princippet brugeren mulighed for at skifte mellem kredsløb, når der trykkes på, så vi vil bruge dem som vores "knapper" til at indtaste lave (0V) eller høje (3.3V) signaler til Basys3 -kortet.

Hver switch har NO (normalt åbnet) terminal forbundet til 3.3V, NC (normalt lukket) terminal forbundet til GND og COM (common) terminal forbundet til FPGA input. Se figur 3.

Fordi vi har 25 endestopkontakter, vil de alle dele en fælles 3.3V -linje og en fælles GND -linje. Derefter vil signallinjen fra hver grænseafbryder blive samlet i grupper på 8 og tilsluttet pmod -forbindelserne på Basys3 -kortet ved hjælp af lynlåsbare jumperwires for at minimere det monumentale rod, vi laver. Se figur 4 eller et eksempel på de første otte taster.

Trin 4: VHDL -opsætning (Vivado)

VHDL -opsætning (Vivado)
VHDL -opsætning (Vivado)
VHDL -opsætning (Vivado)
VHDL -opsætning (Vivado)

Sinusbølgegeneratoren og PWM -generatoren blev først testet for at sikre, at vores koncept fungerede, derefter blev inputbegrænseren og amplitudeadder/shifter integreret. Detaljer om funktionen og I/O for hver procesblok er som vist i figuren. Koden er vist herunder, men også vedhæftet som VHD- og txt -filer. Hvis der er uoverensstemmelser, skal du gå med VHD -filerne.

BTW: vi skulle nok have gjort vores linjer kortere, men kodeindlejring i Instructables viste sig også at være ret irriterende at håndtere, så afstanden er ikke den største, og der er ingen syntaksfremhævelse. Hvis du har Vivado og gerne vil følge koden, anbefaler vi stærkt, at du bare downloader filen.

Lad os først se på modulet Sine Wave Generator.

bibliotek IEEE; brug IEEE. STD_LOGIC_1164. ALL; brug IEEE. NUMERIC_STD. ALL; enhed Wave_Generator er Port (Trigger: i STD_LOGIC; - Tastetryk Freq_Cnt: i STD_LOGIC_VECTOR (15 ned til 0); - Tællerværdi = 100MHz / (Bemærk frekvens*64 divisioner af sinusbølge) (runde til nærmeste nummer) - omdøbt fra Freq wavegenCLK: i STD_LOGIC; - Basys3 100MHz CLK WaveOut: ud STD_LOGIC_VECTOR (9 ned til 0)); - Signeret amplitude af bølgeenden Wave_Generator; arkitektur Adfærdsmæssig af Wave_Generator er signal i: heltalsområde 0 til 64: = 0; -indeks over amplitudehukommelse banktype memory_type er array (0 til 63) med heltalsinterval -64 til 63; - opret hukommelsesbank (ROM) for at holde amplitudeværdier- undrer denne RAM eller ROM sig bare … 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 hukommelsesbank for sinusbølge begynder proces (wavegenCLK, Trigger) variabel tæller: usigneret (15 ned til 0): = to_unsigned (0, 16); - clock divider counter, omdøbt fra count1 begynder hvis (rising_edge (wavegenCLK)) derefter hvis (Trigger = '1') derefter- tasten trykkes på counter: = counter + 1; hvis (tæller = usigneret (Freq_Cnt)) derefter - Freq_Cnt = 100Mhz / (note freq * 64 divisioner af sinusbølgen) - nulstil tæller og tildel amplitudedata til udgangstæller: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitude (i), 10)); - øg i til næste læsning i <= i + 1; - nulstil i, hvis en sinusbølge er fuldført, hvis (i = 63) derefter i <= 0; Afslut Hvis; Afslut Hvis; - (tæller = usigneret (Freq_Cnt)) else- tasten trykkes ikke- nulstil output, amplitudeindeks og tæller WaveOut <= "0000000000"; i <= 0; tæller: = to_unsigned (0, 16); --output Amplitude = -64 når ingen note spilles slutter hvis; - (Trigger = '1') ende hvis; - (stigende_kant (CLK)) slutproces; ende Adfærdsmæssig;

Vi genererer en digital sinusbølge i Basys3 ved hjælp af det interne ur og en ROM. Denne ROM gemmer 64 værdier, der repræsenterer 64 amplituder på en sinusbølge. Se figur 1. De 64 værdier, vi bruger, efterligner en sinusbølge med temmelig god opløsning.

Ved hjælp af det interne ur tæller vi til en værdi, der repræsenterer urets hastighed divideret med frekvensen af den bølge, vi ønsker, og 64: Clk div = 100MHz / (Freq * 64) Hver gang vores tæller når denne værdi, kalder vi et tal fra ROM'en og send den ud af vores bølgegeneratormodul. Frekvensen af vores bølge afhænger af, hvor hurtigt vi kalder disse amplituder.

Vi vil have 25 delmoduler, der hver er forbundet med en frekvens/note.

Her er resten af koden, der kalder Sine Wave Generator -modulerne:

bibliotek IEEE; brug IEEE. STD_LOGIC_1164. ALL; brug IEEE. NUMERIC_STD. ALL; enhed 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); output: ud STD_LOGIC); afslut Two_Octave_Synth; arkitektur Behavioral of Two_Octave_Synth er komponent Wave_Generator er Port (Trigger: i STD_LOGIC; Freq_Cnt: i STD_LOGIC_VECTOR (15 ned til 0); wavegenCLK: i STD_LOGIC; WaveOut: ud STD_LOGIC_VECTOR (9 ned til 0)); slutkomponent; --------------------------- udgangssignaler fra bølge generator ------------------ ----- signal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave5, Wave5, Wave5, Wave5 WaveAs5, WaveB5, WaveC6: signeret (9 ned til 0); -------------------------------- for notevalgslogik -------------- ------ 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: usigneret (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, cnt5, cnt5s: usigneret (4 ned til 0); signalfejl: STD_LOGIC; ----------------------------------- til tilføjelse af sinusbølger ----------- --------------- signal Wave0, Wave1, Wave2, Wave3: signeret (9 ned til 0); -signaler fra Wave Generator-modulets udgangssignal WaveSum: STD_LOGIC_VECTOR (9 ned til 0); -signal for opsummerede sinusbølger (2's kompliment -512 til 511) signalerer positiveWaveSum: STD_LOGIC_VECTOR (9 ned til 0); --tegnet 0 til 1023, til brug i PWM-generator ----------------------------------- til generering af 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: usigneret (9 ned til 0): = to_unsigned (0, 10); begynde Note_C4: Wave_Generator portkort (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, signeret (WaveOut) => WaveC4); --5973, 261,63 Hz Note_Cs4: Wave_Generator portkort (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, signeret (WaveOut) => WaveCs4);-5638, 277,18 Hz Note_D4: Wave_Generator portkort (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, signeret (WaveOut) => WaveD4); --5321, 293,66 Hz Note_Ds4: Wave_Generator portkort (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, signeret (WaveOut) => WaveDs4);-5023, 311,13 Hz Note_E4: Wave_Generator portkort (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, signeret (WaveOut) => WaveE4); --4741, 329,63 Hz Note_F4: Wave_Generator portkort (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, signeret (WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Wave_Generator portkort (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, signeret (WaveOut) => WaveFs4);-4224, 369,99 Hz Note_G4: Wave_Generator portkort (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, signeret (WaveOut) => WaveG4); --3986, 392,00 Hz Note_Gs4: Wave_Generator portkort (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, signeret (WaveOut) => WaveGs4);-3763, 415,30 Hz Note_A4: Wave_Generator portkort (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, signeret (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Wave_Generator portkort (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, signeret (WaveOut) => WaveAs4);-3352, 466,16 Hz Note_B4: Wave_Generator portkort (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, signeret (WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- ---------------------------------------------------------- --------------------------- Note_C5: Wave_Generator portkort (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, signeret (WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Wave_Generator portkort (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, signeret (WaveOut) => WaveCs5);-2819, 554,37 Hz Note_D5: Wave_Generator portkort (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, signeret (WaveOut) => WaveD5); --2661, 587,33 Hz Note_Ds5: Wave_Generator portkort (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, signeret (WaveOut) => WaveDs5);-2512, 622,25 Hz Note_E5: Wave_Generator portkort (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, signeret (WaveOut) => WaveE5); --2371, 659,25 Hz Note_F5: Wave_Generator portkort (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, signeret (WaveOut) => WaveF5); --2238, 698,46 Hz Note_Fs5: Wave_Generator portkort (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, signeret (WaveOut) => WaveFs5);-2112, 739,99 Hz Note_G5: Wave_Generator portkort (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, signeret (WaveOut) => WaveG5); --1994, 783,99 Hz Note_Gs5: Wave_Generator portkort (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, signeret (WaveOut) => WaveGs5);-1882, 830,61 Hz Note_A5: Wave_Generator portkort (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, signeret (WaveOut) => WaveA5); --1776, 880,00 Hz Note_As5: Wave_Generator portkort (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, signeret (WaveOut) => WaveAs5);-1676, 932,33 Hz Note_B5: Wave_Generator portkort (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, signeret (WaveOut) => WaveB5); --1582, 987,77 Hz Note_C6: Wave_Generator portkort (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, signeret (WaveOut) => WaveC6); --1494, 1046,5 Hz ------------ noteringsvalglogik ------------ 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; Valg: proces (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) begynder hvis (cntC6 = "00000") derefter --------------- hvis der ikke genereres signaler Wave0 <= "0000000000"; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 <= "0000000000"; ellers hvis (O4 (0) = '1') så ------------------- note C4 spillede Wave0 Wave0 Wave1 fejl Wave0 Wave1 Wave2 fejl Wave0 Wave1 Wave2 Wave3 fejl Wave0 Wave1 Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Wave1 Wave2 Wave3 fejl Wave0 Wave1 Wave2 Wave0 Wave1 Wave2 Wave3 fejl Wave0 Wave2 Wave2 Wave2 Wave1 Wave Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Bølge1 Bølge2 Bølge3 fejl Bølge0 Wave1 Wave2 Wave3 fejl Wave0 Wave1 Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 fejl Wave0 Wave2 Wave2 Wave2 Wave2 = WaveC6; Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Wave2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 fejl Wave1 <= "0000000000"; Wave2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 fejl <= '1'; slut sag; Afslut Hvis; Afslut Hvis; afslutte processen; ------------- sinusbølge adder -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- gør sinusbølge positiv for pwm --------------------- positiveWaveSum <= ikke WaveSum (9) & WaveSum (8 ned til 0); ------------- PWM generator --------------------- proces (CLK)-varierende antal: usigneret (1 ned til 0): = to_unsigned (0, 2); begynde hvis (stigende_kant (CLK)) derefter --count: = count + 1; --if (count = to_unsigned (4, 2)) derefter --count: = to_unsigned (0, 2); --if (PWM = to_ if (PWM <ping_length) derefter output <= '1'; ellers output <= '0'; ende hvis; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end hvis; slut hvis; afslut proces; afslut Adfærdsmæssig;

4 Note Selector Den vanskeligste del af dette projekt er kun at vælge fire frekvenser. Vi gjorde det med en hel del IF -sætninger, og vi brugte signaler i stedet for variabler, så processen kan simuleres og fejlsøges. Vi prøvede andre metoder ved hjælp af variabler og FOR loops, men løb ind i fejl i løbetid. Så i sidste ende besluttede vi, at hvis det virker, lader vi det være i fred. Løs ikke hvad der ikke er brudt amirit?

De fire outputbølger er mærket Wave0, Wave1, Wave2, Wave3 - det er det, der vil blive tilføjet sammen for at danne det endelige output.

Når man ser på koden, ser man en flok signaler mærket C4, Cs4, D4, Ds4 osv. Disse er 5-bit signaler, der tager den tilsvarende trigger fra O4 (oktav 4) eller O5 (oktav 5) og laver dem 5-bit til tilføjelse.

Dernæst repræsenterer cntC4, cntCs4, osv. Variablerne, hvor mange toner der er lavere end målnoten, inklusive 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 osv.

Når der derefter spilles en note, vil tællingen for målnoten blive undersøgt for at se, hvor note -signalet skal tilsluttes. For eksempel, hvis D5 -note spilles (hvilket betyder, at O5 (2) er høj) og cntD5 er 3, så spilles der i øjeblikket 3 toner, med 2 toner lavere end D5, så vi vil koble bølgeD5 til Wave2 (den tredje bølge signaltælling fra Wave0). Alternativt, hvis cntD5 er 5, så spilles der i øjeblikket 5 noter med 4 toner lavere end D5, så vi vil bare lade waveD5 hænge og ikke gøre noget med det.

IF -udsagnene gentages derefter for at dække sagerne for alle 25 sedler.

Amplitude Adder

Efter at de laveste 4 bølger er valgt, skal vi tilføje dem sammen. Grunden til, at vi kun tilføjer fire noter sammen, er fordi den PWM -idé, vi bruger til vores output, kun kan have en bestemt opløsning, indtil PWM kører for langsomt, og højttaleren begynder at opfange PWM -firkantbølgen. For eksempel, hvis vi skulle bruge en opløsning på 8192 (13 bit), skal hvert af disse 8192 punkter svare til en stigende kant på det indbyggede ur. Så 100MHz / 8192 = 12,2kHz, hvilket er godt inden for området for menneskelig hørelse.

Selve tilføjelsen af amplituderne er superenkel, du skal bare sørge for, at den kan køre rigtig hurtigt.

PWM -output

PWM's arbejdscyklus repræsenterer amplituden af vores outputbølge i det øjeblik. For eksempel, hvis vi har et amplitudeområde på 0 til 128, ville 0 være en 0%driftscyklus, 64 ville være 50%, 128 ville være 100%osv. Denne PWM kører ekstremt hurtigt (vores er 97,6 kHz), så hurtigt, at højttaleren ikke genkender de enkelte firkantbølger og i stedet ser på den gennemsnitlige spænding og skaber vores "analoge" signal.

Begrænsningsfil

Du har muligvis tilsluttet din hardware anderledes, så bare sørg for, at begrænsningsfilen matcher.

Trin 5: Kodeoverførsler

Nedenfor er koden, både i.txt -format og.vhd til Vivado. Wave_Generator er bølgegeneratorundermodulet, og Two_Octave_Synth er det øverste modul med alt andet.

Anbefalede: