تصميم المعالج ModelSim


الجزء الأول
الجزء الثاني
الجزء الثالث
الجزء الرابع
الجزء الخامس

هذه هي النسخة الكاملة من المقالة السابقة التي تمت إضافة مقاعد البدلاء إليها.

نقوم بتصميم كمبيوتر ليتل مان في فيريلوج.

المقالة حول LMC كانت على حبري.

جهاز محاكاة عبر الإنترنت لهذا الكمبيوتر هنا .

دعنا نكتب وحدة ذاكرة الوصول العشوائي ، تتكون من أربع (ADDR_WIDTH = 2) أربع كلمات (DATA_WIDTH = 4) كلمات. يتم تحميل البيانات في ذاكرة الوصول العشوائي من data_in في adr عند وصول ساعة إشارة الساعة.

module R0 #(parameter ADDR_WIDTH = 2, DATA_WIDTH = 4) ( input clk, //  input [ADDR_WIDTH-1:0] adr, // input [DATA_WIDTH-1:0] data_in, //   output [DATA_WIDTH-1:0] RAM_out //   ); reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; //  mem always @(posedge clk) //    clk mem [adr] <= data_in; //     data_in assign RAM_out = mem[adr]; // RAM_out    endmodule 

في طاولة الاختبار ، حمل 0001 عند 00 ، 0010 عند 01 ، 0100 عند 10 ، 1000 عند 11:
إنشاء testbench
إنشاء مشروع جديد وإنشاء ملفات R0.v و tR0.v (ستتم إضافة هذه الملفات تلقائيًا إلى المشروع).
تجميع كلا الملفين.
تشغيل محاكاة الملف المترجم tR0.v

 module tR0; reg clk; reg [1:0] adr; reg [3:0] data_in; wire [3:0] RAM_out; R0 test_R0 (clk, adr, data_in,RAM_out); initial begin clk = 0; adr[0] = 0; adr[1] = 0; data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; #5 data_in[0] = 1; #5 clk = 1; #5 adr[0] = 1; data_in[0] = 0; data_in[1] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 0; adr[1] = 1; data_in[1] = 0; data_in[2] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 1; adr[1] = 1; data_in[2] = 0; data_in[3] = 1; clk = 0; #5 clk = 1; #5 adr[0] = 0; adr[1] = 0; data_in[3] = 0; clk = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; #5 adr[0] = 0; adr[1] = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; #5 adr[0] = 0; adr[1] = 0; #5 adr[0] = 1; adr[1] = 0; #5 adr[0] = 0; adr[1] = 1; #5 adr[0] = 1; adr[1] = 1; end endmodule 



نقوم بتوصيل العداد بإدخال عنوان RAM. من الضروري توصيل مولد الساعة بإدخال العداد.

فيما يلي مثال لبرنامج يستخدم المولد الداخلي ALTUFM_OSC. تردد مولد قياسي 5.5 ميجا هرتز (MAX II EPM240 CPLD Minimal Development Board).

 module inner_Clock ( output reg LED); ALTUFM_OSC osc( .oscena(1'b1), .osc(clk)); reg signal; reg [24:0] osc_counter; reg [24:0] const_data = 25'b10110111000110110000000; initial begin signal = 1'b0; osc_counter = 25'b0; end //  6 000 000    osc_counter always @(posedge clk) begin osc_counter <= osc_counter+ 1'b1; if(osc_counter == const_data) begin signal <= ~signal; osc_counter <= 25'b0; end LED = signal; // LED  ~1   . end endmodule 

يمكنك أيضًا استخدام مولد خارجي ، مثل مؤقت 555 CMOS (مدعوم من 3.3V). نقوم بتوصيل المؤقت 555 بالعداد ، وربط العداد بإدخال عنوان RAM.

T.O. عندما تصل إشارة الساعة إلى العداد ، سننتقل إلى الخلية التالية في الذاكرة. سنقوم بتوصيل زر RAM_button بإدخال ساعة RAM - سيتم تحميل البيانات في RAM عند النقر فوق هذا الزر.

 module R1 (timer555, RAM_button, data_in, RAM_out, counter); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input timer555; input RAM_button; //input [ADDR_WIDTH-1:0] adr; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; output reg [1:0] counter; // Counter always @(posedge timer555) counter <= counter + 1; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

هذا ما تبدو عليه الدائرة في عارض RTL



في محاكي ModelSim ، لن يعمل هذا المخطط ، لأن المحاكي لا يعرف القيمة الأولية لسجلات [1: 0] العداد.
يمكن التحقق من تشغيل الدائرة عن طريق تنزيل البرنامج مباشرة إلى FPGA.

بعد ذلك ، أضف وظيفة التنزيل إلى العداد. التنزيل من data_in [1: 0] بالنقر فوق الزر Counter_load

 module R2 (counter, timer555, Counter_load, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; output [1:0] counter; input timer555, Counter_load; // input [N-1:0] adr; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge Counter_load) if (Counter_load) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

هذه هي الطريقة التي يبدو بها اتصال الأزرار ومصابيح LED في Pin Planner:



تنزيل 0001 عند 00 ، 0010 عند 01 ، 0100 عند 10 ، 1000 عند 11

 module tR2; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg timer555, Counter_load, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R2 test_R2(counter, timer555, Counter_load, RAM_button, data_in, RAM_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; Counter_load = 0; RAM_button = 0; #5 data_in[0]=0; data_in[1]=0; Counter_load=1; RAM_button=0; #5 data_in[0]=1; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=1; data_in[1]=0; Counter_load=1; RAM_button=0; #5 data_in[0]=0; data_in[1]=1; Counter_load=0; RAM_button=1; #5 data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=0; data_in[1]=1; Counter_load=1; RAM_button=0; #5 data_in[2]=1; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[2]=0; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; #5 data_in[0]=1; data_in[1]=1; Counter_load=1; RAM_button=0; #5 data_in[3]=1; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=1; #5 data_in[3]=0; data_in[0]=0; data_in[1]=0; Counter_load=0; RAM_button=0; end endmodule 



في وحدة منفصلة ، قم بإنشاء سجل 4bit'ny (البطارية).

يتم تحميل البيانات في التسجيل عند النقر فوق الزر reg_button:

 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(posedge reg_button) q <= reg_data; endmodule 

قم بإضافة المجمع ، معدد الإرسال MUX2 والمجمّع الإجمالي إلى الدائرة العامة.
يضيف المصمم إلى الرقم في أرقام Acc البطارية من الذاكرة.
يتم إعطاء مدخلات إشارة معدد الإرسال أرقام data_in و sum.
يتم تحميل الرقم من MUX2 في بطارية Acc بالضغط على زر Acc_button.
يتم تحميل الرقم من Ass في ذاكرة الوصول العشوائي عند الضغط على زر RAM_button.





 module R3 (MUX_switch, Acc_button, Acc, counter, timer555, Counter_load, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input MUX_switch; input Acc_button; output [3:0] Acc; input timer555, Counter_load; output [1:0] counter; // input [N-1:0] adr; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge Counter_load) if (Counter_load) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= Acc; assign RAM_out = mem[adr]; // sum wire [3:0] sum; assign sum = Acc + RAM_out; // MUX2 reg [3:0] MUX2; always @* MUX2 = MUX_switch ? sum : data_in; //     Acc_button /* reg Acc_dff; always @(posedge Acc_button or negedge timer555) if (!timer555) Acc_dff <= 1'b0; else Acc_dff <= timer555; */ //Acc register4 Acc_reg( .reg_data(MUX2), //.reg_button(Acc_dff), .reg_button(Acc_button), .q(Acc) ); endmodule 

لقمع الثرثرة المبرمجة ، يمكنك استخدام المخطط البسيط الوارد في التعليقات
/ * reg Acc_dff ؛
دائمًا @ (مؤشّر Acc_button أو عداد الوقت 555)
إذا (! timer555)
Acc_dff <= 1'b0 ؛
آخر
Acc_dff <= timer555 ؛ * /

يمكنك أيضًا القراءة عن قمع الأزرار في التعليقات على المقالة ، ونومض AVR يدويًا

بعد ذلك ، سنضيف الأرقام ، على سبيل المثال ، 2 و 3.

1. تحميل الأرقام في ذاكرة الوصول العشوائي
2. صفر الحمار
3. التبديل MUX2
4. قم بتنزيل الرقم الأول من RAM إلى Ass
5. أضف الرقم الثاني من ذاكرة الوصول العشوائي إلى الرقم الموجود في Ass
6. قم بتحميل المبلغ إلى ذاكرة الوصول العشوائي

 module tR3; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, Counter_load, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R3 test_R3(MUX_switch, Acc_button, Acc, counter, timer555, Counter_load, RAM_button, data_in, RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; Counter_load = 0; Acc_button = 0; RAM_button = 0; MUX_switch = 0; #5 Counter_load = 1; #5 data_in[0]=0; data_in[1]=1; Counter_load = 0; #5 Acc_button = 1; #5 RAM_button = 1; #5 data_in[0]=0; data_in[1] = 0; Acc_button = 0; RAM_button = 0; #5 data_in[0]=1; data_in[1]=1; #15 Acc_button = 1; #5 RAM_button = 1; #5 Acc_button = 0; #5 data_in[0]=0; data_in[1] = 0; RAM_button = 0; #10 Acc_button = 1; #10 Acc_button = 0; #60 MUX_switch = 1; #10 Acc_button = 1; #10 Acc_button = 0; #30 Acc_button = 1; #10 Acc_button = 0; #30 RAM_button = 1; #10 RAM_button = 0; end endmodule 



أضف إلى الوحدة الرئيسية عنصرًا يطرح الرقم المسجل في الذاكرة من البطارية.

 wire [3:0] subtract; assign subract = Acc - RAM_out ; 


نستبدل معدد الإدخال ثنائي الإدخال بأربعة مدخلات
 always @* MUX4 = MUX_switch[1] ? (MUX_switch[0] ? RAM_out : subtract) : (MUX_switch[0] ? sum : data_in); 

نقوم بتوصيل جهاز الإخراج بالبطارية (4bit'ny register) ، ونقوم أيضًا بتوصيل علامتين للبطارية:

1. العلم "صفر" هو سجل. العنصر 4 أم لا. يتم رفع العلم إذا كانت محتويات الحمار صفر.

2. العلم "صفر أو رقم موجب" هو سجل. العنصر ليس على المستوى العالي للبطارية المكونة من أربعة أرقام. يتم رفع العلم إذا كانت محتويات الحمار أكبر من أو تساوي الصفر.

 // "" output Z_flag; assign Z_flag = ~(|Acc); //    // "   " output PZ_flag; assign PZ_flag = ~Acc[3]; 



أضف ثلاثة فرق

1. تحميل محتويات البطارية في جهاز الإخراج data_out
2. تحميل العنوان في العداد إذا تم رفع العلم "صفر" (JMP if Acc = 0)
3. تحميل العنوان في العداد إذا تم رفع العلم "صفر أو رقم موجب" (JMP if Acc> = 0)

 module R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc,counter,timer555,RAM_button,data_in,RAM_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; input JMP, Z_JMP, PZ_JMP; output Z_flag, PZ_flag; input Output_button; output [3:0] data_out; input [1:0] MUX_switch; input Acc_button; output [3:0] Acc; input timer555; output [1:0] counter; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; // flags wire Z,PZ; assign Z = Z_flag & Z_JMP; assign PZ = PZ_flag & PZ_JMP; // Counter reg [1:0] counter; always @ (posedge timer555 or posedge JMP or posedge Z or posedge PZ) if (JMP|Z|PZ) counter <= data_in[1:0]; else counter <= counter + 2'b01; // RAM wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= Acc; assign RAM_out = mem[adr]; // sum wire [3:0] sum; assign sum = Acc + RAM_out; //subtract wire [3:0] subtract; assign subtract = Acc - RAM_out; // MUX4 reg [3:0] MUX4; always @* MUX4 = MUX_switch[1] ? (MUX_switch[0] ? RAM_out : subtract) : (MUX_switch[0] ? sum : data_in); //Acc register4 Acc_reg( .reg_data(MUX4), .reg_button(Acc_button), .q(Acc) ); //data_out register4 Output_reg( .reg_data(Acc), .reg_button(Output_button), .q(data_out) ); assign Z_flag = ~(|Acc); assign PZ_flag = ~Acc[3]; endmodule 



1. تحميل الأرقام في ذاكرة الوصول العشوائي
2. صفر الحمار
3. التبديل MUX2
4. اطرح الرقم الأول (المكتوب في ذاكرة الوصول العشوائي) من Ass
5. اطرح الرقم الثاني (المكتوب في ذاكرة الوصول العشوائي) من Ass
6. تنزيل المبلغ إلى ذاكرة الوصول العشوائي و data_out

 module tR4; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg JMP, Z_JMP, PZ_JMP; wire Z_flag, PZ_flag; reg Output_button; wire [3:0] data_out; reg [1:0] MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R4 test_R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc, counter,timer555,RAM_button,data_in,RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; JMP = 0; Z_JMP = 0; PZ_JMP = 0; Acc_button = 0; RAM_button = 0; Output_button = 0; MUX_switch[0] = 0; MUX_switch[1] = 0; #5 JMP = 1; #5 data_in[0]=0; data_in[1]=1; JMP = 0; #5 Acc_button = 1; #5 RAM_button = 1; #5 data_in[0]=0; data_in[1] = 0; Acc_button = 0; RAM_button = 0; #5 data_in[0]=1; data_in[1]=1; #15 Acc_button = 1; #5 RAM_button = 1; #5 Acc_button = 0; #5 data_in[0]=0; data_in[1] = 0; RAM_button = 0; #10 Acc_button = 1; #10 Acc_button = 0; #60 MUX_switch[1] = 1; #10 Acc_button = 1; #10 Acc_button = 0; #30 Acc_button = 1; #10 Acc_button = 0; #30 RAM_button = 1; Output_button = 1; #10 RAM_button = 0; Output_button = 0; end endmodule 



تحقق من أنه عند وجود رقم موجب في Ass ، لا يحدث انتقال Z_JMP:

 module tR4_jmp; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 4; reg JMP, Z_JMP, PZ_JMP; wire Z_flag, PZ_flag; reg Output_button; wire [3:0] data_out; reg [1:0] MUX_switch; reg Acc_button; wire [3:0] Acc; reg timer555, RAM_button; wire [1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; R4 test_R4 (JMP,Z_JMP,PZ_JMP,Z_flag,PZ_flag,Output_button,data_out,MUX_switch,Acc_button,Acc, counter,timer555,RAM_button,data_in,RAM_out); initial begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; JMP = 0; Z_JMP = 0; PZ_JMP = 0; Acc_button = 0; RAM_button = 0; Output_button = 0; MUX_switch[0] = 0; MUX_switch[1] = 0; #5 JMP = 1; #5 data_in[0]=0; data_in[1]=1; JMP = 0; #5 Acc_button = 1; #5 data_in[0]=1; data_in[1]=1; Acc_button = 1; #5 data_in[0]=1; data_in[1]=1; Acc_button = 0; #5 Z_JMP = 1; #5 PZ_JMP = 1; Z_JMP = 0; #5 PZ_JMP = 0; end endmodule 



ضع أمر القفز غير المشروط في ذاكرة الوصول العشوائي



عرض التصميم

 //wire Counter_load; always @ (posedge timer555) if (Counter_load) counter <= RAM_out[3:0]; else counter <= counter + 2'b01; 

لن يعمل ModelSim ، لذلك سنستخدم الأمر reset_count الإضافي ، الذي يقوم بتهيئة العداد ، وإعادة تعيينه ، أي

 module resCount (reset_count, counter, timer555, RAM_button, data_in, RAM_out); parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; wire Counter_load; assign Counter_load = RAM_out[7]; reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 4'b0000; else if (Counter_load) counter <= RAM_out[3:0]; else counter <= counter + 4'b0001; wire [ADDR_WIDTH-1:0] adr; assign adr = counter; reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; endmodule 

منضدة اختبار

 module tresCount; parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; resCount test_resCount(reset_count, counter, timer555, RAM_button, data_in, RAM_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 0; data_in[7] = 0; RAM_button = 0; reset_count =1; #5 reset_count =0; #1500 data_in[7] =1; #5 RAM_button = 1; #5 data_in[7] =0; RAM_button = 0; end endmodule 



أضف إلى الدائرة MUX2 والحمار. سوف نسجل في Ass مع الأمر RAM_out [6].

 assign Acc_button = RAM_out[6]; 

سنقوم بتوصيل سجل إلى Ass الإدخال على مدار الساعة. عنصر AND

 //  regiser4  (posedge reg_button)  (negedge reg_button) .reg_button(Acc_button & timer555), 

معنى ربط سجل. العنصر وإدخال الساعة هو أنه الآن في الجزء الأمامي من المؤقت 555 يمكنك تبديل معدد الإرسال ، وعند الانخفاض للتسجيل في البطارية. T.O. نضع فريقين في فوز واحد.

سنقوم بتبديل MUX2 باستخدام الأمر RAM_out [5]

 assign MUX_switch = RAM_out[5]; 



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(negedge reg_button) //  "posedge"  "negedge" q <= reg_data; endmodule module R50 (reset_count, counter, timer555, RAM_button, data_in, RAM_out, mux_switch_out, mux_out,Acc_out); parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM_out; output [3:0] Acc_out; output mux_switch_out; output [3:0] mux_out; wire Counter_load; assign Counter_load = RAM_out[7]; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 2'b00; else if (Counter_load) counter <= RAM_out[1:0]; else counter <= counter + 2'b01; wire [ADDR_WIDTH-1:0] adr; assign adr = counter; //RAM reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0]; always @(posedge RAM_button) mem [adr] <= data_in; assign RAM_out = mem[adr]; // MUX2 wire MUX_switch; assign MUX_switch = RAM_out[5]; reg [3:0] MUX2; always @* MUX2 = MUX_switch ? RAM_out : data_in[3:0]; //  4   data_in assign mux_out = MUX2; assign mux_switch_out = MUX_switch; wire Acc_button; assign Acc_button = RAM_out[6]; //Acc register4 Acc_reg( .reg_data(mux_out), .reg_button(Acc_button & timer555), .q(Acc_out) ); endmodule 

في منضدة الاختبار ، اكتب الرقم 0101 إلى الخلية 00 ، والرقم 1010 إلى الخلية 01 ؛ قم بتحميل هذه الأرقام في البطارية

 module tR50; parameter ADDR_WIDTH = 2; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM_out; wire mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; R50 test_R50(reset_count, counter, timer555, RAM_button, data_in, RAM_out, mux_switch_out, mux_out,Acc_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 1; data_in[1] = 0; data_in[2] = 1; data_in[3] = 0; data_in[4] = 0; data_in[5] = 1; data_in[6] = 1; data_in[7] = 0; RAM_button = 0; reset_count =1; #5 RAM_button = 1; reset_count = 0; #5 data_in[0]=0; data_in[2]=0; data_in[5]=0; data_in[6]=0; RAM_button=0; #15 data_in[1]=1; data_in[3]=1; data_in[5]=1;data_in[6]=1; #5 RAM_button=1; #5 data_in[1]=0; data_in[3]=0; data_in[5]=0; data_in[6]=0; RAM_button=0; end endmodule 



نضع ذاكرة الوصول العشوائي الثانية في الدائرة العامة ونكتب إلى ذاكرة الوصول العشوائي باستخدام الأمر RAM1_out [4].

 assign RAM2_button = RAM1_out[4]; 



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(negedge reg_button) q <= reg_data; endmodule module R51 (reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out); parameter ADDR_WIDTH = 3; parameter DATA_WIDTH = 8; input reset_count; output [ADDR_WIDTH-1:0] counter; input timer555; input RAM1_button; input [DATA_WIDTH-1:0] data_in; output [DATA_WIDTH-1:0] RAM1_out; output [3:0] RAM2_out; output [3:0] Acc_out; output mux_switch_out; output [3:0] mux_out; wire Counter_load; assign Counter_load = RAM1_out[7]; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 2'b00; else if (Counter_load) counter <= RAM1_out[1:0]; else counter <= counter + 2'b01; wire [ADDR_WIDTH-1:0] adr1; assign adr1 = counter; //RAM1 reg [DATA_WIDTH-1:0] mem1 [2**ADDR_WIDTH-1:0]; always @(posedge RAM1_button ) mem1 [adr1] <= data_in; assign RAM1_out = mem1[adr1]; wire [ADDR_WIDTH-1:0] adr2; assign adr2 = RAM1_out[3:0]; wire RAM2_button; assign RAM2_button = RAM1_out[4]; //RAM2 reg [3:0] mem2 [2**ADDR_WIDTH-1:0]; always @(posedge RAM2_button) mem2 [adr2] <= Acc_out; assign RAM2_out = mem2[adr2]; // MUX2 wire MUX_switch; assign MUX_switch = RAM1_out[5]; reg [3:0] MUX2; always @* MUX2 = MUX_switch ? RAM2_out : data_in[3:0]; assign mux_out = MUX2; assign mux_switch_out = MUX_switch; wire Acc_button; assign Acc_button = RAM1_out[6]; //Acc register4 Acc_reg( .reg_data(mux_out), .reg_button(Acc_button & timer555), .q(Acc_out) ); endmodule 

في منصة الاختبار ، قم بتحميل الأرقام 0100 و 1000 من Ass إلى صفر 0000 وأول خلية 0001 من ذاكرة الوصول العشوائي mem2 (ثم قم بتحميل هذه الأرقام إلى Ass من ذاكرة الوصول العشوائي mem2)

 module tR51; parameter ADDR_WIDTH = 3; parameter DATA_WIDTH = 8; reg reset_count; reg timer555, RAM1_button; wire [ADDR_WIDTH-1:0] counter; reg [DATA_WIDTH-1:0] data_in; wire [DATA_WIDTH-1:0] RAM1_out; wire [3:0] RAM2_out; wire mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; R51 test_R51(reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 1; data_in[7] = 0; RAM1_button = 0; reset_count =1; #5 RAM1_button = 1; reset_count = 0; #5 RAM1_button = 0; data_in[6] = 0; #10 data_in[4] = 1; #5 RAM1_button = 1; #5 data_in[4] = 0; RAM1_button = 0; #30 data_in[6] = 1; #5 RAM1_button = 1; #5 data_in[6] = 0; RAM1_button = 0; #30 data_in[4] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 data_in[4] = 0; data_in[0] = 0; RAM1_button = 0; #30 data_in[6] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; #30 data_in[5] = 1; data_in[6] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[5] = 0; data_in[6] = 0; #30 data_in[5] = 1; data_in[6] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[0] = 0; data_in[5] = 0; data_in[6] = 0; #70 data_in[2] = 1; #80 data_in[2] = 0; data_in[3] = 1; #40 data_in[3] = 0; end endmodule 



سأضيف أن سجل مخطط ج. لن يعمل العنصر والعنصر في إدخال الساعة للبطارية بشكل صحيح دائمًا (حسب اللوحة). استبدل السجل. العنصر وفي مشغل Acc_dff ، سنقوم بالتحميل في الزناد على الحافة السلبية (عند التراجع) لإشارة ساعة المؤقت 555 ، وسنقوم بتحميل البطارية على الحافة الموجبة

 // Acc_dff reg Acc_dff; always @(negedge timer555) Acc_dff <= Acc_button; 

لذا ، بإضافة الأوامر المتبقية ، قم بإنشاء وحدة R52 (LMC)



 module register4 ( input [3:0] reg_data, input reg_button, output reg [3:0] q ); always @(posedge reg_button) // negedge -> posedge q <= reg_data; endmodule module R52 (Z_flag, PZ_flag, reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out, Acc_out, data_out, Acc_dff); parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 12; input reset_count; input timer555; input RAM1_button; input [DATA_WIDTH-1:0] data_in; output [ADDR_WIDTH-1:0] counter; output [1:0] mux_switch_out; output [3:0] mux_out; output [3:0] Acc_out; output [3:0] data_out; output [DATA_WIDTH-1:0] RAM1_out; output [3:0] RAM2_out; output Z_flag, PZ_flag; output Acc_dff; wire JMP_button, Z_JMP_button,PZ_JMP_button; assign JMP_button = RAM1_out[6]; assign Z_JMP_button = RAM1_out[5]; assign PZ_JMP_button = RAM1_out[4]; wire Z_JMP,PZ_JMP; assign Z_JMP = Z_flag & Z_JMP_button; assign PZ_JMP = PZ_flag & PZ_JMP_button; //Counter reg [ADDR_WIDTH-1:0] counter; always @ (posedge timer555 or posedge reset_count) if (reset_count) counter <= 4'b0000; else if (JMP_button|Z_JMP|PZ_JMP) counter <= RAM1_out[3:0]; else counter <= counter + 4'b0001; wire [ADDR_WIDTH-1:0] adr1; assign adr1 = counter; //RAM1 reg [DATA_WIDTH-1:0] mem1 [2**ADDR_WIDTH-1:0]; always @(posedge RAM1_button ) mem1 [adr1] <= data_in; assign RAM1_out = mem1[adr1]; //RAM2_adr wire [ADDR_WIDTH-1:0] adr2; assign adr2 = RAM1_out[2:0]; //RAM2_button wire RAM2_button; assign RAM2_button = RAM1_out[11]; //RAM2 reg [3:0] mem2 [2**ADDR_WIDTH-1:0]; always @(posedge RAM2_button) mem2 [adr2] <= Acc_out; assign RAM2_out = mem2[adr2]; // sum wire [3:0] sum; assign sum = Acc_out + RAM2_out; //subtract wire [3:0] subtract; assign subtract = Acc_out - RAM2_out; // MUX4 wire [1:0] mux_switch; assign mux_switch[0] = RAM1_out[7]; assign mux_switch[1] = RAM1_out[8]; reg [3:0] MUX4; always @* MUX4 = mux_switch[1] ? (mux_switch[0] ? RAM2_out : subtract) : (mux_switch[0] ? sum : data_in[3:0]); assign mux_out = MUX4; assign mux_switch_out[0] = mux_switch[0]; assign mux_switch_out[1] = mux_switch[1]; //Acc_button wire Acc_button; assign Acc_button = RAM1_out[10]; // Acc_dff reg Acc_dff; always @(negedge timer555) Acc_dff <= Acc_button; //Acc register4 Acc_reg( .reg_data(mux_out), //.reg_button(Acc_button & timer555), .reg_button(Acc_dff), .q(Acc_out) ); //data_out wire Output_button; assign Output_button = RAM1_out[9]; register4 Output_reg( .reg_data(Acc_out), .reg_button(Output_button), .q(data_out) ); // flags assign Z_flag = ~(|Acc_out); assign PZ_flag = ~Acc_out[3]; endmodule 

في منصة الاختبار ، سوف نتحقق من كيفية عمل الخوارزمية للعثور على الحد الأقصى من العدد.

تكمن خصوصية أوامر التحميل في ذاكرة الوصول العشوائي في أنه بعد تحميل جميع الأوامر ، يجب أن نعيد (340ns) إلى الخلية 8 وتحميل أمر آخر

 module tR52; parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 12; reg reset_count; reg timer555; reg RAM1_button; reg [DATA_WIDTH-1:0] data_in; wire [ADDR_WIDTH-1:0] counter; wire [1:0]mux_switch_out; wire [3:0] mux_out; wire [3:0] Acc_out; wire [3:0] data_out; wire [DATA_WIDTH-1:0] RAM1_out; wire [3:0] RAM2_out; wire Z_flag, PZ_flag; wire Acc_dff; R52 test_R52(Z_flag, PZ_flag, reset_count, counter, timer555, RAM1_button, data_in, RAM1_out, RAM2_out, mux_switch_out, mux_out,Acc_out, data_out, Acc_dff); initial // Clock generator begin timer555 = 0; forever #20 timer555 = ~timer555; end initial begin data_in[0] = 0; data_in[1] = 0; data_in[2] = 0; data_in[3] = 0; data_in[4] = 0; data_in[5] = 0; data_in[6] = 0; data_in[7] = 0; data_in[8] = 0; data_in[9] = 0; data_in[10] = 1; data_in[11] = 0; RAM1_button = 0; reset_count =1; //  1-    #5 RAM1_button = 1; reset_count = 0; #5 RAM1_button = 0; data_in[10] = 0; data_in[0] = 0; //  1-    0 #10 data_in[11] = 1; #5 RAM1_button = 1; #5 data_in[11] = 0; RAM1_button = 0; //  2-    #30 data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[10] = 0; //  2-    0 #30 data_in[11] = 1;data_in[0] = 1; #5 RAM1_button = 1; #5 data_in[11] = 0;data_in[0] = 0; RAM1_button = 0; // 1-    #30 data_in[8]=1; data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[8]=0; data_in[10] = 0; //  Acc>=0,    8 #30 data_in[4]=1; data_in[3]=1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[4]=0; data_in[3]=0; //  1-  #30 data_in[7] = 1; data_in[8] = 1; data_in[10] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[7] = 0; data_in[8] = 0; data_in[10] = 0; //     9 #30 data_in[6] = 1; data_in[3]=1; data_in[0]=1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; data_in[3]=0; data_in[0]=0; //   data_out #30 data_in[9] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[9] = 0; //     8 #30 data_in[6] = 1; data_in[3]=1; data_in[0]=0; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[6] = 0; data_in[3]=0; data_in[0]=0; // 2-  #30 data_in[7] = 1; data_in[8] = 1; data_in[10] = 1; data_in[0] = 1; #5 RAM1_button = 1; #5 RAM1_button = 0; data_in[7] = 0; data_in[8] = 0; data_in[10] = 0; data_in[0] = 0; #75 RAM1_button = 1; #5 RAM1_button = 0; #230 data_in[2]=1; data_in[0]=0; //  #80 data_in[2]=0; data_in[0]=1; //   end endmodule 

رابط لجيثب مع رموز البرنامج.

يمكن تنزيل نسخة الطالب المجانية من ModelSim لـ Windows من www.model.com .
بعد ذلك ، يجب عليك (عن طريق ملء النموذج) تنزيل ملف student_license.dat ووضع هذا الملف في الدليل الرئيسي لبرنامج ModelSim .

رابط إلى ملف ModelSim لنظام التشغيل Linux (Ubuntu) هنا
تعليمات التثبيت هنا .

Source: https://habr.com/ru/post/ar412379/


All Articles