Isi kandungan:

Pensintesis Audio Digital Basys3 FPGA: 5 Langkah
Pensintesis Audio Digital Basys3 FPGA: 5 Langkah

Video: Pensintesis Audio Digital Basys3 FPGA: 5 Langkah

Video: Pensintesis Audio Digital Basys3 FPGA: 5 Langkah
Video: #11 Digital Safe System Implementation on Basys 3 FPGA Board | Verilog | Step-by-Step Instructions 2024, Julai
Anonim
Image
Image
Pensintesis Audio Digital Basys3 FPGA
Pensintesis Audio Digital Basys3 FPGA
Pensintesis Audio Digital Basys3 FPGA
Pensintesis Audio Digital Basys3 FPGA

Synthesizer keyboard gelombang sinus digital ini akan mengambil input pengguna melalui rangkaian suis sesaat seperti papan kekunci dan mengeluarkan gelombang audio melalui pembesar suara. Berdasarkan input pengguna, peranti ini akan menghasilkan gelombang sinus dari pelbagai frekuensi dari C4 hingga C6. Pengguna dapat memasukkan nota dari C4 hingga C6 (total 25 nota), dan hingga empat kekunci pada masa yang sama - jika lebih dari empat kekunci ditekan, empat nada terendah akan dimainkan.

Projek ini dilakukan oleh Ryan Morris dan Mavis Tsoi untuk kelas Reka Bentuk Digital Cal Poly CPE 133 kami:)

Langkah 1: Teori

Papan FPGA hanya dapat mengeluarkan isyarat digital. Dengan kata lain, ia hanya dapat menghasilkan voltan tinggi (3.3V) atau voltan rendah (0V). Walau bagaimanapun, isyarat audio adalah analog dan boleh mempunyai kenaikan voltan yang tidak terhingga. Untuk mengatasi ini, kita akan menggunakan isyarat PWM (modulasi lebar nadi) untuk meniru gelombang analog. Sekiranya anda tidak tahu apa itu PWM, lihat ini:

Langkah 2: Bahan & Alatan

  • Komputer dengan Vivado dipasang
  • Kami akan menggunakan versi Vivado 2017.2
  • Papan FPGA Basys3
  • 25 Suis Had SPDT (kami menggunakannya)
  • 30 wayar pelompat (satu hujung lelaki, hujung yang lain tidak menjadi masalah), 12 inci
  • Pemotong wayar
  • Pelucut wayar
  • Wayar ganti untuk pematerian
  • Pemateri teras-resin
  • Besi pematerian
  • Audio bicu audio wanita
  • Penguat / pembesar suara
  • Sesuatu untuk memasang suis (kami menggunakan protoboard + kotak kayu)

Langkah 3: Persediaan Pendawaian & Perkakasan

Penyediaan Pendawaian & Perkakasan
Penyediaan Pendawaian & Perkakasan
Penyediaan Pendawaian & Perkakasan
Penyediaan Pendawaian & Perkakasan
Penyediaan Pendawaian & Perkakasan
Penyediaan Pendawaian & Perkakasan

Senibina Sistem

Lihat Gambar 1: 25 input yang tersedia → Papan Basys3 → penguat & pembesar suara.

Pengeluaran

Lihat Gambar 2: Papan Basys3 → Jack Audio Wanita 1/2 → Pembesar suara (dengan Penguat)

Masukan

Sambungan pmod pada papan Basys3 mesti disambungkan ke tanah untuk melihat input rendah dan tidak akan berfungsi dengan baik jika dibiarkan sebagai litar terbuka. Oleh kerana itu, kita harus menggunakan suis SPDT untuk semua kunci nota kita. Suis SPDT pada dasarnya membolehkan pengguna beralih antara litar semasa ditekan, jadi kami akan menggunakannya sebagai "butang" kami untuk memasukkan isyarat rendah (0V) atau tinggi (3.3V) ke papan Basys3.

Setiap suis akan mempunyai terminal NO (biasanya dibuka) yang disambungkan ke 3.3V, terminal NC (biasanya ditutup) disambungkan ke GND, dan terminal COM (biasa) disambungkan ke input FPGA. Lihat Rajah 3.

