İçindekiler:

Basys3 FPGA Dijital Ses Sentezleyici: 5 Adım
Basys3 FPGA Dijital Ses Sentezleyici: 5 Adım

Video: Basys3 FPGA Dijital Ses Sentezleyici: 5 Adım

Video: Basys3 FPGA Dijital Ses Sentezleyici: 5 Adım
Video: Vivado ile VHDL dilinde Basys 3 FPGA kullanarak Elektronik Zar 2024, Kasım
Anonim
Image
Image
Basys3 FPGA Dijital Ses Sentezleyici
Basys3 FPGA Dijital Ses Sentezleyici
Basys3 FPGA Dijital Ses Sentezleyici
Basys3 FPGA Dijital Ses Sentezleyici

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

Kablolama ve Donanım Kurulumu
Kablolama ve Donanım Kurulumu
Kablolama ve Donanım Kurulumu
Kablolama ve Donanım Kurulumu
Kablolama ve Donanım Kurulumu
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)

VHDL Kurulumu (Vivado)
VHDL Kurulumu (Vivado)
VHDL Kurulumu (Vivado)
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: