Mündəricat:

Basys3 FPGA Rəqəmsal Səs Sintezatoru: 5 addım
Basys3 FPGA Rəqəmsal Səs Sintezatoru: 5 addım

Video: Basys3 FPGA Rəqəmsal Səs Sintezatoru: 5 addım

Video: Basys3 FPGA Rəqəmsal Səs Sintezatoru: 5 addım
Video: Knight Rider Theme Effect by an FPGA Basys3 board 2024, Iyul
Anonim
Image
Image
Basys3 FPGA Rəqəmsal Səs Sintezatoru
Basys3 FPGA Rəqəmsal Səs Sintezatoru
Basys3 FPGA Rəqəmsal Səs Sintezatoru
Basys3 FPGA Rəqəmsal Səs Sintezatoru

Bu rəqəmsal sinus dalğa klaviatura sintezatoru, istifadəçi girişlərini klaviatura kimi qurulmuş bir sıra keçidlər vasitəsilə alacaq və dinamikdən səs dalğası çıxaracaq. İstifadəçi girişlərinə əsaslanaraq, cihaz C4 -dən C6 -a qədər müxtəlif tezliklərdə sinus dalğaları yaradacaq. İstifadəçi C4 -dən C6 -a qədər (cəmi 25 not) və eyni zamanda ən çox dörd düyməni qeyd edə bilər - dörddən çox düyməyə basıldığı təqdirdə ən aşağı dörd ton çalınacaq.

Bu layihə Cal Poly CPE 133 Digital Design sinifimiz üçün Ryan Morris və Mavis Tsoi tərəfindən edildi:)

Addım 1: nəzəriyyə

Bir FPGA lövhəsi yalnız rəqəmsal siqnalları çıxara bilər. Başqa sözlə, yalnız yüksək (3.3V) və ya aşağı (0V) gərginlik yarada bilər. Bununla birlikdə, səs siqnalları analoqdur və gərginlikdə sonsuz çox artım ola bilər. Bunun qarşısını almaq üçün analog dalğanı təqlid etmək üçün PWM (nəbz genişliyi modulyasiyası) siqnalından istifadə edəcəyik. PWM-in nə olduğunu bilmirsinizsə, bunu yoxlayın:

Addım 2: Tərkibi və Alətləri

  • Vivado quraşdırılmış kompüter
  • Vivado 2017.2 versiyasını istifadə edəcəyik
  • Basys3 FPGA lövhəsi
  • 25 SPDT Limit Açarı (bunları istifadə etdik)
  • 30 tullanan tel (bir ucu kişi, digər ucu fərq etməz), 12 düym
  • Tel kəsicilər
  • Tel çıxarıcılar
  • Lehim üçün ehtiyat tel
  • Qatranlı Lehim
  • Lehimleme dəmir
  • ¼”qadın audio jakı
  • Gücləndirici/dinamik
  • Açarları bağlamaq üçün bir şey (protoboard + taxta qutudan istifadə etdik)

Addım 3: Kablolama və Avadanlıq Quraşdırması

Kablolama və Avadanlıq Quraşdırması
Kablolama və Avadanlıq Quraşdırması
Kablolama və Avadanlıq Quraşdırması
Kablolama və Avadanlıq Quraşdırması
Kablolama və Avadanlıq Quraşdırması
Kablolama və Avadanlıq Quraşdırması

Sistem Memarlığı

Şəkil 1 -ə baxın: 25 mövcud giriş → Basys3 Board → gücləndirici və dinamik.

Çıxış

Bax Şəkil 2: Basys3 Board → 1/2 Qadın Audio Jak → Dinamik (Gücləndirici ilə)

Giriş

Basys3 lövhəsindəki pmod əlaqələri aşağı girişi görmək üçün yerə bağlanmalıdır və açıq bir dövrə olaraq qalarsa düzgün işləməyəcəkdir. Bu səbəbdən bütün qeyd düymələrimiz üçün SPDT açarlarından istifadə etməliyik. Bir SPDT açarı əsasən istifadəçiyə basıldıqda dövrə arasında keçid etməyə imkan verir, buna görə də onları Basys3 lövhəsinə aşağı (0V) və ya yüksək (3.3V) siqnalları daxil etmək üçün "düymələrimiz" kimi istifadə edəcəyik.

