Daftar Isi:

Basys3 FPGA Digital Audio Synthesizer: 5 Langkah
Basys3 FPGA Digital Audio Synthesizer: 5 Langkah

Video: Basys3 FPGA Digital Audio Synthesizer: 5 Langkah

Video: Basys3 FPGA Digital Audio Synthesizer: 5 Langkah
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

Synthesizer keyboard gelombang sinus digital ini akan mengambil input pengguna melalui serangkaian sakelar sesaat yang ditata seperti keyboard dan mengeluarkan gelombang audio melalui speaker. Berdasarkan input pengguna, perangkat akan menghasilkan gelombang sinus berbagai frekuensi dari C4 hingga C6. Pengguna dapat memasukkan nada dari C4 hingga C6 (total 25 nada), dan hingga empat tuts pada saat yang bersamaan -- jika lebih dari empat tuts ditekan, empat nada terendah akan dimainkan.

Proyek ini dilakukan oleh Ryan Morris dan Mavis Tsoi untuk kelas Desain Digital Cal Poly CPE 133 kami:)

Langkah 1: Teori

Papan FPGA hanya dapat mengeluarkan sinyal digital. Dengan kata lain, hanya dapat menghasilkan tegangan tinggi (3.3V) atau tegangan rendah (0V). Namun, sinyal audio analog dan dapat memiliki banyak kenaikan tegangan. Untuk menyiasatinya, kita akan menggunakan sinyal PWM (modulasi lebar pulsa) untuk meniru gelombang analog. Jika Anda tidak tahu apa itu PWM, lihat ini:

Langkah 2: Bahan & Alat

  • Komputer dengan Vivado diinstal
  • Kami akan menggunakan Vivado versi 2017.2
  • Papan FPGA Basys3
  • 25 Saklar Batas SPDT (kami menggunakan ini)
  • 30 kabel jumper (satu ujung jantan, ujung lainnya tidak masalah), 12 inci
  • Pemotong kawat
  • penari telanjang kawat
  • Kawat cadangan untuk menyolder
  • Solder inti resin
  • Besi solder
  • ” soket audio wanita
  • Amplifier/speaker
  • Sesuatu untuk memasang sakelar (kami menggunakan protoboard + kotak kayu)

Langkah 3: Pengaturan Pengkabelan & Perangkat Keras

Pengaturan Pengkabelan & Perangkat Keras
Pengaturan Pengkabelan & Perangkat Keras
Pengaturan Pengkabelan & Perangkat Keras
Pengaturan Pengkabelan & Perangkat Keras
Pengaturan Pengkabelan & Perangkat Keras
Pengaturan Pengkabelan & Perangkat Keras

sistem arsitektur

Lihat Gambar 1: 25 input yang tersedia → Basys3 Board → amplifier & speaker.

Keluaran

Lihat Gambar 2: Basys3 Board → 1/2 Female Audio Jack → Speaker (dengan Amplifier)

Memasukkan

Sambungan pmod pada papan Basys3 harus terhubung ke ground untuk melihat input yang rendah dan tidak akan berfungsi dengan baik jika dibiarkan sebagai rangkaian terbuka. Karena itu, kita harus menggunakan sakelar SPDT untuk semua kunci catatan kita. Sakelar SPDT pada dasarnya memungkinkan pengguna untuk beralih antar sirkuit saat ditekan, jadi kami akan menggunakannya sebagai "tombol" kami untuk memasukkan sinyal rendah (0V) atau tinggi (3.3V) ke papan Basys3.

Setiap sakelar akan memiliki terminal NO (biasanya terbuka) terhubung ke 3.3V, terminal NC (biasanya tertutup) terhubung ke GND, dan terminal COM (umum) terhubung ke input FPGA. Lihat Gambar 3.

Karena kami memiliki 25 sakelar batas, semuanya akan berbagi saluran 3.3V yang sama dan saluran GND yang sama. Kemudian, jalur sinyal dari setiap sakelar batas akan digabungkan dalam kelompok 8 dan dihubungkan ke koneksi pmod pada papan Basys3 menggunakan kabel jumper zip untuk meminimalkan kekacauan monumental yang akan kita buat. Lihat Gambar 4 atau contoh dari delapan kunci pertama.

Langkah 4: Pengaturan VHDL (Vivado)