Kerana kita mempunyai 25 suis had, semuanya akan berkongsi garis 3.3V dan garis GND biasa. Kemudian, garis isyarat dari setiap suis had akan digabungkan dalam kumpulan 8 dan disambungkan ke sambungan pmod pada papan Basys3 menggunakan wayar jumper berzip untuk meminimumkan kekacauan monumental yang akan kita buat. Lihat Gambar 4 atau contoh lapan kunci pertama.

Langkah 4: Persediaan VHDL (Vivado)

Persediaan VHDL (Vivado)
Persediaan VHDL (Vivado)
Persediaan VHDL (Vivado)
Persediaan VHDL (Vivado)

Penjana gelombang sinus dan penjana PWM pertama kali diuji untuk memastikan konsep kami berfungsi, kemudian pengehad input dan penambah / pengubah amplitud disatukan. Perincian fungsi dan I / O dari setiap blok proses adalah seperti yang ditunjukkan dalam Gambar. Kod ditunjukkan di bawah, tetapi juga dilampirkan sebagai fail VHD dan txt. Sekiranya terdapat perbezaan, gunakan fail VHD.

BTW: kita mungkin sepatutnya membuat garis kita lebih pendek tetapi penyisipan kod pada Instructables ternyata agak menjengkelkan untuk ditangani, jadi jaraknya bukanlah yang terbaik dan tidak ada penekanan sintaks. Sekiranya anda mempunyai Vivado dan ingin mengikuti kodnya, kami sangat mengesyorkan anda memuat turun fail tersebut.

Pertama, mari kita lihat modul Sine Wave Generator.

perpustakaan IEEE; gunakan IEEE. STD_LOGIC_1164. ALL; gunakan IEEE. NUMERIC_STD. ALL; entiti Wave_Generator adalah Port (Pencetus: dalam STD_LOGIC; - Tekan kekunci Freq_Cnt: dalam STD_LOGIC_VECTOR (15 ke bawah 0); - Nilai penghitung = 100MHz / (Kekerapan Catatan * 64 Bahagian Gelombang Sinus) (bulat ke angka terdekat) - dinamakan semula dari gelombang FreqCLK: dalam STD_LOGIC; - Basys3 100MHz CLK WaveOut: keluar STD_LOGIC_VECTOR (9 ke bawah 0)); - Amplitud tanda gelombang Wave_Generator yang ditandatangani; senibina Behavioral of Wave_Generator adalah isyarat i: julat integer 0 hingga 64: = 0; - indeks bank memori amplitud jenis memory_type ialah array (0 hingga 63) julat bilangan bulat -64 hingga 63; - buat bank memori (ROM) untuk menahan nilai amplitud - adakah RAM atau ROM ini hanya tertanya-tanya… amplitud isyarat: 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); - bank memori amplitud untuk proses permulaan gelombang sinus (wavegenCLK, Trigger) pembilang pemboleh ubah: tidak ditandatangani (15 ke bawah 0): = to_unsigned (0, 16); - pembilang jam pembahagi, dinamakan semula dari kiraan1 bermula jika (meningkat_kebaikan (gelombanggenCLK)) kemudian jika (Pemicu = '1') maka - kekunci ditekan pembilang: = pembilang + 1; jika (pembilang = tidak ditandatangani (Freq_Cnt)) maka - Freq_Cnt = 100Mhz / (perhatikan freq * 64 bahagian gelombang sinus) - tetapkan semula pembilang dan tetapkan data amplitud ke kaunter output: = to_unsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (to_signed (amplitud (i), 10)); - kenaikan i untuk bacaan seterusnya i <= i + 1; - tetapkan semula i jika satu gelombang sinus telah selesai jika (i = 63) maka i <= 0; tamat sekiranya; tamat sekiranya; - (counter = unsigned (Freq_Cnt)) lain - kekunci tidak ditekan - tetapkan semula output, indeks amplitud, dan pembilang WaveOut <= "0000000000"; saya <= 0; pembilang: = to_unsigned (0, 16); - Output Amplitude = -64 apabila nota dimainkan akhir jika; - (Pencetus = '1') berakhir jika; - (end_edge (CLK)) proses akhir; Tingkah laku akhir;