Hər bir keçiddə 3.3V -ə qoşulmuş NO (normal açılan) terminal, GND -yə qoşulmuş NC (normal olaraq bağlanan) terminal və FPGA girişinə qoşulmuş COM (ümumi) terminal olacaq. Şəkil 3 -ə baxın.

25 limit açarımız olduğuna görə hamısı ümumi bir 3.3V xətti və ortaq bir GND xətti paylaşacaq. Daha sonra, hər bir limit keçidindən gələn siqnal xətti 8 nəfərlik qruplara yığılacaq və edəcəyimiz monumental qarışıqlığı minimuma endirmək üçün sıxışdırıla bilən keçid tellərindən istifadə edərək Basys3 lövhəsindəki pmod əlaqələrinə bağlanacaq. Şəkil 4 və ya ilk səkkiz düymənin nümunəsinə baxın.

Addım 4: VHDL Quraşdırması (Vivado)

VHDL Quraşdırması (Vivado)
VHDL Quraşdırması (Vivado)
VHDL Quraşdırması (Vivado)
VHDL Quraşdırması (Vivado)

Sinus dalğası generatoru və PWM generatoru konsepsiyamızın işlədiyinə əmin olmaq üçün əvvəlcə sınaqdan keçirildi, sonra giriş məhdudlaşdırıcısı və amplituda toplayıcı/dəyişdirici birləşdirildi. Hər bir proses blokunun funksiyası və I/O detalları Şəkildə göstərildiyi kimidir. Kod aşağıda göstərilmişdir, eyni zamanda VHD və txt faylları kimi əlavə edilmişdir. Uyğunsuzluqlar varsa, VHD faylları ilə gedin.

BTW: yəqin ki, xətlərimizi qısaltmalıydıq, lakin Instructables -da kod yerləşdirmənin də başa düşülməsi olduqca zəhlətökən olduğu ortaya çıxdı, buna görə də aralıq ən böyük deyil və sintaksisi vurğulamaq yoxdur. Vivado'ya sahibsinizsə və kodu izləmək istəsəniz, faylı yükləməyinizi şiddətlə tövsiyə edirik.

Əvvəlcə Sine Wave Generator moduluna baxaq.

kitabxana IEEE; IEEE. STD_LOGIC_1164. ALL istifadə edin; IEEE. NUMERIC_STD. ALL istifadə edin; Wave_Generator varlığı Portdur (Tetikleyici: STD_LOGIC -də; - Freq_Cnt düyməsini sıxın: STD_LOGIC_VECTOR -da (15 aşağıya doğru); - Sayaç dəyəri = 100MHz / (Qeyd Tezliyi*64 Sinus Dalğasının Bölmələri) (ən yaxın nömrəyə yuvarlaq) - dəyişdirildi Freq wavegenCLK -dən: STD_LOGIC -də; - Basys3 100MHz CLK WaveOut: STD_LOGIC_VECTOR -dan kənarda (9 aşağı 0)); - Dalğa ucunun imzalanmış amplitudası Wave_Generator; memarlıq Wave_Generatorun Davranışı i siqnaldır: 0 -dan 64 -ə qədər tam aralıq: = 0; -genlik yaddaşının bank indeksi memory_type -64 -dən 63 -ə qədər tam sıra aralığında (0 -dan 63 -ə qədər); - amplituda dəyərlərini tutmaq üçün yaddaş bankı (ROM) yaradın- bu RAM və ya ROM-u maraqlandırır … siqnal amplitudası: 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); - sinus dalğa başlanğıc prosesi üçün amplituda yaddaş bankı (wavegenCLK, Trigger) dəyişən sayğacı: işarəsiz (15 aşağı 0): = to_unsigned (0, 16); - count1-dən yenidən adlandırılan saat bölücü sayğacı, əgər (yüksələn_kiymət (dalğaCLK)), sonra (Tetik = '1') olarsa- sayaca basılır: = sayıcı + 1; if (counter = imzasız (Freq_Cnt)) sonra - Freq_Cnt = 100Mhz / (sinus dalğasının freq * 64 bölməsinə diqqət yetirin) - sayğacı sıfırlayın və çıxış sayğacına amplitud məlumatlarını təyin edin: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplituda (i), 10)); - növbəti oxu üçün artım i <= i + 1; - i sinüs dalğası tamamlandıqda i i sıfırlayın (i = 63), onda i <= 0; bitərsə; bitərsə; - (sayğac = işarəsiz (Freq_Cnt)) başqa- düyməyə basılmır- çıxışı, amplituda indeksini və sayğacını sıfırlayın WaveOut <= "0000000000"; i <= 0; sayğac: = to_unsigned (0, 16); -çıxış amplitudu = -64, heç bir qeyd ifa olunmadıqda; - (Tetik = '1') bitərsə; - (yüksəliş_ kənarı (CLK)) son proses; Davranışa son qoymaq;

Daxili saat və ROMdan istifadə edərək Basys3 -də rəqəmsal sinus dalğası yaradacağıq. Bu ROM, bir sinus dalğasında 64 amplitüdünü təmsil edən 64 dəyəri saxlayacaq. Şəkil 1 -ə baxın. İstifadə etdiyimiz 64 dəyər olduqca yaxşı bir qətnamə ilə sinus dalğasını təqlid edir.

Daxili saatı istifadə edərək, istədiyimiz dalğanın tezliyinə bölünən saat sürətini təmsil edən bir dəyəri hesablayırıq və 64: Clk div = 100MHz / (Freq * 64) Sayğacımız bu dəyərə hər dəfə çatanda, ROM və dalğa generator modulumuzdan göndərin. Dalğamızın tezliyi, bu amplitüdləri nə qədər sürətli adlandırmağımızdan asılı olacaq.

Hər biri bir tezlik/qeydlə əlaqəli 25 alt modulumuz olacaq.

Sine Wave Generator modullarını çağıran kodun qalanları budur:

kitabxana IEEE; IEEE. STD_LOGIC_1164. ALL istifadə edin; IEEE. NUMERIC_STD. ALL istifadə edin; Two_Octave_Synth varlığı Limandır (CLK: STD_LOGIC -də; O4: STD_LOGIC_VECTOR -da (11 aşağıya 0); O5: STD_LOGIC_VECTOR -da (12 aşağıya 0); çıxış: STD_LOGIC xaricində); son İki_Oktava_Synth; Two_Octave_Synth arxitekturası Davranış Wave_Generator Limandır (Tetikleyici: STD_LOGIC -də; Freq_Cnt: STD_LOGIC_VECTOR -da (15 aşağı 0); wavegenCLK: STD_LOGIC -də; WaveOut: STD_LOGIC_VECTOR -dan 9 -a) son komponent; --------------------------- dalğa generatorundan çıxış siqnalları ------------------ ----- siqnal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, Wave5, Wave5, Wave5 WaveAs5, WaveB5, WaveC6: imzalanmışdır (9 aşağı 0); -------------------------------- qeyd seçimi məntiqi üçün -------------- ------ siqnal 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: işarəsiz (4 aşağı 0); siqnal 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: imzasız (4 aşağı 0); siqnal xətası: STD_LOGIC; ----------------------------------- sinus dalğaları əlavə etmək üçün ----------- --------------- dalğa0, dalğa1, dalğa2, dalğa3: işarələndi (9 aşağıya 0); -Dalğa Generator modulu çıxış siqnalı WaveSum-dan siqnallar: STD_LOGIC_VECTOR (9 aşağı 0); -ümumiləşdirilmiş sinus dalğaları üçün siqnal (2 -nin komplimenti -512 -dən 511 -ə qədər) müsbətWaveSum siqnalı: STD_LOGIC_VECTOR (9 -dan 0 -a qədər); -0 ilə 1023 arasında imzalanmamış, PWM generatorunda istifadə üçün ----------------------------------- PWM yaratmaq üçün ------------------------------- siqnal ping_length: işarəsiz (9 aşağı 0): = işarəsiz (müsbətWaveSum); --siqnal off_length: işarəsiz (6 aşağıya 0): = imzasız (127, 7) -imzasız (WAVE); siqnal PWM: işarəsiz (9 aşağı 0): = to_unsigned (0, 10); başlamaq Note_C4: Wave_Generator liman xəritəsi (Tetikleyici => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveC4); --5973, 261.63 Hz Note_Cs4: Wave_Generator port xəritəsi (Tetik => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveCs4);-5638, 277.18 Hz Note_D4: Wave_Generator liman xəritəsi (Tetik => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Wave_Generator liman xəritəsi (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveDs4);-5023, 311.13 Hz Note_E4: Wave_Generator liman xəritəsi (Tetik => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Wave_Generator liman xəritəsi (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Wave_Generator liman xəritəsi (Tetik => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveFs4);-4224, 369.99 Hz Note_G4: Wave_Generator liman xəritəsi (Tetik => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Wave_Generator liman xəritəsi (Tetik => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveGs4);-3763, 415.30 Hz Note_A4: Wave_Generator liman xəritəsi (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveA4); --3552, 440.00 Hz Note_As4: Wave_Generator liman xəritəsi (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveAs4);-3352, 466.16 Hz Note_B4: Wave_Generator liman xəritəsi (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveB4); --3164, 493.88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Wave_Generator liman xəritəsi (Tetik => O5 (0), Freq_Cnt => X "0BAB", dalğaCLK => CLK, imzalanmış (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Wave_Generator liman xəritəsi (Tetik => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveCs5);-2819, 554.37 Hz Note_D5: Wave_Generator liman xəritəsi (Tetik => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Wave_Generator liman xəritəsi (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveDs5);-2512, 622.25 Hz Note_E5: Wave_Generator liman xəritəsi (Tetik => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Wave_Generator liman xəritəsi (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Wave_Generator port xəritəsi (Tetik => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveFs5);-2112, 739.99 Hz Note_G5: Wave_Generator liman xəritəsi (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Wave_Generator liman xəritəsi (Tetik => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveGs5);-1882, 830.61 Hz Note_A5: Wave_Generator liman xəritəsi (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Wave_Generator liman xəritəsi (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveAs5);-1676, 932.33 Hz Note_B5: Wave_Generator liman xəritəsi (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Wave_Generator liman xəritəsi (Trigger => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, imzalanmış (WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ qeyd seçimi məntiqi ------------ 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; Seçim: proses (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, Wave5, Wave5, Wave5, Wave5 WaveB5, WaveC6) əgər başlasa (cntC6 = "00000") sonra --------------- heç bir siqnal yaranmırsa Wave0 <= "0000000000"; Dalğa1 <= "0000000000"; Dalğa2 <= "0000000000"; Dalğa3 <= "0000000000"; başqa (O4 (0) = '1') onda ------------------- qeyd C4 oynadı Dalğa0 Dalğa0 Dalğa1 xətası Dalğa0 Dalğa1 Dalğa2 Səhv Dalğa0 Dalğa1 Dalğa2 Dalğa3 Xəta Dalğa0 Dalğa1 Dalğa2 Dalğa3 xətası Dalğa0 Dalğa1 Dalğa2 Dalğa3 Dalğası0 Dalğa1 Dalğa2 Dalğa3 Dalğası1 Dalğa2 Dalğa2 Dalğa3 xətası Dalğa0 Dalğa1 Dalğa2 Dalğa3 Dalğası0 Dalğa1 Dalğa2 Dalğa3 Dalğası2 Dalğa2 = WaveC6; Dalğa1 <= "0000000000"; Dalğa2 <= "0000000000"; Dalğa3 Dalğa1 <= DalğaC6; Dalğa2 <= "0000000000"; Dalğa3 Dalğa2 <= DalğaC6; Dalğa3 Dalğa3 xətası Dalğa1 <= "0000000000"; Dalğa2 <= "0000000000"; Dalğa3 Dalğa2 <= "0000000000"; Wave3 Wave3 xətası <= '1'; son hal; bitərsə; bitərsə; prosesi bitirmək; ------------- sinus dalğa toplayıcısı -------------------- WaveSum <= STD_LOGIC_VECTOR (Dalğa0 + Dalğa1 + Dalğa2 + Dalğa3); --------- sinüs dalğasını pwm üçün pozitiv edin --------------------- pozitivWaveSum <= deyil WaveSum (9) və WaveSum (8-dən 0-a qədər)); ------------- PWM generatoru --------------------- proses (CLK)-dəyişən sayı: işarəsiz (1 aşağı 0): = imzasız (0, 2); əgər başlasa (yüksələn_kiymət (CLK)) sonra --sayı: = say + 1; --if (say = to_unsigned (4, 2)) sonra --count: = to_unsigned (0, 2); --if (PWM = to_ if (PWM <ping_length), sonra çıxış <= '1'; başqa çıxış <= '0'; son əgər; PWM <= PWM + 1; ping_length <= işarəsiz (müsbətWaveSum);-son əgər; sona çatsa; sona çatma prosesi; Davranışa son qoy;

4 Qeyd Seçicisi Bu layihənin ən çətin hissəsi yalnız dörd tezliyi seçməkdir. Bütün lotta IF ifadələri ilə etdik və prosesin simulyasiya edilməsi və düzəldilməsi üçün dəyişənlər yerinə siqnallardan istifadə etdik. Dəyişənlərdən və FOR döngələrindən istifadə edərək digər üsulları sınadıq, amma iş vaxtı səhvləri ilə üzləşdik. Beləliklə, sonunda qərar verdik ki, işə yarayarsa, onu tək qoyaq. Qırılmayan amiriti düzəltməyin?

Dörd çıxış dalğası Wave0, Wave1, Wave2, Wave3 olaraq etiketlənir - bunlar son çıxışı yaratmaq üçün bir araya gələcək.

Koda baxdığınızda, C4, Cs4, D4, Ds4 və s. Etiketli bir dəstə siqnal görürsünüz. Bunlar, O4 (oktava 4) və ya O5 (oktava 5) -dən müvafiq tetikleyicini götürən 5 bitlik siqnallardır. Əlavə etmək üçün 5 bit.

Sonrakı cntC4, cntCs4 və s. Dəyişənlər, hədəf notu da daxil olmaqla, hədəf notundan daha aşağı neçə notun oynandığını göstərir. Məsələn, C4, E4, G4, A#4 və D5 çalınsa (C9 akkordu) cntC4 1, cntE4 2, cntG4 3 və s.

Sonra, hər dəfə bir not çalındıqda, qeyd siqnalının haraya bağlanacağını görmək üçün hədəf notun sayı araşdırılacaq. Məsələn, D5 notu çalınırsa (bu O5 (2) yüksəkdir) və cntD5 3 -dirsə, hazırda 2 not D5 -dən aşağı olmaqla 3 not çalınır, buna görə də dalğa D5 -i Wave2 -ə bağlayacağıq (üçüncü dalğa) Dalğadan gələn siqnal sayılması0). Alternativ olaraq, əgər cntD5 5 -dirsə, hazırda D5 -dən 4 not aşağı olan 5 not oynanılır, buna görə də yalnız waveD5 -i asıb buraxacağıq və bununla heç nə etməyəcəyik.

IF ifadələri daha sonra bütün 25 qeydi əhatə edən halları əhatə etmək üçün təkrarlanır.

Amplitude Adder

Ən aşağı 4 dalğa seçildikdən sonra onları bir yerə əlavə etməliyik. Birlikdə yalnız dörd not əlavə etməyimizin səbəbi, Çıxış üçün istifadə etdiyimiz PWM ideyasının, PWM çox yavaş işləyənə və dinamikin PWM kvadrat dalğasını almağa başlayana qədər müəyyən bir qətnaməyə sahib olmasıdır. Məsələn, 8192 (13 bit) bir qətnamə istifadə etsək, bu 8192 nöqtənin hər biri təyyarə saatının yüksələn kənarına uyğun olmalıdır. Beləliklə, 100MHz / 8192 = 12.2kHz, bu da insan eşitmə qabiliyyətindədir.

Amplitudların faktiki olaraq əlavə edilməsi çox sadədir, sadəcə çox sürətli işləyə biləcəyinə əmin olmalısınız.

PWM Çıxışı

PWM -in vəzifə dövrü, o anda çıxış dalğamızın amplitüdünü təmsil edəcək. Məsələn, 0 -dan 128 -ə qədər bir amplitüd aralığımız varsa, 0 0%iş dövrü olardı, 64%50%, 128%100 olardı və s. Bu PWM son dərəcə sürətli işləyəcək (bizimki 97.6 kHz), dinamik o qədər sürətlidir ki, fərdi kvadrat dalğaları tanımayacaq və bunun əvəzinə "analoq" siqnalımızı yaradan orta gərginliyə baxacaq.

Məhdudiyyətlər faylı

Təchizatınızı fərqli bir şəkildə bağlamış ola bilərsiniz, buna görə məhdudiyyət faylının uyğun olduğuna əmin olun.

Addım 5: Kod Yükləmələri

Vivado üçün həm.txt formatında, həm də.vhd kodudur. Wave_Generator dalğa generatoru alt moduludur və Two_Octave_Synth başqa hər şeylə üst moduldur.

Tövsiyə: