جدول المحتويات:

جهاز المزج الصوتي الرقمي Basys3 FPGA: 5 خطوات
جهاز المزج الصوتي الرقمي Basys3 FPGA: 5 خطوات

فيديو: جهاز المزج الصوتي الرقمي Basys3 FPGA: 5 خطوات

فيديو: جهاز المزج الصوتي الرقمي Basys3 FPGA: 5 خطوات
فيديو: جهاز الصوت الديجيتال . شرح المنشد ياسين باطية ج 1 the t . mix DM20 2024, يوليو
Anonim
Image
Image
جهاز مزج الصوت الرقمي Basys3 FPGA
جهاز مزج الصوت الرقمي Basys3 FPGA
جهاز مزج الصوت الرقمي Basys3 FPGA
جهاز مزج الصوت الرقمي Basys3 FPGA

سيأخذ جهاز المزج الرقمي ذو الموجة الجيبية مدخلات المستخدم عبر سلسلة من المفاتيح اللحظية الموضوعة مثل لوحة المفاتيح وإخراج موجة صوتية عبر مكبر صوت. بناءً على مدخلات المستخدم ، سيقوم الجهاز بتوليد موجات جيبية بترددات مختلفة من C4 إلى C6. يمكن للمستخدم إدخال الملاحظات من C4 حتى C6 (إجمالي 25 ملاحظة) ، وما يصل إلى أربعة مفاتيح في نفس الوقت - إذا تم الضغط على أكثر من أربعة مفاتيح ، فسيتم تشغيل النغمات الأربعة الأقل.

تم تنفيذ هذا المشروع بواسطة Ryan Morris و Mavis Tsoi لفئة التصميم الرقمي Cal Poly CPE 133 الخاصة بنا:)

الخطوة 1: النظرية

يمكن للوحة FPGA إخراج الإشارات الرقمية فقط. بمعنى آخر ، يمكن أن ينتج فقط جهدًا عاليًا (3.3 فولت) أو جهدًا منخفضًا (0 فولت). ومع ذلك ، فإن الإشارات الصوتية تناظرية ويمكن أن تحتوي على عدد لا نهائي من الزيادات في الجهد. للتغلب على هذا ، سنستخدم إشارة PWM (تعديل عرض النبضة) لمحاكاة الموجة التناظرية. إذا كنت لا تعرف ما هو PWM ، فتحقق من ذلك:

الخطوة الثانية: المكونات والأدوات

  • جهاز كمبيوتر مثبت عليه Vivado
  • سنستخدم إصدار Vivado 2017.2
  • مجلس Basys3 FPGA
  • 25 مفتاح حد SPDT (استخدمنا هذه)
  • 30 سلك توصيل (ذكر طرف واحد ، طرف آخر لا يهم) ، 12 بوصة
  • قواطع للاسلاك
  • قواطع الأسلاك
  • سلك احتياطي للحام
  • الراتنج الأساسية اللحيم
  • لحام حديد
  • ¼”مقبس صوت أنثى
  • مكبر للصوت / مكبر الصوت
  • شيء لتركيب المفاتيح (استخدمنا لوح حماية + صندوق خشبي)

الخطوة 3: إعداد الأسلاك والأجهزة

إعداد الأسلاك والأجهزة
إعداد الأسلاك والأجهزة
إعداد الأسلاك والأجهزة
إعداد الأسلاك والأجهزة
إعداد الأسلاك والأجهزة
إعداد الأسلاك والأجهزة

بنية النظام

انظر الشكل 1: 25 مدخلًا متاحًا ← لوحة Basys3 ← مكبر صوت ومكبر صوت.

انتاج |

انظر الشكل 2: لوحة Basys3 → 1/2 مقبس صوت أنثى ← مكبر صوت (مع مكبر للصوت)

مدخل

يجب توصيل وصلات pmod على لوحة Basys3 بالأرض لرؤية مدخل منخفض ولن تعمل بشكل صحيح إذا تركت كدائرة مفتوحة. لهذا السبب ، يتعين علينا استخدام مفاتيح SPDT لجميع مفاتيح الملاحظات الخاصة بنا. يسمح مفتاح SPDT بشكل أساسي للمستخدم بالتبديل بين الدوائر عند الضغط عليه ، لذلك سنستخدمها كـ "أزرار" لإدخال إشارات منخفضة (0 فولت) أو عالية (3.3 فولت) إلى لوحة Basys3.