Pengaturan VHDL (Vivado)
Pengaturan VHDL (Vivado)
Pengaturan VHDL (Vivado)
Pengaturan VHDL (Vivado)

Generator gelombang sinus dan generator PWM pertama diuji untuk memastikan konsep kami bekerja, kemudian input limiter dan amplitudo adder/shifter diintegrasikan. Detail fungsi dan I/O dari masing-masing blok proses seperti yang ditunjukkan pada Gambar. Kode ditampilkan di bawah, tetapi juga dilampirkan sebagai file VHD dan txt. Jika ada perbedaan, pergi dengan file VHD.

BTW: kita mungkin seharusnya membuat baris kita lebih pendek tetapi penyematan kode pada Instructables juga ternyata cukup mengganggu untuk ditangani, jadi jaraknya bukan yang terbesar dan tidak ada penyorotan sintaks. Jika Anda memiliki Vivado dan ingin mengikuti kodenya, kami sangat menyarankan Anda untuk mengunduh file saja.

Pertama, mari kita lihat modul Sine Wave Generator.

perpustakaan IEEE; gunakan IEEE. STD_LOGIC_1164. ALL; gunakan IEEE. NUMERIC_STD. ALL; entitas Wave_Generator adalah Port (Pemicu: di STD_LOGIC; -- Tekan tombol Freq_Cnt: di STD_LOGIC_VECTOR(15 turun hingga 0); -- Nilai penghitung = 100MHz / (Catatan Frekuensi*64 Divisi Gelombang Sinus) (dibulatkan ke angka terdekat) -- berganti nama dari Freq wavegenCLK: di STD_LOGIC; -- Basys3 100MHz CLK WaveOut: keluar STD_LOGIC_VECTOR(9 ke bawah 0)); -- Amplitudo bertanda dari Wave_Generator akhir gelombang; arsitektur Perilaku Wave_Generator adalah sinyal i: integer range 0 sampai 64:= 0; -- indeks amplitudo bank memori tipe memory_type adalah larik (0 hingga 63) dari rentang bilangan bulat -64 hingga 63; -- buat bank memori (ROM) untuk menyimpan nilai amplitudo -- apakah ini RAM atau ROM hanya ingin tahu… amplitudo sinyal: 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); -- amplitudo memori bank untuk proses awal gelombang sinus (wavegenCLK, Trigger) variabel counter: unsigned (15 downto 0):= to_unsigned(0, 16); -- penghitung pembagi jam, berganti nama dari hitungan1 mulai if (rising_edge(wavegenCLK)) lalu if (Pemicu = '1') maka -- tombol ditekan penghitung:= penghitung + 1; if (counter = unsigned(Freq_Cnt)) then -- Freq_Cnt = 100Mhz / (perhatikan freq * 64 pembagian gelombang sinus) -- reset counter dan tetapkan data amplitudo ke output counter:= to_unsigned(0, 16); WaveOut <= STD_LOGIC_VECTOR (untuk_ditandatangani(amplitudo(i), 10)); -- kenaikan i untuk bacaan berikutnya i <= i + 1; -- reset i jika satu gelombang sinus telah selesai jika (i = 63) maka i <= 0; berakhir jika; berakhir jika; -- (counter = unsigned(Freq_Cnt)) else -- key tidak ditekan -- reset output, indeks amplitudo, dan counter WaveOut <= "0000000000"; saya <= 0; penghitung:= to_unsigned(0, 16); --output Amplitudo = -64 saat tidak ada nada yang dimainkan akhiri jika; -- (Pemicu = '1') berakhir jika; -- (rising_edge(CLK)) proses akhir; akhir Perilaku;

Kami akan menghasilkan gelombang sinus digital di Basys3 dengan menggunakan jam internal dan ROM. ROM ini akan menyimpan 64 nilai yang mewakili 64 amplitudo pada gelombang sinus. Lihat Gambar 1. 64 nilai yang kami gunakan meniru gelombang sinus dengan resolusi yang cukup bagus.

Menggunakan jam internal, kami menghitung ke nilai yang mewakili kecepatan jam dibagi dengan frekuensi gelombang yang kami inginkan dan 64: Clk div = 100MHz / (Freq * 64) Setiap kali penghitung kami mencapai nilai itu, kami memanggil nomor dari ROM dan mengirimkannya dari modul pembangkit gelombang kami. Frekuensi gelombang kita akan tergantung pada seberapa cepat kita menyebut amplitudo ini.

Kami akan memiliki 25 sub-modul, masing-masing terkait dengan satu frekuensi/not.

Berikut sisa kode yang memanggil modul Sine Wave Generator:

perpustakaan IEEE; gunakan IEEE. STD_LOGIC_1164. ALL; gunakan IEEE. NUMERIC_STD. ALL; entitas 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); akhir Dua_Octave_Synth; Perilaku arsitektur Two_Octave_Synth adalah komponen Wave_Generator adalah Port (Pemicu: di STD_LOGIC; Freq_Cnt: di STD_LOGIC_VECTOR(15 turun ke 0); wavegenCLK: di STD_LOGIC; WaveOut: keluar STD_LOGIC_VECTOR(9 turun ke 0)); komponen akhir; ---------------------------- sinyal keluaran dari generator gelombang ------------------ ----- 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: ditandatangani (9 hingga 0); --------------------------------untuk logika pemilihan nada-------------- ------ 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: unsigned(4 sampai 0); sinyal cntC4, cntCs4, cntD4, cntDs4, cntE4, cntF4, cntFs4, cntG4, cntGs4, cntA4, cntAs4, cntB4, cntC5, cntCs5, cntD5, cntDs5, cntE5, cntF5, cntFs5, cntFs5, cntG5, cnt: unsigned(4 ke 0); kesalahan sinyal: STD_LOGIC; -----------------------------------untuk menambahkan gelombang sinus----------- --------------- sinyal Wave0, Wave1, Wave2, Wave3: ditandatangani (9 hingga 0); --sinyal dari sinyal keluaran modul Wave Generator WaveSum: STD_LOGIC_VECTOR(9 sampai 0); --sinyal untuk penjumlahan gelombang sinus (pujian 2 -512 hingga 511) sinyal positiveWaveSum: STD_LOGIC_VECTOR(9 ke bawah 0); --unsigned 0 hingga 1023, untuk digunakan dalam generator PWM -----------------------------------untuk menghasilkan PWM ------------------------------- sinyal ping_length: unsigned (9 downto 0):= unsigned(positiveWaveSum); --signal off_length: unsigned (6 downto 0):= to_unsigned(127, 7) - unsigned(WAVE); sinyal PWM: unsigned (9 downto 0):= to_unsigned(0, 10); mulai Note_C4: Peta port Wave_Generator (Pemicu => O4(0), Freq_Cnt => X"1755", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveC4; --5973, 261,63 Hz Note_Cs4: Peta port Wave_Generator (Pemicu => O4(1), Freq_Cnt => X"1606", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveCs4;--5638, 277,18 Hz Note_D4: Peta port Wave_Generator (Pemicu => O4(2), Freq_Cnt => X"14C9", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveD4; --5321, 293.66 Hz Note_Ds4: Peta port Wave_Generator (Pemicu => O4(3), Freq_Cnt => X"139F", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveDs4;--5023, 311.13 Hz Note_E4: Peta port Wave_Generator (Pemicu => O4(4), Freq_Cnt => X"1285", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveE4; --4741, 329.63 Hz Note_F4: Peta port Wave_Generator (Pemicu => O4(5), Freq_Cnt => X"117B", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveF4); --4475, 349,23 Hz Note_Fs4: Peta port Wave_Generator (Pemicu => O4(6), Freq_Cnt => X"1080", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveFs4;--4224, 369,99 Hz Note_G4: Peta port Wave_Generator (Pemicu => O4(7), Freq_Cnt => X"0F92", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveG4; --3986, 392.00 Hz Note_Gs4: Peta port Wave_Generator (Pemicu => O4(8), Freq_Cnt => X"0EB3", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveGs4;--3763, 415.30 Hz Note_A4: Peta port Wave_Generator (Pemicu => O4(9), Freq_Cnt => X"0DE0", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveA4; --3552, 440.00 Hz Note_As4: Peta port Wave_Generator (Pemicu => O4(10), Freq_Cnt => X"0D18", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveAs4;--3352, 466.16 Hz Note_B4: Peta port Wave_Generator (Pemicu => O4(11), Freq_Cnt => X"0C5C", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveB4; --3164, 493,88 Hz -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: Peta port Wave_Generator (Pemicu => O5(0), Freq_Cnt => X"0BAB", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveC5); --2987, 523.25 Hz Note_Cs5: Peta port Wave_Generator (Pemicu => O5(1), Freq_Cnt => X"0B03", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveCs5;--2819, 554.37 Hz Note_D5: Peta port Wave_Generator (Pemicu => O5(2), Freq_Cnt => X"0A65", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveD5); --2661, 587,33 Hz Note_Ds5: Peta port Wave_Generator (Pemicu => O5(3), Freq_Cnt => X"09D0", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveDs5;--2512, 622.25 Hz Note_E5: Peta port Wave_Generator (Pemicu => O5(4), Freq_Cnt => X"0943", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveE5; --2371, 659.25 Hz Note_F5: Peta port Wave_Generator (Pemicu => O5(5), Freq_Cnt => X"08Be", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveF5); --2238, 698.46 Hz Note_Fs5: Peta port Wave_Generator (Pemicu => O5(6), Freq_Cnt => X"0840", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveFs5;--2112, 739.99 Hz Note_G5: Peta port Wave_Generator (Pemicu => O5(7), Freq_Cnt => X"07CA", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveG5; --1994, 783.99 Hz Note_Gs5: Peta port Wave_Generator (Pemicu => O5(8), Freq_Cnt => X"075A", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveGs5;--1882, 830.61 Hz Note_A5: Peta port Wave_Generator (Pemicu => O5(9), Freq_Cnt => X"06F0", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveA5); --1776, 880.00 Hz Note_As5: Peta port Wave_Generator (Pemicu => O5(10), Freq_Cnt => X"068C", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveAs5;--1676, 932.33 Hz Note_B5: Peta port Wave_Generator (Pemicu => O5(11), Freq_Cnt => X"062E", wavegenCLK => CLK, ditandatangani (WaveOut) => WaveB5; ---1582, 987.77 Hz Note_C6: Peta port Wave_Generator (Pemicu => O5(12), Freq_Cnt => X"05D6", wavegenCLK => CLK, ditandatangani(WaveOut) => WaveC6); ---1494, 1046,5 Hz ------------ logika pemilihan not ------------ 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; Pilihan: 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) dimulai jika (cntC6 = "000000") kemudian ---------------jika tidak ada sinyal yang dihasilkan Wave0 <= "0000000000"; Gelombang1 <= "0000000000"; Gelombang2 <= "0000000000"; Gelombang3 <= "0000000000"; lain jika (O4(0) = '1') maka -------------------catatan C4 memainkan Wave0 Wave0 Wave1 error Wave0 Wave1 Wave2 error Wave0 Wave1 Wave2 Wave3 error Wave0 Wave1 Gelombang2 Kesalahan Gelombang3 Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang2 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Kesalahan Gelombang2 Gelombang3 Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 Gelombang1 Gelombang2 Gelombang3 kesalahan Gelombang0 < = GelombangC6; Gelombang1 <= "0000000000"; Gelombang2 <= "0000000000"; Gelombang3 Gelombang1 <= GelombangC6; Gelombang2 <= "0000000000"; Gelombang3 Gelombang2 <= GelombangC6; Gelombang3 Kesalahan gelombang3 Gelombang1 <= "0000000000"; Gelombang2 <= "0000000000"; Gelombang3 Gelombang2 <= "0000000000"; Gelombang3 Gelombang3 kesalahan <= '1'; kasus akhir; berakhir jika; berakhir jika; proses akhir; ------------- penambah gelombang sinus -------------------- WaveSum <= STD_LOGIC_VECTOR(Wave0 + Wave1 + Wave2 + Wave3); --------- membuat gelombang sinus positif untuk pwm--------------------- positiveWaveSum <= bukan WaveSum(9) & WaveSum(8 turun hingga 0); ------------- Generator PWM --------------------- proses (CLK) --jumlah variabel: tidak ditandatangani (1 hingga 0):= to_unsigned(0, 2); mulai if (rising_edge(CLK)) lalu --count:= count + 1; --if (count = to_unsigned(4, 2)) maka --count:= to_unsigned(0, 2); --if (PWM = to_ if (PWM < ping_length) maka output <= '1'; else output <= '0'; end if; PWM <= PWM + 1; ping_length <= unsigned(positiveWaveSum); --end jika; akhir jika; akhir proses; akhir Perilaku;

4 Note Selector Bagian tersulit dari proyek ini adalah memilih hanya empat frekuensi. Kami melakukannya dengan seluruh pernyataan IF lotta, dan kami menggunakan sinyal alih-alih variabel sehingga prosesnya dapat disimulasikan dan di-debug. Kami mencoba metode lain menggunakan variabel dan perulangan FOR, tetapi mengalami kesalahan run-time. Jadi, pada akhirnya, kami memutuskan bahwa jika berhasil, kami akan membiarkannya. Jangan perbaiki apa yang tidak rusak amirite?

Keempat gelombang keluaran diberi label Wave0, Wave1, Wave2, Wave3 -- inilah yang akan ditambahkan bersama untuk membentuk keluaran akhir.

Melihat kodenya, Anda akan melihat sekelompok sinyal berlabel C4, Cs4, D4, Ds4, dll. Ini adalah sinyal 5-bit yang mengambil pemicu yang sesuai dari O4 (oktaf 4) atau O5 (oktaf 5) dan membuatnya 5-bit untuk menambahkan.

Selanjutnya variabel cntC4, cntCs4, dll mewakili berapa banyak nada yang lebih rendah dari nada target yang telah dimainkan, termasuk nada target. Misalnya, jika C4, E4, G4, A#4, dan D5 dimainkan (kord C9), cntC4 akan menjadi 1, cntE4 akan menjadi 2, cntG4 akan menjadi 3, dst.

Kemudian, setiap kali sebuah not dimainkan, hitungan untuk not target akan diperiksa untuk melihat ke mana harus mengaitkan sinyal not tersebut. Misalnya, jika nada D5 dimainkan (yang berarti O5(2) tinggi) dan cntD5 adalah 3, maka saat ini ada 3 nada yang dimainkan, dengan 2 nada lebih rendah dari D5, jadi kita akan mengaitkan waveD5 ke Wave2 (gelombang ketiga penghitungan sinyal dari Wave0). Atau, jika cntD5 adalah 5, maka saat ini ada 5 nada yang dimainkan, dengan 4 nada lebih rendah dari D5, jadi kita akan membiarkan waveD5 menggantung dan tidak melakukan apa pun dengannya.

Pernyataan IF kemudian diulang untuk mencakup kasus untuk semua 25 catatan.

Penambah Amplitudo

Setelah 4 gelombang terendah dipilih, kita harus menjumlahkannya. Alasan kami hanya akan menambahkan empat nada bersama adalah karena ide PWM yang kami gunakan untuk output kami hanya dapat memiliki resolusi tertentu sampai PWM berjalan terlalu lambat dan speaker akan mulai mengambil gelombang persegi PWM. Misalnya, jika kita menggunakan resolusi 8192 (13 bit), masing-masing dari 8192 poin tersebut harus sesuai dengan tepi naik jam onboard. Jadi, 100MHz / 8192 = 12.2kHz, yang termasuk dalam jangkauan pendengaran manusia.

Penambahan amplitudo sebenarnya sangat sederhana, Anda hanya perlu memastikannya dapat berjalan sangat cepat.

Keluaran PWM

Siklus tugas PWM akan mewakili amplitudo gelombang keluaran kami pada saat itu. Misalnya, jika kita memiliki rentang amplitudo 0 hingga 128, 0 akan menjadi siklus kerja 0%, 64 akan menjadi 50%, 128 akan menjadi 100%, dll. PWM ini akan berjalan sangat cepat (milik kita adalah 97,6 kHz), begitu cepat sehingga pembicara tidak akan mengenali gelombang persegi individu dan malah melihat tegangan rata-rata, menciptakan sinyal "analog" kami.

File Kendala

Anda mungkin telah menghubungkan perangkat keras Anda secara berbeda, jadi pastikan file kendala cocok.

Langkah 5: Unduhan Kode

Di bawah ini adalah kodenya, baik dalam format.txt maupun.vhd untuk Vivado. Wave_Generator adalah sub-modul pembangkit gelombang, dan Two_Octave_Synth adalah modul teratas dengan yang lainnya.

Direkomendasikan: