İçindekiler:
- 1. Adım: Teori
- Adım 2: Malzemeler ve Araçlar
- Adım 3: Kablolama ve Donanım Kurulumu
- Adım 4: VHDL Kurulumu (Vivado)
- Adım 5: Kod İndirmeleri
Video: Basys3 FPGA Dijital Ses Sentezleyici: 5 Adım
2024 Yazar: John Day | [email protected]. Son düzenleme: 2024-01-30 13:21
Bu dijital sinüs dalgası klavye sentezleyici, bir klavye gibi düzenlenmiş bir dizi anlık anahtar aracılığıyla kullanıcı girişlerini alacak ve bir hoparlör aracılığıyla bir ses dalgası çıkışı yapacaktır. Kullanıcı girişlerine bağlı olarak cihaz, C4'ten C6'ya kadar çeşitli frekanslarda sinüs dalgaları üretecektir. Kullanıcı, C4'ten C6'ya kadar (toplam 25 nota) ve aynı anda dört tuşa kadar nota girebilir - dörtten fazla tuşa basılırsa, en düşük dört ton çalınır.
Bu proje Ryan Morris ve Mavis Tsoi tarafından Cal Poly CPE 133 Dijital Tasarım sınıfımız için yapılmıştır:)
1. Adım: Teori
Bir FPGA kartı yalnızca dijital sinyaller verebilir. Başka bir deyişle, yalnızca yüksek (3,3V) voltaj veya düşük (0V) voltaj üretebilir. Bununla birlikte, ses sinyalleri analogdur ve voltajda sonsuz sayıda artışa sahip olabilir. Bunu aşmak için bir analog dalgayı taklit etmek için bir PWM (darbe genişliği modülasyonu) sinyali kullanacağız. PWM'nin ne olduğunu bilmiyorsanız, şunu kontrol edin:
Adım 2: Malzemeler ve Araçlar
- Vivado yüklü bilgisayar
- Vivado 2017.2 sürümünü kullanacağız
- Basys3 FPGA Kartı
- 25 SPDT Limit Anahtarı (bunları kullandık)
- 30 atlama teli (bir ucu erkek, diğer ucu fark etmez), 12 inç
- Tel kesiciler
- Tel striptizci
- Lehimleme için yedek tel
- reçine çekirdekli Lehim
- Havya
- ¼” dişi ses jakı
- Amplifikatör/hoparlör
- Anahtarları monte etmek için bir şey (protoboard + tahta kutu kullandık)
Adım 3: Kablolama ve Donanım Kurulumu
sistem mimarisi
Bkz. Şekil 1: 25 kullanılabilir giriş → Basys3 Board → amplifikatör ve hoparlör.
Çıktı
Bkz. Şekil 2: Basys3 Board → 1/2 Dişi Ses Jakı → Hoparlör (Amplifikatörlü)
Giriş
Basys3 kartındaki pmod bağlantıları, düşük bir giriş görmek için toprağa bağlanmalıdır ve açık devre olarak bırakılırsa düzgün çalışmayacaktır. Bu nedenle, tüm nota anahtarlarımız için SPDT anahtarlarını kullanmak zorundayız. Bir SPDT anahtarı temelde kullanıcının basıldığında devreler arasında geçiş yapmasına izin verir, bu nedenle bunları Basys3 kartına düşük (0V) veya yüksek (3,3V) sinyaller girmek için "düğmelerimiz" olarak kullanacağız.
Her anahtarın NO (normalde açık) terminali 3.3V'a, NC (normalde kapalı) terminali GND'ye ve COM (ortak) terminali FPGA girişine bağlı olacaktır. Şekil 3'e bakın.
25 limit anahtarımız olduğundan, hepsi ortak bir 3.3V hattı ve ortak bir GND hattını paylaşacak. Ardından, her bir limit anahtarından gelen sinyal hattı, 8'li gruplar halinde toplanacak ve yapacağımız devasa karmaşayı en aza indirmek için sıkıştırılabilir jumper kabloları kullanarak Basys3 kartındaki pmod bağlantılarına bağlanacaktır. Şekil 4'e veya ilk sekiz tuş örneğine bakın.
Adım 4: VHDL Kurulumu (Vivado)
Konseptimizin çalıştığından emin olmak için önce sinüs dalgası üreteci ve PWM üreteci test edildi, ardından giriş sınırlayıcı ve genlik toplayıcı/kaydırıcı entegre edildi. Her bir proses bloğunun fonksiyonu ve I/O detayları Şekilde gösterildiği gibidir. Kod aşağıda gösterilmiştir, ancak VHD ve txt dosyaları olarak da eklenmiştir. Tutarsızlıklar varsa, VHD dosyalarıyla gidin.
BTW: Muhtemelen satırlarımızı daha kısa yapmalıydık, ancak Instructables'a kod yerleştirmenin de uğraşması oldukça can sıkıcı olduğu ortaya çıktı, bu nedenle boşluk en büyük değil ve sözdizimi vurgulaması yok. Vivado'nuz varsa ve kodu takip etmek istiyorsanız, dosyayı indirmenizi şiddetle tavsiye ederiz.
Öncelikle Sinüs Jeneratörü modülüne bakalım.
kitaplık IEEE;IEEE. STD_LOGIC_1164. ALL kullanın; IEEE. NUMERIC_STD. ALL kullanın; varlık Wave_Generator Port is (Tetikleyici: STD_LOGIC'de; -- Tuşa basma Freq_Cnt: STD_LOGIC_VECTOR'da(15'ten 0'a); -- Sayaç değeri = 100MHz / (Not Frekansı*64 Sinüs Dalgası Bölümü) (yuvarladan en yakın sayıya) -- yeniden adlandırıldı Freq wavegenCLK'den: STD_LOGIC'de; -- Basys3 100MHz CLK WaveOut: çıkış STD_LOGIC_VECTOR(9'dan 0'a); -- Dalga sonunun işaretli genliği Wave_Generator; mimari Wave_Generator davranışı i sinyalidir: tamsayı aralığı 0 ila 64:= 0; -- genlik bellek bankası tipinin indeksi memory_type tamsayı aralığının (0 ila 63) dizisidir -64 ila 63; -- genlik değerlerini tutmak için bellek bankası (ROM) oluşturun -- bu RAM veya ROM sadece merak mı ediyor… sinyal genliği: 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); -- sinüs dalgası başlangıç süreci için genlik bellek bankası (wavegenCLK, Trigger) değişken sayıcı: unsigned (15'ten 0)'a:= to_unsigned(0, 16); -- saat bölücü sayacı, say1'den yeniden adlandırılan start if (rising_edge(wavegenCLK)) sonra if (Tetikleyici = '1') o zaman -- tuşuna basılırsa sayıcı:= sayaç + 1; if (counter = unsigned(Freq_Cnt)) o zaman -- Freq_Cnt = 100Mhz / (freq * sinüs dalgasının 64 bölümünü not edin) -- sayacı sıfırlayın ve çıkış sayacına genlik verisi atayın:= to_unsigned(0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed(genlik(i), 10)); -- sonraki okuma için i artırma i <= i + 1; -- i'yi sıfırla eğer bir sinüs dalgası tamamlandıysa if(i = 63) o zaman i <= 0; eğer son; eğer son; -- (counter = unsigned(Freq_Cnt)) başka -- tuşa basılmaz -- çıkışı, genlik indeksini ve sayacı sıfırlayın WaveOut <= "0000000000"; ben <= 0; sayaç:= to_unsigned(0, 16); --output Genlik = -64 nota çalınmadığında sona ererse; -- (Tetikleyici = '1') if sonu; -- (rising_edge(CLK)) bitiş işlemi; son Davranış;
Dahili saat ve bir ROM kullanarak Basys3'te bir dijital sinüs dalgası üreteceğiz. Bu ROM, bir sinüs dalgasında 64 genliği temsil eden 64 değeri saklayacaktır. Bkz. Şekil 1. Kullandığımız 64 değer, oldukça iyi çözünürlüğe sahip bir sinüs dalgasına öykünür.
Dahili saati kullanarak, saat hızını istediğimiz dalganın frekansına bölerek temsil eden bir değere kadar sayıyoruz ve 64: Clk div = 100MHz / (Freq * 64) Sayacımız o değere her ulaştığında, bir numara çağırıyoruz. ROM'u seçin ve bunu dalga üreteci modülümüzden gönderin. Dalgamızın frekansı, bu genlikleri ne kadar hızlı olarak adlandırdığımıza bağlı olacaktır.
Her biri bir frekans/nota ile ilişkili 25 alt modülümüz olacak.
İşte Sine Wave Generator modüllerini çağıran kodun geri kalanı:
kitaplık IEEE;IEEE. STD_LOGIC_1164. ALL kullanın; IEEE. NUMERIC_STD. ALL kullanın; varlık Two_Octave_Synth Port is (CLK: STD_LOGIC'de; O4: STD_LOGIC_VECTOR'da(11'den 0'a); O5: STD_LOGIC_VECTOR'da(12'den 0'a); çıktı: STD_LOGIC çıkışında); Two_Octave_Synth'i sonlandır; mimari Two_Octave_Synth'in Davranışı Wave_Generator bileşenidir Port (Tetikleyici: STD_LOGIC'de; Freq_Cnt: STD_LOGIC_VECTOR'da(15'ten 0'a); wavegenCLK: STD_LOGIC'de; WaveOut: çıkış STD_LOGIC_VECTOR(9'dan 0'a); uç bileşen; ---------------------------Dalga üretecinden gelen çıkış sinyalleri------------------ ----- sinyal WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveGs5, WaveA5, WaveAs5, WaveB5, WaveC6: imzalı(9'dan 0'a); --------------------------------Not seçim mantığı için-------------- ------ sinyal 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şaretsiz(4'ten 0'a kadar); sinyal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntF5, cntFs5, cntG5, cnt,cnt,cnt,cntG5,As cnt,cntG5,As: imzasız(4'ten 0'a kadar); sinyal hatası: STD_LOGIC; ----------------------------------- sinüs dalgaları eklemek için ----------- --------------- sinyal Dalga0, Dalga1, Dalga2, Dalga3: işaretli(9'dan 0'a); --Dalga Üretici modülü çıkış sinyalinden gelen sinyaller WaveSum: STD_LOGIC_VECTOR(9'dan 0'a); --toplanan sinüs dalgaları için sinyal (2'nin tamamlayıcısı -512 ila 511) sinyal pozitifWaveSum: STD_LOGIC_VECTOR(9'dan 0'a); --unsigned 0 - 1023, PWM üretecinde kullanım için -----------------------------------PWM oluşturmak için ---------------------------------- sinyal ping_length: unsigned (9'dan 0'a kadar):= unsigned(positiveWaveSum); --signal off_length: unsigned (6'dan 0'a kadar):= to_unsigned(127, 7) - unsigned(WAVE); sinyal PWM: unsigned (9'dan 0'a kadar):= to_unsigned(0, 10); start Note_C4: Wave_Generator port haritası (Trigger => O4(0), Freq_Cnt => X"1755", wavegenCLK => CLK, imzalı(WaveOut) => WaveC4); --5973, 261.63 Hz Note_Cs4: Wave_Generator port haritası (Trigger => O4(1), Freq_Cnt => X"1606", wavegenCLK => CLK, Signed(WaveOut) => WaveCs4);--5638, 277.18 Hz Note_D4: Wave_Generator port haritası (Trigger => O4(2), Freq_Cnt => X"14C9", wavegenCLK => CLK, imzalı(WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Wave_Generator port haritası (Trigger => O4(3), Freq_Cnt => X"139F", wavegenCLK => CLK, Signed(WaveOut) => WaveDs4);--5023, 311.13 Hz Note_E4: Wave_Generator port haritası (Trigger => O4(4), Freq_Cnt => X"1285", wavegenCLK => CLK, imzalı(WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Wave_Generator port haritası (Trigger => O4(5), Freq_Cnt => X"117B", wavegenCLK => CLK, imzalı(WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Wave_Generator port haritası (Trigger => O4(6), Freq_Cnt => X"1080", wavegenCLK => CLK, Signed(WaveOut) => WaveFs4);--4224, 369.99 Hz Note_G4: Wave_Generator port haritası (Trigger => O4(7), Freq_Cnt => X"0F92", wavegenCLK => CLK, imzalı(WaveOut) => WaveG4); --3986, 392.00 Hz Note_Gs4: Wave_Generator port haritası (Trigger => O4(8), Freq_Cnt => X"0EB3", wavegenCLK => CLK, Signed(WaveOut) => WaveGs4);--3763, 415.30 Hz Note_A4: Wave_Generator port haritası (Trigger => O4(9), Freq_Cnt => X"0DE0", wavegenCLK => CLK, imzalı(WaveOut) => WaveA4); --3552, 440.00 Hz Note_As4: Wave_Generator port haritası (Trigger => O4(10), Freq_Cnt => X"0D18", wavegenCLK => CLK, Signed(WaveOut) => WaveAs4);--3352, 466.16 Hz Note_B4: Wave_Generator port haritası (Trigger => O4(11), Freq_Cnt => X"0C5C", wavegenCLK => CLK, imzalı(WaveOut) => WaveB4); --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Wave_Generator port haritası (Tetikleyici => O5(0), Freq_Cnt => X"0BAB", wavegenCLK => CLK, işaretli(WaveOut) => WaveC5); --2987, 523,25 Hz Note_Cs5: Wave_Generator port haritası (Trigger => O5(1), Freq_Cnt => X"0B03", wavegenCLK => CLK, Signed(WaveOut) => WaveCs5);--2819, 554.37 Hz Note_D5: Wave_Generator port haritası (Trigger => O5(2), Freq_Cnt => X"0A65", wavegenCLK => CLK, imzalı(WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Wave_Generator port haritası (Trigger => O5(3), Freq_Cnt => X"09D0", wavegenCLK => CLK, Signed(WaveOut) => WaveDs5);--2512, 622.25 Hz Note_E5: Wave_Generator port haritası (Trigger => O5(4), Freq_Cnt => X"0943", wavegenCLK => CLK, imzalı(WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Wave_Generator port haritası (Trigger => O5(5), Freq_Cnt => X"08Be", wavegenCLK => CLK, işaretli(WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Wave_Generator bağlantı noktası haritası (Trigger => O5(6), Freq_Cnt => X"0840", wavegenCLK => CLK, Signed(WaveOut) => WaveFs5);--2112, 739,99 Hz Note_G5: Wave_Generator port haritası (Trigger => O5(7), Freq_Cnt => X"07CA", wavegenCLK => CLK, imzalı(WaveOut) => WaveG5); --1994, 783.99 Hz Note_Gs5: Wave_Generator port haritası (Trigger => O5(8), Freq_Cnt => X"075A", wavegenCLK => CLK, Signed(WaveOut) => WaveGs5);--1882, 830.61 Hz Note_A5: Wave_Generator port haritası (Trigger => O5(9), Freq_Cnt => X"06F0", wavegenCLK => CLK, imzalı(WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Wave_Generator port haritası (Trigger => O5(10), Freq_Cnt => X"068C", wavegenCLK => CLK, Signed(WaveOut) => WaveAs5);--1676, 932.33 Hz Note_B5: Wave_Generator port haritası (Trigger => O5(11), Freq_Cnt => X"062E", wavegenCLK => CLK, imzalı(WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Wave_Generator port haritası (Tetikleyici => O5(12), Freq_Cnt => X"05D6", wavegenCLK => CLK, işaretli(WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ not seçim mantığı ------------ 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, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveGs5, WaveA5, WaveAs5, WaveB5, WaveC6) eğer (cntC6 = "00000") ise başlar o zaman --------------- eğer sinyal üretilmiyorsa Wave0 <= "0000000000"; Dalga1 <= "00000000000"; Dalga2 <= "00000000000"; Dalga3 <= "00000000000"; else if (O4(0) = '1') ise ------------------- not C4 çalındı Dalga0 Dalga0 Dalga1 hatası Dalga0 Dalga1 Dalga2 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 Dalga1 Dalga2 Dalga3 hatası Dalga0 < = DalgaC6; Dalga1 <= "00000000000"; Dalga2 <= "00000000000"; Dalga3 Dalga1 <= DalgaC6; Dalga2 <= "00000000000"; Dalga3 Dalga2 <= DalgaC6; Dalga3 Dalga3 hatası Dalga1 <= "0000000000"; Dalga2 <= "00000000000"; Dalga3 Dalga2 <= "00000000000"; Dalga3 Dalga3 hatası <= '1'; son durum; eğer son; eğer son; bitiş süreci; -------------sinüs dalgası toplayıcı-------------------- WaveSum <= STD_LOGIC_VECTOR(Dalga0 + Dalga1 + Dalga2 + Dalga3); --------- pwm için sinüs dalgasını pozitif yap --------------------- pozitifWaveSum <= WaveSum(9) değil & WaveSum(8'den 0'a kadar)); -------------PWM üreteci ---------------------- süreç(CLK) --değişken sayısı: işaretsiz (1'den 0'a kadar)):= to_unsigned(0, 2); başlar if (rising_edge(CLK)) sonra --count:= count + 1; --if (count = to_unsigned(4, 2)) o zaman --count:= to_unsigned(0, 2); --if (PWM = to_ if (PWM < ping_length) o zaman çıktı <= '1'; else çıktı <= '0'; end if; PWM <= PWM + 1; ping_length <= unsigned(pozitifWaveSum); --end eğer; eğer sonu; süreci sonlandır; Davranışı sonlandır;
4 Not SeçiciBu projenin en zor kısmı sadece dört frekans seçmektir. Bunu bir sürü IF deyimiyle yaptık ve sürecin simüle edilebilmesi ve hatalarının ayıklanabilmesi için değişkenler yerine sinyaller kullandık. Değişkenleri ve FOR döngülerini kullanarak başka yöntemler denedik, ancak çalışma zamanı hatalarıyla karşılaştık. Sonunda, işe yararsa onu kendi haline bırakmaya karar verdik. Amirite bozuk olmayanı tamir etmiyor musun?
Dört çıkış dalgası Dalga0, Dalga1, Dalga2, Dalga3 olarak etiketlenir - bunlar nihai çıktıyı oluşturmak için birlikte eklenecek olanlardır.
Koda baktığınızda, C4, Cs4, D4, Ds4 vb. etiketli bir grup sinyal göreceksiniz. Bunlar, karşılık gelen tetikleyiciyi O4 (oktav 4) veya O5'ten (oktav 5) alan ve onları oluşturan 5 bitlik sinyallerdir. Eklemek için 5 bit.
Daha sonra cntC4, cntCs4, vb. değişkenleri, hedef nota dahil olmak üzere hedef notadan daha düşük kaç nota çalındığını gösterir. Örneğin, C4, E4, G4, A#4 ve D5 çalınırsa (C9 akoru) cntC4 1 olur, cntE4 2 olur, cntG4 3 olur, vb.
Ardından, bir nota çalındığında, nota sinyalinin nereye bağlanacağını görmek için hedef nota sayımı incelenir. Örneğin, D5 notası çalınıyorsa (bu, O5(2)'nin yüksek olduğu anlamına gelir) ve cntD5 3 ise, o zaman şu anda 2 nota D5'ten daha düşük olan 3 nota çalınmaktadır, bu nedenle waveD5'i Wave2'ye bağlayacağız (üçüncü dalga) Dalga0'dan sinyal sayımı). Alternatif olarak, cntD5 5 ise, o zaman şu anda D5'ten daha düşük 4 nota ile çalınmakta olan 5 nota vardır, bu nedenle waveD5'i asılı bırakacağız ve onunla hiçbir şey yapmayacağız.
IF ifadeleri daha sonra 25 notun tümü için durumları kapsayacak şekilde tekrarlanır.
Genlik Toplayıcı
En düşük 4 dalga seçildikten sonra bunları bir araya toplamamız gerekiyor. Yalnızca dört notu bir araya toplamamızın nedeni, çıktımız için kullandığımız PWM fikrinin, PWM çok yavaş çalışana ve konuşmacı PWM kare dalgasını almaya başlayana kadar yalnızca belirli bir çözünürlüğe sahip olabilmesidir. Örneğin, 8192 (13 bit) çözünürlük kullanacak olsaydık, bu 8192 noktanın her biri yerleşik saatin yükselen kenarına karşılık gelmelidir. Yani, 100MHz / 8192 = 12.2kHz, bu da insan işitme aralığı içindedir.
Genliklerin gerçek eklenmesi çok basittir, sadece gerçekten hızlı çalışabileceğinden emin olmanız gerekir.
PWM Çıkışı
PWM'nin görev döngüsü, o andaki çıkış dalgamızın genliğini temsil edecektir. Örneğin, 0 ile 128 arasında bir genlik aralığımız varsa, 0 %0 görev döngüsü, 64 %50, 128 %100 vb. olur. Bu PWM son derece hızlı çalışır (bizimki 97.6 kHz), o kadar hızlı ki, konuşmacı tek tek kare dalgaları tanımayacak ve bunun yerine ortalama voltaja bakarak “analog” sinyalimizi yaratacaktır.
Kısıtlamalar Dosyası
Donanımınızı farklı şekilde bağlamış olabilirsiniz, bu nedenle kısıtlama dosyasının eşleştiğinden emin olun.
Adım 5: Kod İndirmeleri
Aşağıda hem.txt biçiminde hem de Vivado için.vhd kodu bulunmaktadır. Wave_Generator, dalga üreteci alt modülüdür ve Two_Octave_Synth, diğer her şeyin bulunduğu en üst modüldür.
Önerilen:
Arpej Sentezleyici (Sivrisinek I): 6 Adım
Arpeggiating Synthesizer (Mosquito I): Mosquito I, Arduino Nano ve Mozzi ses sentez kitaplığını kullanan küçük bir arpej sentezleyicidir. Yirmiden fazla 8 adımlı diziyi çalabilir, ancak istediğiniz kadar özel dizi ekleyebilirsiniz. Kurulumu nispeten basittir ve
Dijital Kumpas Nasıl Yıkılır ve Dijital Kumpas Nasıl Çalışır: 4 Adım
Dijital Kumpas Nasıl Yıkılır ve Dijital Kumpas Nasıl Çalışır: Birçok kişi ölçüm için kumpas kullanmayı bilir. Bu eğitim size bir dijital kumpasın nasıl parçalanacağını ve dijital kumpasın nasıl çalıştığının bir açıklamasını öğretecektir
Bluetooth Ses ve Dijital Sinyal İşleme: Arduino Çerçevesi: 10 Adım
Bluetooth Ses ve Dijital Sinyal İşleme: bir Arduino Çerçevesi: Özet Bluetooth'u düşündüğümde aklıma müzik geliyor ama ne yazık ki çoğu mikrodenetleyici Bluetooth üzerinden müzik çalamıyor. Raspberry Pi yapabilir ama bu bir bilgisayar. Mikrodenetleyicilerin Bluet aracılığıyla ses çalması için Arduino tabanlı bir çerçeve geliştirmek istiyorum
Basit ve Ucuz Lazer Dijital Ses İletimi: 4 Adım
Basit ve Ucuz Lazer Dijital Ses İletimi: Lazer silahını yaptığımdan beri, lazeri, eğlence için (çocuk interkomu) veya belki daha karmaşık bir lazer silahı için veri iletmek için ses göndermek için modüle etmeyi düşünüyorum. , bir alıcının kime çarptığını bulmasını sağlar.
Özel Gümüş Kablolar Ses/Dijital/Yüksek Frekans/GPS: 7 Adım
Özel Gümüş Kablolar Ses/Dijital/Yüksek Frekans/GPS: Hem ipod için ses hem de artık video için dijital olan birçok yeni ses/video modu ve yeni cihazla, sistemlerimizi daha karmaşık kablolarla yeni cihazlara bağlamamız gerekiyor. Bazıları çok pahalı…Bunlarda olması gereken bileşenler & inşaat projesi için malzemeler