سيكون لكل محول محطة NO (مفتوحة عادة) متصلة بـ 3.3V ، وطرف NC (مغلق عادة) متصل بـ GND ، وطرف COM (مشترك) متصل بمدخل FPGA. انظر الشكل 3.

نظرًا لأن لدينا 25 مفتاحًا حدًا ، فسيشتركون جميعًا في خط مشترك 3.3 فولت وخط GND مشترك. بعد ذلك ، سيتم تجميع خط الإشارة من كل مفتاح حد في مجموعات من 8 وتوصيله بوصلات pmod على لوحة Basys3 باستخدام أسلاك توصيل قابلة للانزلاق لتقليل الفوضى الهائلة التي سنحدثها. انظر الشكل 4 أو مثال على المفاتيح الثمانية الأولى.

الخطوة 4: إعداد VHDL (Vivado)

إعداد VHDL (Vivado)
إعداد VHDL (Vivado)
إعداد VHDL (Vivado)
إعداد VHDL (Vivado)

تم اختبار مولد الموجة الجيبية ومولد PWM أولاً للتأكد من أن مفهومنا يعمل ، ثم تم دمج محدد الإدخال ومحول السعة / ناقل الحركة. تظهر تفاصيل الوظيفة والإدخال / الإخراج لكل كتلة عملية كما هو موضح في الشكل. يظهر الرمز أدناه ، ولكن يتم إرفاقه أيضًا كملفات VHD و txt. إذا كان هناك تناقضات ، فانتقل إلى ملفات VHD.

راجع للشغل: ربما كان علينا أن نجعل أسطرنا أقصر ، لكن كان تضمين الكود في Instructables أيضًا مزعجًا جدًا للتعامل معه ، لذا فإن التباعد ليس هو الأفضل ولا يوجد تمييز في بناء الجملة. إذا كان لديك Vivado وترغب في اتباع التعليمات البرمجية ، فنحن نوصيك بشدة بتنزيل الملف فقط.

أولاً ، دعنا نلقي نظرة على وحدة مولد الموجة الجيبية.

مكتبة IEEE ؛ استخدم IEEE. STD_LOGIC_1164. ALL ؛ استخدم IEEE. NUMERIC_STD. ALL ؛ الكيان Wave_Generator هو المنفذ (المشغل: في STD_LOGIC ؛ - الضغط على المفتاح Freq_Cnt: في STD_LOGIC_VECTOR (15 لأسفل إلى 0) ؛ - قيمة العداد = 100 ميجا هرتز / (ملاحظة التردد * 64 أقسام موجة جيبية) (تقريب إلى أقرب رقم) - إعادة تسميته من Freq wavegenCLK: في STD_LOGIC ؛ - Basys3 100 ميجا هرتز CLK WaveOut: خارج STD_LOGIC_VECTOR (9 أسفل إلى 0)) ؛ - السعة المميزة لنهاية الموجة Wave_Generator ؛ السلوك المعماري لـ Wave_Generator هو الإشارة i: النطاق الصحيح من 0 إلى 64: = 0 ؛ - مؤشر نوع ذاكرة السعة من نوع Memory_type هو صفيف (من 0 إلى 63) من نطاق عدد صحيح -64 إلى 63 ؛ - إنشاء بنك ذاكرة (ROM) للاحتفاظ بقيم السعة - هل هذه ذاكرة الوصول العشوائي أو ROM تتساءل فقط … سعة الإشارة: نوع الذاكرة: = (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 ، يبدأ إذا (Rising_edge (wavegenCLK)) ثم إذا (Trigger = '1') ثم - يتم الضغط على مفتاح العداد: = counter + 1 ؛ إذا (العداد = غير موقعة (Freq_Cnt)) إذن - Freq_Cnt = 100Mhz / (لاحظ التكرار * 64 قسمًا من الموجة الجيبية) - إعادة تعيين العداد وتعيين بيانات السعة لعداد الإخراج: = to_unsigned (0 ، 16) ؛ WaveOut <= STD_LOGIC_VECTOR (to_signed (السعة (i) ، 10)) ؛ - الزيادة i للقراءة التالية i <= i + 1 ؛ - إعادة تعيين i إذا اكتملت موجة جيبية واحدة إذا (i = 63) ثم i <= 0 ؛ إنهاء إذا؛ إنهاء إذا؛ - (العداد = غير موقعة (Freq_Cnt)) وإلا - لم يتم الضغط على المفتاح - إعادة تعيين الإخراج ومؤشر السعة والعداد WaveOut <= "0000000000" ؛ أنا <= 0 ؛ العداد: = to_unsigned (0 ، 16) ؛ - سعة الإخراج = -64 عندما لا يتم تشغيل أي ملاحظة تنتهي إذا ؛ - (Trigger = '1') ينتهي إذا ؛ - عملية النهاية (Rising_edge (CLK)) ؛ نهاية السلوك

سنولد موجة جيبية رقمية في Basys3 باستخدام الساعة الداخلية وذاكرة القراءة فقط. ستخزن ذاكرة القراءة فقط 64 قيمة تمثل 64 سعة على موجة جيبية. انظر الشكل 1. القيم الـ 64 التي نستخدمها تحاكي موجة جيبية بدقة جيدة.

باستخدام الساعة الداخلية ، نحسب القيمة التي تمثل سرعة الساعة مقسومة على تردد الموجة التي نريدها و 64: Clk div = 100MHz / (Freq * 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 ؛ الهندسة المعمارية سلوك Two_Octave_Synth هو المكون Wave_Generator هو المنفذ (المشغل: في STD_LOGIC ؛ Freq_Cnt: في STD_LOGIC_VECTOR (15 أسفل إلى 0) ؛ wavegenCLK: في STD_LOGIC ؛ WaveOut: خارج STD_LOGIC_VECTOR (9 أسفل إلى 0)) ؛ المكون النهائي --------------------------- إشارات الإخراج من مولد الموجة ------------------ ----- إشارة 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 ، cnt5nt5nt5 ، cntDs5 ، cntE5 ، cnt5nt5nt5 ، cntCs5: بدون توقيع (4 أسفل إلى 0) ؛ خطأ في الإشارة: STD_LOGIC ؛ ----------------------------------- لإضافة موجات جيبية ----------- --------------- إشارة الموجة 0 ، الموجة 1 ، الموجة 2 ، الموجة 3: موقعة (9 أسفل حتى 0) ؛ - إشارات من إشارة خرج وحدة الموجة WaveSum: STD_LOGIC_VECTOR (9 أسفل إلى 0) ؛ - إشارة لموجات جيبية مجمعة (مجاملة 2 -512 إلى 511) إشارة موجبة - غير موقعة من 0 إلى 1023 ، للاستخدام في مولد PWM ----------------------------------- لتوليد PWM ------------------------------- إشارة ping_length: unsigned (9 downto 0): = unsigned (positiveWaveSum)؛ --signal off_length: غير موقعة (6 downto 0): = to_unsigned (127، 7) - غير موقعة (WAVE) ؛ إشارة PWM: غير موقعة (9 لأسفل حتى 0): = to_unsigned (0 ، 10) ؛ بدء Note_C4: خريطة منفذ Wave_Generator (المشغل => O4 (0) ، Freq_Cnt => X "1755" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveC4) ؛ --5973 ، 261.63 هرتز Note_Cs4: خريطة منفذ Wave_Generator (Trigger => O4 (1) ، Freq_Cnt => X "1606" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveCs4) ؛ - 5638 ، 277.18 هرتز Note_D4: خريطة منفذ Wave_Generator (Trigger => O4 (2) ، Freq_Cnt => X "14C9" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveD4) ؛ --5321 ، 293.66 هرتز Note_Ds4: خريطة منفذ Wave_Generator (Trigger => O4 (3) ، Freq_Cnt => X "139F" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveDs4) ؛ - 5023 ، 311.13 هرتز Note_E4: خريطة منفذ Wave_Generator (Trigger => O4 (4) ، Freq_Cnt => X "1285" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveE4) ؛ --4741 ، 329.63 هرتز Note_F4: خريطة منفذ Wave_Generator (المشغل => O4 (5) ، Freq_Cnt => X "117B" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveF4) ؛ --4475 ، 349.23 هرتز Note_Fs4: خريطة منفذ Wave_Generator (Trigger => O4 (6) ، Freq_Cnt => X "1080" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveFs4) ؛ - 4224 ، 369.99 هرتز Note_G4: خريطة منفذ Wave_Generator (Trigger => O4 (7) ، Freq_Cnt => X "0F92" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveG4) ؛ --3986 ، 392.00 هرتز Note_Gs4: خريطة منفذ Wave_Generator (Trigger => O4 (8) ، Freq_Cnt => X "0EB3" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveGs4) ؛ - 3763 ، 415.30 هرتز Note_A4: خريطة منفذ Wave_Generator (Trigger => O4 (9) ، Freq_Cnt => X "0DE0" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveA4) ؛ --3552 ، 440.00 هرتز Note_As4: خريطة منفذ Wave_Generator (المشغل => O4 (10) ، Freq_Cnt => X "0D18" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveAs4) ؛ - 3352 ، 466.16 هرتز Note_B4: خريطة منفذ Wave_Generator (Trigger => O4 (11) ، Freq_Cnt => X "0C5C" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveB4) ؛ - 3164 ، 493.88 هرتز -------------------------------------------- -------------------------------------------------- --------------------------- Note_C5: خريطة منفذ Wave_Generator (Trigger => O5 (0) ، Freq_Cnt => X "0BAB" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveC5) ؛ --2987 ، 523.25 هرتز Note_Cs5: خريطة منفذ Wave_Generator (Trigger => O5 (1) ، Freq_Cnt => X "0B03" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveCs5) ؛ - 2819 ، 554.37 هرتز Note_D5: خريطة منفذ Wave_Generator (Trigger => O5 (2) ، Freq_Cnt => X "0A65" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveD5) ؛ --2661 ، 587.33 هرتز Note_Ds5: خريطة منفذ Wave_Generator (Trigger => O5 (3) ، Freq_Cnt => X "09D0" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveDs5) ؛ - 2512 ، 622.25 هرتز Note_E5: خريطة منفذ Wave_Generator (Trigger => O5 (4) ، Freq_Cnt => X "0943" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveE5) ؛ - 2371 ، 659.25 هرتز Note_F5: خريطة منفذ Wave_Generator (المشغل => O5 (5) ، Freq_Cnt => X "08Be" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveF5) ؛ --2238 ، 698.46 هرتز Note_Fs5: خريطة منفذ Wave_Generator (Trigger => O5 (6) ، Freq_Cnt => X "0840" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveFs5) ؛ - 2112 ، 739.99 هرتز Note_G5: خريطة منفذ Wave_Generator (Trigger => O5 (7) ، Freq_Cnt => X "07CA" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveG5) ؛ --1994 ، 783.99 هرتز Note_Gs5: خريطة منفذ Wave_Generator (Trigger => O5 (8) ، Freq_Cnt => X "075A" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveGs5) ؛ - 1882 ، 830.61 هرتز Note_A5: خريطة منفذ Wave_Generator (Trigger => O5 (9) ، Freq_Cnt => X "06F0" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveA5) ؛ --1776 ، 880.00 هرتز Note_As5: خريطة منفذ Wave_Generator (Trigger => O5 (10) ، Freq_Cnt => X "068C" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveAs5) ؛ - 1676 ، 932.33 هرتز Note_B5: خريطة منفذ Wave_Generator (Trigger => O5 (11) ، Freq_Cnt => X "062E" ، wavegenCLK => CLK ، موقع (WaveOut) => WaveB5) ؛ --1582 ، 987.77 هرتز Note_C6: خريطة منفذ Wave_Generator (المشغل => O5 (12) ، Freq_Cnt => X "05D6" ، wavegenCLK => CLK ، موقعة (WaveOut) => WaveC6) ؛ --1494 ، 1046.5 هرتز ------------ منطق الاختيار ------------ 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 ، WaveF5 ، WaveDs5 ، WaveE5 ، WaveF5 ، WaveFs5 ، WaveG5A ، WaveGs5 ، Wave WaveB5 ، WaveC6) تبدأ إذا (cntC6 = "00000") ثم --------------- إذا لم يتم إنشاء إشارات Wave0 <= "0000000000" ؛ Wave1 <= "0000000000" ؛ Wave2 <= "0000000000" ؛ Wave3 <= "0000000000" ؛ وإلا إذا كان (O4 (0) = '1') ثم ------------------- لاحظ أن C4 لعبت Wave0 Wave0 Wave1 خطأ الموجة 1 Wave1 الموجة 1 خطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 خطأ الموجة 1 الموجة الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الموجة 0 الموجة 1 الموجة الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الخطأ الموجة 0 الموجة 1 الموجة 2 الموجة 3 الموجة 0 الموجة 1 الموجة = WaveC6 ؛ Wave1 <= "0000000000" ؛ Wave2 <= "0000000000" ؛ Wave3 Wave1 <= WaveC6 ؛ Wave2 <= "0000000000" ؛ Wave3 Wave2 <= WaveC6 ؛ خطأ Wave3 Wave3 Wave1 <= "0000000000" ؛ Wave2 <= "0000000000" ؛ Wave3 Wave2 <= "0000000000" ؛ خطأ Wave3 Wave3 <= '1' ؛ حالة النهاية إنهاء إذا؛ إنهاء إذا؛ إنهاء العملية؛ ------------- ملصق موجة جيبية -------------------- WaveSum <= STD_LOGIC_VECTOR (Wave0 + Wave1 + Wave2 + Wave3) ؛ --------- جعل موجة جيبية موجبة لـ pwm --------------------- موجبة الموجة <= not WaveSum (9) & WaveSum (8 downto 0) ؛ ------------- مولد PWM --------------------- عملية (CLK) - عدد متغير: غير موقع (1 إلى 0): = to_unsigned (0، 2) ؛ ابدأ إذا (Rising_edge (CLK)) ثم --count: = count + 1 ؛ - if (count = to_unsigned (4، 2)) ثم --count: = to_unsigned (0، 2)؛ --إذا كان (PWM = to_ if (PWM <ping_length) ثم خرج <= '1' ؛ خرج آخر <= '0' ؛ end if ؛ PWM <= PWM + 1 ؛ ping_length <= غير موقعة (موجبة الموجة) ؛ - إنهاء إذا ؛ إنهاء إذا ؛ إنهاء العملية ؛ إنهاء السلوك ؛

4 محدد الملاحظات الجزء الأصعب من هذا المشروع هو اختيار أربعة ترددات فقط. لقد فعلنا ذلك باستخدام عبارات lotta 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 chord) ، فسيكون cntC4 1 و cntE4 سيكون 2 و cntG4 سيكون 3 وما إلى ذلك.

بعد ذلك ، عندما يتم تشغيل ملاحظة ، سيتم فحص عدد النوتة المستهدفة لمعرفة مكان ربط إشارة النوتة. على سبيل المثال ، إذا تم تشغيل ملاحظة D5 (مما يعني أن O5 (2) مرتفع) و cntD5 هو 3 ، فهناك حاليًا 3 نوتات يتم عزفها ، مع نغمتين أقل من D5 ، لذلك سنربط waveD5 بالموجة 2 (الموجة الثالثة عد الإشارة من Wave0). بدلاً من ذلك ، إذا كان cntD5 يساوي 5 ، فهناك 5 نوتات يتم تشغيلها حاليًا ، مع 4 ملاحظات أقل من D5 ، لذلك سنترك waveD5 معلقة ولن نفعل أي شيء بها.

ثم يتم تكرار عبارات IF لتغطية الحالات لجميع الملاحظات البالغ عددها 25.

السعة الأفعى

بعد تحديد الموجات الأربع الدنيا ، يتعين علينا جمعها معًا. السبب في أننا سنضيف أربع ملاحظات فقط معًا هو أن فكرة PWM التي نستخدمها لإخراجنا يمكن أن يكون لها دقة معينة فقط حتى يعمل PWM ببطء شديد وسيبدأ المتحدث في التقاط الموجة المربعة PWM. على سبيل المثال ، إذا أردنا استخدام دقة 8192 (13 بت) ، فيجب أن تتوافق كل نقطة من هذه النقاط البالغ عددها 8192 مع حافة صاعدة للساعة المدمجة. لذلك ، 100 ميجاهرتز / 8192 = 12.2 كيلو هرتز ، وهو ما يقع ضمن نطاق السمع البشري.

إن الإضافة الفعلية للسعات بسيطة للغاية ، ما عليك سوى التأكد من أنها يمكن أن تعمل بسرعة كبيرة.

إخراج PWM

ستمثل دورة عمل PWM سعة موجة الخرج لدينا في تلك اللحظة. على سبيل المثال ، إذا كان لدينا نطاق اتساع من 0 إلى 128 ، سيكون 0 دورة عمل 0٪ ، و 64 سيكون 50٪ ، و 128 سيكون 100٪ ، وما إلى ذلك. سريع جدًا بحيث لا يتعرف المتحدث على الموجات المربعة الفردية وبدلاً من ذلك ينظر إلى متوسط الجهد ، مما يخلق إشارة "تمثيلية".

ملف القيود

ربما تكون قد قمت بتوصيل أجهزتك بشكل مختلف ، لذا تأكد فقط من تطابق ملف القيود.

الخطوة 5: تنزيلات التعليمات البرمجية

يوجد أدناه الرمز ، بتنسيق.txt و.vhd لـ Vivado. Wave_Generator هي الوحدة الفرعية لمولد الموجة ، و Two_Octave_Synth هي الوحدة النمطية الأعلى مع كل شيء آخر.

موصى به: