Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> Verilog

Menguasai Blok Generate Verilog: Instanisasi Modul Dinamis & Desain Bersyarat

Sebuah blok generate memungkinkan untuk memperbanyak instance modul atau melakukan instantiasi bersyarat dari modul apa pun. Ini memberikan kemampuan untuk desain dibangun berdasarkan parameter Verilog. Pernyataan ini sangat nyaman ketika operasi atau instance modul yang sama perlu diulang beberapa kali atau jika kode tertentu harus disertakan secara bersyarat berdasarkan parameter Verilog yang diberikan.

Sebuah blok generate tidak dapat berisi deklarasi port, parameter, specparam atau blok specify. Namun, item modul lain dan blok generate lain diizinkan. Semua instantiasi generate dikodekan di dalam sebuah module dan di antara kata kunci generate dan endgenerate.

Instantiasi yang dihasilkan dapat berupa modul, penugasan berkelanjutan, blok always atau initial dan primitive yang ditentukan pengguna. Terdapat dua jenis konstruksi generate - loop dan kondisional.

Generate for loop

Sebuah half adder akan diinstanisasi N kali dalam modul desain tingkat atas lain yang disebut my_design menggunakan konstruksi generate for loop. Variabel loop harus dideklarasikan menggunakan kata kunci genvar yang memberitahu alat bahwa variabel ini akan digunakan khusus selama elaborasi blok generate.

  // Desain untuk half-adder module ha ( input a, b, output sum, cout); assign sum = a ^ b; assign cout = a & b; endmodule // Desain tingkat atas yang berisi N instance half adder module my_design #(parameter N=4) ( input [N-1:0] a, b, output [N-1:0] sum, cout); // Deklarasikan variabel loop sementara yang akan digunakan selama // generasi dan tidak akan tersedia selama simulasi genvar i; // Generate for loop untuk menginstanisasi N kali generate for (i = 0; i < N; i = i + 1) begin ha u0 (a[i], b[i], sum[i], cout[i]); end endgenerate endmodule  

Testbench

Parameter testbench digunakan untuk mengontrol jumlah instance half adder dalam desain. Ketika N adalah 2, my_design akan memiliki dua instance half adder.

  module tb; parameter N = 2; reg [N-1:0] a, b; wire [N-1:0] sum, cout; // Instanisasi desain tingkat atas dengan N=2 sehingga akan memiliki 2 // instance half adder terpisah dan keduanya diberikan dua input terpisah my_design #(.N(N)) md( .a(a), .b(b), .sum(sum), .cout(cout)); initial begin a <= 0; b <= 0; $monitor ("a=0x%0h b=0x%0h sum=0x%0h cout=0x%0h", a, b, sum, cout); #10 a <= 'h2; b <= 'h3; #20 b <= 'h4; #10 a <= 'h5; end endmodule  

a[0] dan b[0] memberikan output sum[0] dan cout[0] sementara a[1] dan b[1] memberikan output sum[1] dan cout[1].

Simulation Log
 ncsim> run a=0x0 b=0x0 sum=0x0 cout=0x0 a=0x2 b=0x3 sum=0x1 cout=0x2 a=0x2 b=0x0 sum=0x2 cout=0x0 a=0x1 b=0x0 sum=0x1 cout=0x0 ncsim: *W,RNQUIE: Simulasi selesai. ncsim> exit 

Lihat bahwa RTL yang dihasilkan memang memiliki dua instance half adder yang dihasilkan oleh blok generate.

Generate if

Ditunjukkan di bawah ini adalah contoh menggunakan if else di dalam konstruksi generate untuk memilih antara dua implementasi multiplexer yang berbeda. Desain pertama menggunakan pernyataan assign untuk mengimplementasikan mux sementara desain kedua menggunakan pernyataan case. Sebuah parameter yang disebut USE_CASE didefinisikan dalam modul desain tingkat atas untuk memilih antara dua pilihan.

  // Desain #1: Desain multiplexer menggunakan pernyataan "assign" untuk menugaskan // sinyal out module mux_assign ( input a, b, sel, output out); assign out = sel ? a : b; // Pernyataan display awal digunakan sehingga // kita tahu desain mana yang diinstanisasi dari log // simulasi initial $display ("mux_assign is instantiated"); endmodule // Desain #2: Desain multiplexer menggunakan pernyataan "case" untuk menggerakkan // sinyal out module mux_case (input a, b, sel, output reg out); always @ (a or b or sel) begin case (sel) 0 : out = a; 1 : out = b; endcase end // Pernyataan display awal digunakan sehingga // kita tahu desain mana yang diinstanisasi dari log // simulasi initial $display ("mux_case is instantiated"); endmodule // Desain Tingkat Atas: Gunakan parameter untuk memilih salah satu module my_design ( input a, b, sel, output out); parameter USE_CASE = 0; // Gunakan blok "generate" untuk menginstanisasi mux_case // atau mux_assign menggunakan konstruk if else dengan generate generate if (USE_CASE) mux_case mc (.a(a), .b(b), .sel(sel), .out(out)); else mux_assign ma (.a(a), .b(b), .sel(sel), .out(out)); endgenerate endmodule  

Testbench

Testbench menginstanisasi modul tingkat atas my_design dan mengatur parameter USE_CASE ke 1 sehingga menginstanisasi desain menggunakan pernyataan case.

  module tb; // Deklarasi variabel testbench reg a, b, sel; wire out; integer i; // Instanisasi desain tingkat atas dan atur parameter USE_CASE ke 1 sehingga // desain menggunakan pernyataan case diinstanisasi my_design #(.USE_CASE(1)) u0 ( .a(a), .b(b), .sel(sel), .out(out)); initial begin // Inisialisasi variabel testbench a <= 0; b <= 0; sel <= 0; // Berikan nilai acak ke input DUT dengan beberapa keterlambatan for (i = 0; i < 5; i = i + 1) begin #10 a <= $random; b <= $random; sel <= $random; $display ("i=%0d a=0x%0h b=0x%0h sel=0x%0h out=0x%0h", i, a, b, sel, out); end end endmodule  

Ketika parameter USE_CASE adalah 1, dapat terlihat dari log simulasi bahwa desain multiplexer menggunakan pernyataan case diinstanisasi. Dan ketika USE_CASE adalah nol, desain multiplexer menggunakan pernyataan assign diinstanisasi. Ini terlihat dari pernyataan display yang dicetak dalam log simulasi.

Simulation Log
 // Ketika USE_CASE = 1 ncsim> run mux_case is instantiated i=0 a=0x0 b=0x0 sel=0x0 out=0x0 i=1 a=0x0 b=0x1 sel=0x1 out=0x1 i=2 a=0x1 b=0x1 sel=0x1 out=0x1 i=3 a=0x1 b=0x0 sel=0x1 out=0x0 i=4 a=0x1 b=0x0 sel=0x1 out=0x0 ncsim: *W,RNQUIE: Simulasi selesai. // Ketika USE_CASE = 0 ncsim> run mux_assign is instantiated i=0 a=0x0 b=0x0 sel=0x0 out=0x0 i=1 a=0x0 b=0x1 sel=0x1 out=0x0 i=2 a=0x1 b=0x1 sel=0x1 out=0x1 i=3 a=0x1 b=0x0 sel=0x1 out=0x1 i=4 a=0x1 b=0x0 sel=0x1 out=0x1 ncsim: *W,RNQUIE: Simulasi selesai. 

Generate Case

Sebuah generate case memungkinkan modul, blok initial dan always untuk diinstanisasi dalam modul lain berdasarkan ekspresi case untuk memilih salah satu dari banyak pilihan.

  // Desain #1: Half adder module ha (input a, b, output reg sum, cout); always @ (a or b) {cout, sum} = a + b; initial $display ("Half adder instantiation"); endmodule // Desain #2: Full adder module fa (input a, b, cin, output reg sum, cout); always @ (a or b or cin) {cout, sum} = a + b + cin; initial $display ("Full adder instantiation"); endmodule // Desain tingkat atas: Pilih antara half adder dan full adder module my_adder (input a, b, cin, output sum, cout); parameter ADDER_TYPE = 1; generate case(ADDER_TYPE) 0 : ha u0 (.a(a), .b(b), .sum(sum), .cout(cout)); 1 : fa u1 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout)); endcase endgenerate endmodule  

Testbench

  module tb; reg a, b, cin; wire sum, cout; my_adder #(.ADDER_TYPE(0)) u0 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout)); initial begin a <= 0; b <= 0; cin <= 0; $monitor("a=0x%0h b=0x%0h cin=0x%0h cout=0%0h sum=0x%0h", a, b, cin, cout, sum); for (int i = 0; i < 5; i = i + 1) begin #10 a <= $random; b <= $random; cin <= $random; end end endmodule  

Perhatikan bahwa karena half adder diinstanisasi, cin tidak memiliki efek pada output sum dan cout.

Simulation Log
 ncsim> run Half adder instantiation a=0x0 b=0x0 cin=0x0 cout=00 sum=0x0 a=0x0 b=0x1 cin=0x1 cout=00 sum=0x1 a=0x1 b=0x1 cin=0x1 cout=01 sum=0x0 a=0x1 b=0x0 cin=0x1 cout=00 sum=0x1 ncsim: *W,RNQUIE: Simulasi selesai. 

Verilog

  1. Menguasai Verilog: Tutorial Lengkap untuk Desain Sirkuit Digital
  2. Menguasai Konkatenasi Verilog: Panduan Praktis
  3. Dasar-dasar Verilog: Ringkasan Ringkas
  4. Memahami Penugasan Verilog: Jenis, Sintaks, dan Praktik Terbaik
  5. Perbedaan Kunci Penugasan Blokir dan Non-Blokir Verilog
  6. Menguasai Fungsi Verilog untuk Desain RTL yang Efisien
  7. Memahami Tugas Verilog: Fungsi vs Tugas, Sintaks, dan Penggunaan
  8. Generator Jam Verilog: Panduan Desain dan Implementasi
  9. Menguasai Fungsi Matematika Verilog untuk Desain Perangkat Keras yang Efisien
  10. Menguasai $timeformat Verilog: Kontrol Presisi dan Tampilan