Kami akan menghasilkan gelombang sinus digital di Basys3 dengan menggunakan jam dalaman dan ROM. ROM ini akan menyimpan 64 nilai yang mewakili 64 amplitud pada gelombang sinus. Lihat Gambar 1. 64 nilai yang kita gunakan meniru gelombang sinus dengan resolusi yang cukup baik.

Dengan menggunakan jam dalaman, kita mengira nilai yang mewakili kelajuan jam dibahagi dengan frekuensi gelombang yang kita mahukan dan 64: Clk div = 100MHz / (Freq * 64) Setiap kali kaunter kami mencapai nilai itu, kami memanggil nombor dari ROM dan hantar keluar dari modul penjana gelombang kami. Kekerapan gelombang kita akan bergantung pada seberapa cepat kita memanggil amplitud ini.

Kami akan mempunyai 25 sub-modul, masing-masing dikaitkan dengan satu frekuensi / nota.

Inilah baki kod yang memanggil modul Sine Wave Generator:

perpustakaan IEEE; gunakan IEEE. STD_LOGIC_1164. ALL; gunakan IEEE. NUMERIC_STD. ALL; entiti Two_Octave_Synth adalah Port (CLK: in STD_LOGIC; O4: in STD_LOGIC_VECTOR (11 downto 0); O5: in STD_LOGIC_VECTOR (12 downto 0); output: out STD_LOGIC); tamat Two_Octave_Synth; seni bina Behavioral of Two_Octave_Synth adalah komponen Wave_Generator adalah Port (Pencetus: dalam STD_LOGIC; Freq_Cnt: dalam STD_LOGIC_VECTOR (15 ke bawah 0); wavegenCLK: dalam STD_LOGIC; WaveOut: keluar STD_LOGIC_VECTOR (9 ke 0)); komponen akhir; --------------------------- isyarat output dari penjana gelombang ------------------ ----- isyarat WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveGs5, WaveA5, Wave WaveAs5, WaveB5, WaveC6: ditandatangani (9 ke bawah 0); -------------------------------- untuk logik pemilihan nota -------------- ------ isyarat 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: tidak ditandatangani (4 ke bawah 0); isyarat cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cnt, c5, cnt, cnt, cnt, cnt, c5, cnt: tidak ditandatangani (4 ke bawah 0); ralat isyarat: STD_LOGIC; ----------------------------------- untuk menambah gelombang sinus ----------- --------------- isyarat Wave0, Wave1, Wave2, Wave3: ditandatangani (9 ke bawah 0); --signal dari isyarat output modul Wave Generator WaveSum: STD_LOGIC_VECTOR (9 ke bawah 0); --signal untuk gelombang sinus penjumlahan (pujian 2 -512 hingga 511) isyarat positifWaveSum: STD_LOGIC_VECTOR (9 ke bawah 0); - tidak ditandatangani 0 hingga 1023, untuk digunakan dalam penjana PWM ----------------------------------- untuk menghasilkan PWM ------------------------------- signal ping_length: unsigned (9 downto 0): = unsigned (positiveWaveSum); --signal off_length: unsigned (6 downto 0): = to_unsigned (127, 7) - unsigned (WAVE); isyarat PWM: tidak ditandatangani (9 ke bawah 0): = to_unsigned (0, 10); mulakan Note_C4: Peta port Wave_Generator (Trigger => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveC4); --5973, 261.63 Hz Note_Cs4: Peta port Wave_Generator (Trigger => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveCs4); - 5638, 277.18 Hz Note_D4: Peta port Wave_Generator (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveD4); --5321, 293.66 Hz Note_Ds4: Peta port Wave_Generator (Trigger => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveDs4); - 5023, 311.13 Hz Note_E4: Peta pelabuhan Wave_Generator (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveE4); --4741, 329.63 Hz Note_F4: Peta port Wave_Generator (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveF4); --4475, 349.23 Hz Note_Fs4: Peta port Wave_Generator (Pencetus => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveFs4); - 4224, 369.99 Hz Note_G4: Peta pelabuhan Wave_Generator (Trigger => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveG4); --3986, 392,00 Hz Note_Gs4: Peta port Wave_Generator (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveGs4); - 3763, 415.30 Hz Note_A4: Peta port Wave_Generator (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveA4); --3552, 440,00 Hz Note_As4: Peta port Wave_Generator (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveAs4); - 3352, 466.16 Hz Note_B4: Peta pelabuhan Wave_Generator (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveB4); --3164, 493.88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Peta port Wave_Generator (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Peta port Wave_Generator (Trigger => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveCs5); - 2819, 554.37 Hz Note_D5: Peta pelabuhan Wave_Generator (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveD5); --2661, 587.33 Hz Note_Ds5: Peta port Wave_Generator (Trigger => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveDs5); - 2512, 622.25 Hz Note_E5: Peta pelabuhan Wave_Generator (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveE5); --2371, 659.25 Hz Note_F5: Peta port Wave_Generator (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Peta port Wave_Generator (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveFs5); - 2112, 739.99 Hz Note_G5: Peta pelabuhan Wave_Generator (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveG5); --1994, 783,99 Hz Note_Gs5: Peta port Wave_Generator (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveGs5); - 1882, 830.61 Hz Note_A5: Peta pelabuhan Wave_Generator (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Peta port Wave_Generator (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveAs5); - 1676, 932.33 Hz Note_B5: Peta pelabuhan Wave_Generator (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveB5); --1582, 987.77 Hz Note_C6: Peta port Wave_Generator (Pencetus => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ logik pemilihan nota ------------ 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; Pemilihan: proses (WaveC4, WaveCs4, WaveD4, WaveDs4, WaveE4, WaveF4, WaveFs4, WaveG4, WaveGs4, WaveA4, WaveAs4, WaveB4, WaveC5, WaveCs5, WaveD5, WaveDs5, WaveE5, WaveF5, WaveFs5, WaveG5, WaveG5, Wave5 WaveB5, WaveC6) bermula jika (cntC6 = "00000") maka --------------- jika tidak ada isyarat yang dihasilkan Wave0 <= "0000000000"; Gelombang1 <= "0000000000"; Gelombang2 <= "0000000000"; Gelombang3 <= "0000000000"; lain jika (O4 (0) = '1') maka ------------------- perhatikan C4 dimainkan Wave0 Wave0 Wave1 error1 Wave0 Wave1 Wave2 error Wave0 Wave1 Wave2 Wave3 error3 Wave0 Wave1 Ralat Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 error3 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error3 Wave0 Wave1 Wave2 Wave3 Wave3 Wave1 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 Wave3 Wave0 Wave1 Wave2 Wave3 Wave3 Wave3 Wave1 Wave2 Wave3 error1 Wave1 Wave1 Ralat Wave2 Wave3 Wave0 Wave1 Wave2 Wave3 error3 Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 error3 Wave1 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave3 Wave3 Wave1 Wave1 Wave2 Wave3 error Wave0 Wave1 Wave2 Wave2 Wave3 Wave3 Wave1 Wave2 Wave3 error0 < = GelombangC6; Gelombang1 <= "0000000000"; Gelombang2 <= "0000000000"; Wave3 Wave1 <= WaveC6; Gelombang2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Ralat Wave3 Wave3 Wave1 <= "0000000000"; Gelombang2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Ralat Wave3 Wave3 <= '1'; kes akhir; tamat sekiranya; tamat sekiranya; proses akhir; ------------- penambah gelombang sinus -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- menjadikan gelombang sinus positif untuk pwm --------------------- positiveWaveSum <= bukan WaveSum (9) & WaveSum (8 ke bawah 0); ------------- Penjana PWM --------------------- proses (CLK) - kiraan berubah: tidak ditandatangani (1 ke 0): = to_unsigned (0, 2); mulakan jika (meningkat_kebangkitan (CLK)) maka --kira: = hitung + 1; --jika (hitung = ke_tidak ditandatangani (4, 2)) kemudian --kira: = ke_unsigned (0, 2); --if (PWM = to_ if (PWM <ping_length) maka keluarkan <= '1'; output lain <= '0'; tamat jika; PWM <= PWM + 1; ping_length <= unsigned (positiveWaveSum); --end if; end if; end process; end Behavioral;

4 Pemilih Catatan Bahagian paling sukar dalam projek ini ialah memilih hanya empat frekuensi. Kami melakukannya dengan pernyataan IF lotta keseluruhan, dan kami menggunakan isyarat dan bukannya pemboleh ubah sehingga prosesnya dapat disimulasikan dan disebug. Kami mencuba kaedah lain menggunakan pemboleh ubah dan gelung UNTUK, tetapi mengalami kesilapan masa jalan. Oleh itu, pada akhirnya, kami memutuskan bahawa jika ia berfungsi, kami akan membiarkannya. Tidak betulkan apa yang tidak pecah amirit?

Keempat gelombang output dilabel Wave0, Wave1, Wave2, Wave3 - inilah yang akan ditambah bersama untuk membentuk output akhir.

Melihat kodnya, anda akan melihat sekumpulan isyarat berlabel C4, Cs4, D4, Ds4, dll. Ini adalah isyarat 5-bit yang mengambil pencetus yang sesuai dari O4 (oktaf 4) atau O5 (oktaf 5) dan membuatnya 5-bit untuk penambahan.

Seterusnya pemboleh ubah cntC4, cntCs4, dll menunjukkan berapa banyak nota yang lebih rendah daripada nota sasaran yang telah dimainkan, termasuk nota sasaran. Contohnya, jika C4, E4, G4, A # 4, dan D5 dimainkan (kord C9) cntC4 akan menjadi 1, cntE4 akan menjadi 2, cntG4 akan menjadi 3, dll.

Kemudian, setiap kali nota dimainkan, kiraan untuk nota sasaran akan diperiksa untuk melihat di mana untuk menghubungkan isyarat nota. Sebagai contoh, jika nota D5 dimainkan (yang bermaksud O5 (2) tinggi) dan cntD5 adalah 3, maka pada masa ini terdapat 3 nota yang dimainkan, dengan 2 nota lebih rendah dari D5, jadi kami akan menghubungkan gelombangD5 ke Wave2 (gelombang ketiga pengiraan isyarat dari Wave0). Sebagai alternatif, jika cntD5 adalah 5, pada masa ini terdapat 5 nota yang dimainkan, dengan 4 nota lebih rendah daripada D5, jadi kami akan membiarkan waveD5 tergantung dan tidak melakukan apa-apa dengannya.

Penyataan IF kemudian diulang untuk merangkumi kes-kes untuk semua 25 nota.

Penambah Amplitudo

Setelah 4 gelombang terendah dipilih, kita harus menambahkannya bersama. Sebab kita hanya akan menambah empat nota adalah kerana idea PWM yang kita gunakan untuk output kita hanya boleh mempunyai resolusi tertentu sehingga PWM berjalan terlalu perlahan dan pembesar suara akan mula mengambil gelombang persegi PWM. Sebagai contoh, jika kita menggunakan resolusi 8192 (13 bit), masing-masing 8192 titik tersebut harus sesuai dengan kelebihan jam onboard yang meningkat. Jadi, 100MHz / 8192 = 12.2kHz, yang berada dalam jarak pendengaran manusia.

Penambahan amplitud sebenarnya adalah sangat sederhana, anda hanya perlu memastikan ia boleh berjalan dengan pantas.

Keluaran PWM

Kitaran tugas PWM akan mewakili amplitud gelombang output kami pada masa itu. Sebagai contoh, jika kita mempunyai rentang amplitud 0 hingga 128, 0 akan menjadi kitaran tugas 0%, 64 akan menjadi 50%, 128 akan menjadi 100%, dll. PWM ini akan berjalan dengan sangat pantas (milik kita adalah 97.6 kHz), begitu pantas sehingga pembesar suara tidak akan mengenali gelombang persegi individu dan sebaliknya melihat voltan purata, mewujudkan isyarat "analog" kami.

Fail Kekangan

Anda mungkin menghubungkan perkakasan anda dengan cara yang berbeza, jadi pastikan fail kekangan sesuai.

Langkah 5: Muat turun Kod

Berikut adalah kod, baik dalam format.txt dan.vhd untuk Vivado. Wave_Generator adalah sub-modul penjana gelombang, dan Two_Octave_Synth adalah modul teratas dengan yang lain.

Disyorkan: