Სარჩევი:

Basys3 FPGA ციფრული აუდიო სინთეზატორი: 5 ნაბიჯი
Basys3 FPGA ციფრული აუდიო სინთეზატორი: 5 ნაბიჯი

ვიდეო: Basys3 FPGA ციფრული აუდიო სინთეზატორი: 5 ნაბიჯი

ვიდეო: Basys3 FPGA ციფრული აუდიო სინთეზატორი: 5 ნაბიჯი
ვიდეო: n-Discovery - #Star #ომები #ეპიზოდი #48 #სპექტრის#back to basics #გლუვი 2024, ივლისი
Anonim
Image
Image
Basys3 FPGA ციფრული აუდიო სინთეზატორი
Basys3 FPGA ციფრული აუდიო სინთეზატორი
Basys3 FPGA ციფრული აუდიო სინთეზატორი
Basys3 FPGA ციფრული აუდიო სინთეზატორი

ეს ციფრული სინუსური ტალღის კლავიატურის სინთეზატორი მიიღებს მომხმარებლის შეყვანას კლავიატურის მსგავსად განლაგებული მომენტალური გადამრთველების მეშვეობით და გამოსცემს აუდიო ტალღას სპიკერის საშუალებით. მომხმარებლის შეყვანის საფუძველზე, მოწყობილობა გამოიმუშავებს სხვადასხვა სიხშირის სინუსურ ტალღებს C4– დან C6– მდე. მომხმარებელს შეუძლია შეიტანოს ჩანაწერები C4– დან C6– მდე (სულ 25 ნოტა) და ერთდროულად ოთხამდე ღილაკი - თუ ოთხზე მეტ ღილაკს დააჭერთ, ოთხი ყველაზე დაბალი ტონი დაიკვრება.

ეს პროექტი გაკეთდა რაიან მორისისა და მევის ცოის მიერ ჩვენი Cal Poly CPE 133 ციფრული დიზაინის კლასისთვის:)

ნაბიჯი 1: თეორია

FPGA დაფას შეუძლია გამოუშვას მხოლოდ ციფრული სიგნალები. სხვა სიტყვებით რომ ვთქვათ, მას შეუძლია წარმოქმნას მხოლოდ მაღალი (3.3V) ძაბვა ან დაბალი (0V) ძაბვა. ამასთან, აუდიო სიგნალები არის ანალოგური და შეიძლება ჰქონდეს უსასრულოდ ბევრი ზრდა ძაბვაში. ამის გადასალახად, ჩვენ გამოვიყენებთ PWM (პულსის სიგანის მოდულაციას) სიგნალს ანალოგიური ტალღის იმიტირებისთვის. თუ არ იცით რა არის PWM, შეამოწმეთ ეს:

ნაბიჯი 2: ინგრედიენტები და ინსტრუმენტები

  • დაინსტალირებული კომპიუტერი Vivado– ით
  • ჩვენ ვიყენებთ Vivado ვერსიას 2017.2
  • Basys3 FPGA დაფა
  • 25 SPDT ლიმიტის გადამრთველი (ჩვენ გამოვიყენეთ ეს)
  • 30 მხტუნავი მავთული (ერთი ბოლო მამაკაცი, მეორე ბოლო არ აქვს მნიშვნელობა), 12 ინჩი
  • Მავთულის საჭრელები
  • მავთულის სტრიპტიზატორები
  • სათადარიგო მავთული soldering
  • ფისოვანი ბირთვიანი შემდუღებელი
  • გასაყიდი რკინა
  • ¼”ქალის აუდიო ბუდე
  • გამაძლიერებელი/სპიკერი
  • გადამრთველების დასაყენებლად (ჩვენ გამოვიყენეთ პროტობორდი + ხის ყუთი)

ნაბიჯი 3: გაყვანილობა და აპარატურის დაყენება

გაყვანილობა და აპარატურის დაყენება
გაყვანილობა და აპარატურის დაყენება
გაყვანილობა და აპარატურის დაყენება
გაყვანილობა და აპარატურის დაყენება
გაყვანილობა და აპარატურის დაყენება
გაყვანილობა და აპარატურის დაყენება

სისტემური არქიტექტურა

იხილეთ სურათი 1: 25 ხელმისაწვდომი საშუალებები → Basys3 Board → გამაძლიერებელი და სპიკერი.

გამომავალი

იხილეთ სურათი 2: Basys3 დაფა → 1/2 ქალი აუდიო ჯეკი → სპიკერი (გამაძლიერებლით)

შეყვანა

Pmod კავშირები Basys3 დაფაზე უნდა იყოს დაკავშირებული მიწასთან, რათა ნახოთ დაბალი შეყვანა და არ იმუშავებს სწორად თუ დარჩება ღია წრედ. ამის გამო, ჩვენ უნდა გამოვიყენოთ SPDT კონცენტრატორები ჩვენი ყველა შენიშვნის გასაღებისთვის. SPDT გადამრთველი ძირითადად მომხმარებელს საშუალებას აძლევს გადართოს სქემებს შორის დაჭერისას, ასე რომ ჩვენ გამოვიყენებთ მათ როგორც ჩვენს „ღილაკებს“Basys3 დაფაზე დაბალი (0V) ან მაღალი (3.3V) სიგნალების შესაყვანად.

თითოეულ გადამრთველს ექნება NO (ჩვეულებრივ გახსნილი) ტერმინალი 3.3V- თან, NC (ჩვეულებრივ დახურული) ტერმინალი GND- თან და COM (საერთო) ტერმინალი FPGA შეყვანასთან. იხილეთ სურათი 3.

რადგან ჩვენ გვაქვს 25 ლიმიტიანი გადამრთველი, ისინი ყველა იზიარებენ საერთო 3.3V ხაზს და საერთო GND ხაზს. შემდეგ, სიგნალის ხაზი თითოეული ლიმიტის გადამრთველიდან შეფუთული იქნება 8 -კაციან ჯგუფებში და დაუკავშირდება Basmod3 დაფაზე არსებულ pmod კავშირებს zippable jumper მავთულის გამოყენებით, რათა მინიმუმამდე დავიყვანოთ ჩვენი მონუმენტური არეულობა. იხილეთ სურათი 4 ან პირველი რვა გასაღების მაგალითი.

ნაბიჯი 4: VHDL დაყენება (Vivado)

VHDL დაყენება (Vivado)
VHDL დაყენება (Vivado)
VHDL დაყენება (Vivado)
VHDL დაყენება (Vivado)

სინუსური ტალღის გენერატორი და PWM გენერატორი პირველად იქნა შემოწმებული იმისათვის, რომ დარწმუნებული ყოფილიყო, რომ ჩვენი კონცეფცია მუშაობს, შემდეგ კი ინტეგრირებული იყო შეყვანის შემზღუდველი და ამპლიტუდის შემმჩნეველი/გადამრთველი. თითოეული პროცესის ბლოკის ფუნქციის და I/O დეტალები მოცემულია ფიგურაში. კოდი ნაჩვენებია ქვემოთ, მაგრამ ასევე ერთვის VHD და txt ფაილებს. თუ არსებობს შეუსაბამობები, გადადით VHD ფაილებთან.

BTW: ჩვენ ალბათ უნდა გაგვეკეთებინა ჩვენი ხაზები უფრო მოკლე, მაგრამ Instructables– ზე ჩაშენებული კოდი ასევე საკმაოდ შემაშფოთებელი აღმოჩნდა, ამიტომ ინტერვალი არ არის უდიდესი და არ არსებობს სინტაქსის ხაზგასმა. თუ თქვენ გაქვთ Vivado და გსურთ დაიცვას კოდი, ჩვენ გირჩევთ, უბრალოდ გადმოწეროთ ფაილი.

პირველი, მოდით შევხედოთ Sine Wave Generator მოდულს.

ბიბლიოთეკა IEEE; გამოიყენეთ IEEE. STD_LOGIC_1164. ALL; გამოიყენეთ IEEE. NUMERIC_STD. ALL; ერთეულის Wave_Generator არის პორტი (გამომწვევი: STD_LOGIC; - გასაღები პრეს Freq_Cnt: STD_LOGIC_VECTOR (15 ქვემოთ 0); - მრიცხველის მნიშვნელობა = 100 MHz / (შენიშვნის სიხშირე*64 სინუსური ტალღის განყოფილება) (მრგვალი უახლოეს რიცხვამდე) - გადაარქვა სახელი Freq wavegenCLK: STD_LOGIC; - Basys3 100MHz CLK WaveOut: გარეთ STD_LOGIC_VECTOR (9 ქვემოთ 0 -ზე)); - ტალღის ბოლოს ტალღის გენერატორი ამპლიტუდა; Wave_Generator- ის არქიტექტურა არის სიგნალი i: მთელი დიაპაზონი 0 -დან 64 -მდე: = 0; -ამპლიტუდის მეხსიერების ბანკის ინდექსი ტიპის memory_type არის მასივი (0 -დან 63 -მდე) მთელი დიაპაზონის -64 -დან 63 -მდე; - შექმენით მეხსიერების ბანკი (ROM) ამპლიტუდის მნიშვნელობების შესანარჩუნებლად- ეს RAM ან ROM უბრალოდ მაინტერესებს … სიგნალის ამპლიტუდა: 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); - ამპლიტუდის მეხსიერების ბანკი სინუსური ტალღისთვის პროცესის დასაწყებად (wavegenCLK, Trigger) ცვლადი მრიცხველი: ხელმოუწერელი (15 ქვემოთ 0): = to_unsigned (0, 16); - საათის გამყოფის მრიცხველი, სახელწოდებით count1 იწყება if (იზრდება თუ (მრიცხველი = ხელმოუწერელი (Freq_Cnt)) მაშინ - Freq_Cnt = 100Mhz / (შენიშვნა სიხშირე * სინუსური ტალღის 64 განყოფილება) - გადააყენეთ მრიცხველი და მიანიჭეთ ამპლიტუდის მონაცემები გამომავალ მრიცხველს: = to_sunsigned (0, 16); WaveOut <= STD_LOGIC_VECTOR (ხელმოწერილი (ამპლიტუდა (i), 10)); - i დამატება შემდეგი კითხვისთვის i <= i + 1; - გადატვირთვა, თუ ერთი სინუსური ტალღა დასრულებულია, თუ (i = 63) მაშინ i <= 0; დაასრულე თუ; დაასრულე თუ; - (counter = ხელმოუწერელი (Freq_Cnt)) სხვა- გასაღები არ არის დაჭერილი- გადატვირთეთ გამომავალი, ამპლიტუდის ინდექსი და მრიცხველი WaveOut <= "0000000000"; მე <= 0; მრიცხველი: = ხელმოუწერელი (0, 16); -გამოყვანის ამპლიტუდა = -64 როდესაც შენიშვნა არ არის დაკრული, თუ; - (გააქტიურება = '1') დასრულდება თუ; - (ამწევის ზღვარი (CLK)) დასრულების პროცესი; დასრულება ქცევითი;

ჩვენ შევქმნით ციფრულ სინუსის ტალღას Basys3– ში შიდა საათის და ROM– ის გამოყენებით. ეს ROM ინახავს 64 მნიშვნელობას, რომელიც წარმოადგენს 64 ამპლიტუდას სინუსურ ტალღაზე. იხილეთ სურათი 1. 64 მნიშვნელობა, რომელსაც ჩვენ ვიყენებთ, ემორჩილება სინუსის ტალღას საკმაოდ კარგი გარჩევადობით.

შიდა საათის გამოყენებით, ჩვენ ვითვლით მნიშვნელობას, რომელიც წარმოადგენს საათის სიჩქარეს გაყოფილი ტალღის სიხშირეზე და 64: Clk div = 100MHz / (სიხშირე * 64) ყოველ ჯერზე, როდესაც ჩვენი მრიცხველი მიაღწევს ამ მნიშვნელობას, ჩვენ ვიძახებთ რიცხვს ROM და გააგზავნეთ ჩვენი ტალღის გენერატორის მოდულიდან. ჩვენი ტალღის სიხშირე იქნება დამოკიდებული იმაზე, თუ რამდენად სწრაფად ვუწოდებთ ამ ამპლიტუდებს.

ჩვენ გვექნება 25 ქვე-მოდული, თითოეული ასოცირდება ერთ სიხშირესთან/ნოტთან.

აქ არის კოდის დარჩენილი ნაწილი, რომელიც უწოდებს Sine Wave Generator მოდულებს:

ბიბლიოთეკა IEEE; გამოიყენეთ IEEE. STD_LOGIC_1164. ALL; გამოიყენეთ IEEE. NUMERIC_STD. ALL; ერთეული Two_Octave_Synth არის პორტი (CLK: STD_LOGIC– ში; O4: STD_LOGIC_VECTOR– ში (11 ქვემოთ 0 – ზე); O5: STD_LOGIC_VECTOR– ში (12 ქვემოთ 0 – ზე); გამომავალი: STD_LOGIC); დასასრული ორი _ ოქტავა_ სინთჰი; არქიტექტურა ქცევითი Two_Octave_Synth არის კომპონენტი Wave_Generator is Port (Trigger: in STD_LOGIC; Freq_Cnt: in STD_LOGIC_VECTOR (15 ქვემოთ 0); wavegenCLK: in STD_LOGIC; WaveOut: out STD_LOGIC_) დასასრული კომპონენტი; --------------------------- ტალღის გენერატორის სიგნალები ------------------ ----- სიგნალი 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: ხელმოწერილი (9 ქვემოთ 0); -------------------------------- შენიშვნების შერჩევის ლოგიკისთვის -------------- ------ სიგნალი 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: ხელმოუწერელი (4 ქვემოთ 0); სიგნალი 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: ხელმოუწერელი (4 ქვემოთ 0 -ზე); სიგნალის შეცდომა: STD_LOGIC; ---------------------------------------- სინუსური ტალღების დასამატებლად ----------- --------------- სიგნალი Wave0, Wave1, Wave2, Wave3: ხელმოწერილია (9 ქვემოთ 0-ზე); -სიგნალები ტალღის გენერატორის მოდულის გამომავალი სიგნალიდან WaveSum: STD_LOGIC_VECTOR (9 ქვემოთ 0-ზე); -სიგნალი შეჯამებული სინუსური ტალღებისთვის (2 -ის კომპლიმენტი -512 -დან 511 -მდე) სიგნალი დადებითი WaveSum: STD_LOGIC_VECTOR (9 ქვემოთ 0 -ზე); -ხელმოუწერელია 0-დან 1023 წლამდე, PWM გენერატორში გამოსაყენებლად --------------------------------------- PWM გენერირებისთვის ------------------------------- სიგნალის პინგ_ სიგრძე: ხელმოუწერელი (9 ქვემოთ 0): = ხელმოუწერელი (positiveWaveSum); -სიგნალი off_length: ხელმოუწერელი (6 ქვემოთ 0 -ზე): = ხელმოუწერელი (127, 7) -ხელმოუწერელი (ტალღა); სიგნალი PWM: ხელმოუწერელი (9 ქვემოთ 0): = ხელმოუწერელი (0, 10); დაიწყეთ შენიშვნა_C4: Wave_Generator პორტის რუკა (გამომწვევი => O4 (0), Freq_Cnt => X "1755", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveC4); --5973, 261.63 Hz შენიშვნა_Cs4: Wave_Generator პორტის რუკა (გამომწვევი => O4 (1), Freq_Cnt => X "1606", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveCs4);-5638, 277.18 Hz შენიშვნა_D4: Wave_Generator პორტის რუკა (Trigger => O4 (2), Freq_Cnt => X "14C9", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveD4); --5321, 293.66 Hz შენიშვნა_Ds4: Wave_Generator პორტის რუკა (გამომწვევი => O4 (3), Freq_Cnt => X "139F", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveDs4);-5023, 311.13 Hz შენიშვნა_E4: Wave_Generator პორტის რუკა (Trigger => O4 (4), Freq_Cnt => X "1285", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveE4); --4741, 329.63 Hz შენიშვნა_F4: Wave_Generator პორტის რუკა (Trigger => O4 (5), Freq_Cnt => X "117B", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveF4); --4475, 349.23 Hz შენიშვნა_Fs4: Wave_Generator პორტის რუკა (Trigger => O4 (6), Freq_Cnt => X "1080", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveFs4);-4224, 369.99 Hz შენიშვნა_G4: Wave_Generator პორტის რუკა (გამომწვევი => O4 (7), Freq_Cnt => X "0F92", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveG4); --3986, 392.00 Hz შენიშვნა_Gs4: Wave_Generator პორტის რუკა (Trigger => O4 (8), Freq_Cnt => X "0EB3", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveGs4);-3763, 415.30 Hz შენიშვნა_A4: Wave_Generator პორტის რუკა (Trigger => O4 (9), Freq_Cnt => X "0DE0", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveA4); --3552, 440.00 Hz შენიშვნა_As4: Wave_Generator პორტის რუკა (Trigger => O4 (10), Freq_Cnt => X "0D18", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveAs4);-3352, 466.16 Hz შენიშვნა_B4: Wave_Generator პორტის რუკა (Trigger => O4 (11), Freq_Cnt => X "0C5C", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveB4); --3164, 493.88 ჰერცი ------------------------------------------------ ------------------------------------------------------ --------------------------- შენიშვნა_C5: Wave_Generator პორტის რუკა (Trigger => O5 (0), Freq_Cnt => X "0BAB", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveC5); --2987, 523.25 Hz შენიშვნა_Cs5: Wave_Generator პორტის რუკა (გამომწვევი => O5 (1), Freq_Cnt => X "0B03", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveCs5);-2819, 554.37 Hz შენიშვნა_D5: Wave_Generator პორტის რუკა (Trigger => O5 (2), Freq_Cnt => X "0A65", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveD5); --2661, 587.33 ჰერცი შენიშვნა_დს 5: ტალღის გენერატორის პორტის რუკა (გამომწვევი => O5 (3), Freq_Cnt => X "09D0", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveDs5);-2512, 622.25 ჰერცი შენიშვნა_E5: Wave_Generator პორტის რუკა (Trigger => O5 (4), Freq_Cnt => X "0943", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveE5); --2371, 659.25 Hz შენიშვნა_F5: Wave_Generator პორტის რუკა (Trigger => O5 (5), Freq_Cnt => X "08Be", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveF5); --2238, 698.46 Hz შენიშვნა_Fs5: Wave_Generator პორტის რუკა (Trigger => O5 (6), Freq_Cnt => X "0840", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveFs5);-2112, 739.99 Hz Note_G5: Wave_Generator პორტის რუკა (Trigger => O5 (7), Freq_Cnt => X "07CA", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveG5); --1994, 783.99 Hz შენიშვნა_Gs5: Wave_Generator პორტის რუკა (Trigger => O5 (8), Freq_Cnt => X "075A", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveGs5);-1882, 830.61 Hz შენიშვნა_A5: Wave_Generator პორტის რუკა (Trigger => O5 (9), Freq_Cnt => X "06F0", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveA5); --1776, 880.00 Hz შენიშვნა_As5: Wave_Generator პორტის რუკა (Trigger => O5 (10), Freq_Cnt => X "068C", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveAs5);-1676, 932.33 Hz შენიშვნა_B5: Wave_Generator პორტის რუკა (Trigger => O5 (11), Freq_Cnt => X "062E", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveB5); --1582, 987.77 Hz შენიშვნა_C6: Wave_Generator პორტის რუკა (გამომწვევი => O5 (12), Freq_Cnt => X "05D6", wavegenCLK => CLK, ხელმოწერილი (WaveOut) => WaveC6); --1494, 1046.5 Hz ------------ შენიშვნების შერჩევის ლოგიკა ------------ 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; შერჩევა: პროცესი (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) იწყება თუ (cntC6 = "00000") შემდეგ --------------- თუ არ წარმოიქმნება სიგნალები Wave0 <= "0000000000"; ტალღა 1 <= "0000000000"; ტალღა 2 <= "0000000000"; ტალღა 3 <= "0000000000"; სხვა შემთხვევაში თუ (O4 (0) = '1') მაშინ ------------------- შენიშვნა C4 ითამაშა Wave0 Wave0 Wave1 შეცდომა Wave0 Wave1 Wave2 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა ტალღა Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 Wave3 შეცდომა Wave0 Wave1 Wave2 Wave3 შეცდომა ტალღა = WaveC6; ტალღა 1 <= "0000000000"; ტალღა 2 <= "0000000000"; Wave3 Wave1 <= WaveC6; ტალღა 2 <= "0000000000"; Wave3 Wave2 <= WaveC6; Wave3 Wave3 შეცდომა Wave1 <= "0000000000"; ტალღა 2 <= "0000000000"; Wave3 Wave2 <= "0000000000"; Wave3 Wave3 შეცდომა <= '1'; დასასრული საქმე; დაასრულე თუ; დაასრულე თუ; პროცესის დასრულება; ------------- სინუსური ტალღის დამატება -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3); --------- სინუსური ტალღა დადებითი იყოს pwm --------------------- პოზიტიური WaveSum <= არა WaveSum (9) & WaveSum (8 ქვემოთ 0); ------------- PWM გენერატორი --------------------- პროცესი (CLK)-ცვლადი რაოდენობა: ხელმოუწერელი (1 ქვემოთ 0-ზე): = ხელმოუწერელი (0, 2); დავიწყოთ თუ (იზრდება --if (ითვლიან = ხელმოუწერელ (4, 2)) შემდეგ-ითვლიან: = ხელმოუწერელს (0, 2); --if (PWM = to_ if (PWM <ping_length) მაშინ გამომავალი <= '1'; წინააღმდეგ შემთხვევაში გამომავალი <= '0'; დასრულდება თუ; PWM <= PWM + 1; ping_length <= ხელმოუწერელი (positiveWaveSum);-დასასრული თუ; დასრულება თუ; დასრულების პროცესი; დასრულება ქცევითი;

4 შენიშვნის ამომრჩეველი ამ პროექტის ყველაზე რთული ნაწილია მხოლოდ ოთხი სიხშირის შერჩევა. ჩვენ გავაკეთეთ ეს ლოტა IF განცხადებებით და ჩვენ გამოვიყენეთ სიგნალები ცვლადების ნაცვლად, რათა პროცესის სიმულაცია და გამართვა მოხდეს. ჩვენ ვცადეთ სხვა მეთოდები ცვლადების და FOR მარყუჟების გამოყენებით, მაგრამ გაშვებული დროის შეცდომებს წავაწყდით. საბოლოოდ, ჩვენ გადავწყვიტეთ, რომ თუ ის იმუშავებს, მას მარტო დავტოვებთ.არ გაასწორო ის, რაც არ არის გატეხილი ამირიტი?

ოთხი გამომავალი ტალღა არის წარწერით Wave0, Wave1, Wave2, Wave3 - ეს არის ის, რაც დაემატება ერთად, რათა შეიქმნას საბოლოო გამომუშავება.

კოდის დათვალიერებისას თქვენ ნახავთ სიგნალების რამოდენიმე მარკირებას C4, Cs4, D4, Ds4 და ა.შ. ეს არის 5 ბიტიანი სიგნალები, რომლებიც იღებენ შესაბამის გამომწვევს O4 (ოქტავა 4) ან O5 (ოქტავა 5) და ქმნიან მათ 5 ბიტიანი დასამატებლად.

შემდეგ cntC4, cntCs4 და ა.შ ცვლადი წარმოადგენს სამიზნე ნოტზე დაბალ ნოტებს, მათ შორის სამიზნე ნოტს. მაგალითად, თუ ითამაშება C4, E4, G4, A#4 და D5 (C9 აკორდი) cntC4 იქნება 1, cntE4 იქნება 2, cntG4 იქნება 3 და ა.

შემდეგ, როდესაც ნოტი უკრავს, სამიზნე ნოტის რაოდენობა შეისწავლება, რათა დაინახოს, სად უნდა შეაერთოს ნოტის სიგნალი. მაგალითად, თუ D5 შენიშვნა უკრავს (რაც იმას ნიშნავს, რომ O5 (2) არის მაღალი) და cntD5 არის 3, მაშინ ამჟამად 3 ნოტი უკრავს, 2 ნოტით დაბალია ვიდრე D5, ასე რომ ჩვენ wavedu5– ს ვუერთებთ Wave2– ს (მესამე ტალღა სიგნალის დათვლა ტალღადან 0). ალტერნატიულად, თუ cntD5 არის 5, მაშინ ამჟამად 5 ნოტი უკრავს, 4 ნოტით დაბალია ვიდრე D5, ასე რომ ჩვენ უბრალოდ დავტოვებთ waveD5 ჩამოკიდებულს და არაფერს გავაკეთებთ.

IF განცხადებები შემდეგ მეორდება და მოიცავს 25 -ე ჩანაწერს.

ამპლიტუდის ადდერი

მას შემდეგ რაც შეირჩევა ყველაზე დაბალი 4 ტალღა ჩვენ უნდა დავამატოთ ისინი ერთად. მიზეზი, რის გამოც ჩვენ მხოლოდ ოთხ ნოტს დავამატებთ არის ის, რომ PWM იდეას, რომელსაც ჩვენ გამოვიყენებთ, შეიძლება ჰქონდეს მხოლოდ გარკვეული გარჩევადობა, სანამ PWM არ მუშაობს ძალიან ნელა და სპიკერი დაიწყებს PWM კვადრატული ტალღის აღებას. მაგალითად, თუ ჩვენ გამოვიყენებთ გარჩევადობას 8192 (13 ბიტი), თითოეული იმ 8192 პუნქტიდან უნდა შეესაბამებოდეს ბორტ საათის საათის ამომავალ ზღვარს. ასე რომ, 100MHz / 8192 = 12.2kHz, რაც ადამიანის სმენის დიაპაზონშია.

ამპლიტუდების ფაქტობრივი დამატება ძალიან მარტივია, თქვენ უბრალოდ უნდა დარწმუნდეთ, რომ ის მართლაც სწრაფად გადის.

PWM გამომავალი

PWM– ის სამუშაო ციკლი წარმოადგენს იმ მომენტში ჩვენი გამომავალი ტალღის ამპლიტუდას. მაგალითად, თუ ჩვენ გვაქვს ამპლიტუდის დიაპაზონი 0 -დან 128 -მდე, 0 იქნება 0%სამუშაო ციკლი, 64 იქნება 50%, 128 იქნება 100%და ა.შ. ეს PWM იმუშავებს ძალიან სწრაფად (ჩვენი არის 97,6 კჰც), იმდენად სწრაფად, რომ სპიკერი არ ამოიცნობს ცალკეულ კვადრატულ ტალღებს და ნაცვლად შეხედავს საშუალო ძაბვას, შექმნის ჩვენს "ანალოგიურ" სიგნალს.

შეზღუდვების ფაილი

თქვენ შეიძლება სხვაგვარად დააკავშიროთ თქვენი აპარატურა, ასე რომ დარწმუნდით, რომ შეზღუდვების ფაილი ემთხვევა.

ნაბიჯი 5: კოდის გადმოწერა

ქვემოთ მოცემულია კოდი, როგორც.txt ფორმატში, ასევე.vhd Vivado– სთვის. Wave_Generator არის ტალღის გენერატორის ქვე-მოდული, ხოლო Two_Octave_Synth არის ზედა მოდული ყველაფერთან ერთად.

გირჩევთ: