Verilog
Sebuah generate
block memungkinkan untuk menggandakan instance modul atau melakukan instantiasi bersyarat dari modul apa pun. Ini memberikan kemampuan untuk desain yang akan dibangun berdasarkan parameter Verilog. Pernyataan ini sangat cocok ketika operasi yang sama atau contoh modul perlu diulang beberapa kali atau jika kode tertentu harus dimasukkan secara kondisional berdasarkan parameter Verilog yang diberikan.
Sebuah generate
blok tidak boleh berisi port, parameter, specparam
deklarasi atau specify
blok. Namun, item modul lain dan blok pembangkit lainnya diperbolehkan. Semua instantiasi yang dihasilkan dikodekan dalam module
dan di antara kata kunci generate
dan endgenerate
.
Instansiasi yang dihasilkan dapat memiliki salah satu modul, penugasan berkelanjutan, always
atau initial
blok dan primitif yang ditentukan pengguna. Ada dua jenis konstruk generate - loop dan conditional.
Setengah penambah akan dipakai N kali dalam modul desain tingkat atas lain yang disebut my_design menggunakan generate
untuk konstruksi loop. Variabel loop harus dideklarasikan menggunakan kata kunci genvar
yang memberi tahu alat bahwa variabel ini akan digunakan secara khusus selama elaborasi blok generate.
// Design for a half-adder
module ha ( input a, b,
output sum, cout);
assign sum = a ^ b;
assign cout = a & b;
endmodule
// A top level design that contains N instances of half adder
module my_design
#(parameter N=4)
( input [N-1:0] a, b,
output [N-1:0] sum, cout);
// Declare a temporary loop variable to be used during
// generation and won't be available during simulation
genvar i;
// Generate for loop to instantiate N times
generate
for (i = 0; i < N; i = i + 1) begin
ha u0 (a[i], b[i], sum[i], cout[i]);
end
endgenerate
endmodule
Parameter testbench digunakan untuk mengontrol jumlah instance half adder dalam desain. Ketika N adalah 2, my_design akan memiliki dua instance setengah penambah.
module tb;
parameter N = 2;
reg [N-1:0] a, b;
wire [N-1:0] sum, cout;
// Instantiate top level design with N=2 so that it will have 2
// separate instances of half adders and both are given two separate
// inputs
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 jumlah[0] dan cout[0] sedangkan a[1] dan b[1] memberikan output jumlah[1] dan cout[1].
Log Simulasincsim> 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: Simulation is complete. ncsim> exit
Lihat bahwa RTL yang diuraikan memang memiliki dua instance setengah penambah yang dihasilkan oleh generate
blokir.
Di bawah ini adalah contoh menggunakan if else
di dalam generate
konstruksi untuk memilih antara dua implementasi multiplexer yang berbeda. Desain pertama menggunakan assign
pernyataan untuk mengimplementasikan mux sedangkan desain kedua menggunakan case
penyataan. Parameter yang disebut USE_CASE didefinisikan dalam modul desain tingkat atas untuk memilih di antara dua pilihan.
// Design #1: Multiplexer design uses an "assign" statement to assign
// out signal
module mux_assign ( input a, b, sel,
output out);
assign out = sel ? a : b;
// The initial display statement is used so that
// we know which design got instantiated from simulation
// logs
initial
$display ("mux_assign is instantiated");
endmodule
// Design #2: Multiplexer design uses a "case" statement to drive
// out signal
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
// The initial display statement is used so that
// we know which design got instantiated from simulation
// logs
initial
$display ("mux_case is instantiated");
endmodule
// Top Level Design: Use a parameter to choose either one
module my_design ( input a, b, sel,
output out);
parameter USE_CASE = 0;
// Use a "generate" block to instantiate either mux_case
// or mux_assign using an if else construct with 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 membuat instance modul tingkat atas my_design dan menyetel parameter USE_CASE ke 1 sehingga membuat instance desain menggunakan case
pernyataan.
module tb;
// Declare testbench variables
reg a, b, sel;
wire out;
integer i;
// Instantiate top level design and set USE_CASE parameter to 1 so that
// the design using case statement is instantiated
my_design #(.USE_CASE(1)) u0 ( .a(a), .b(b), .sel(sel), .out(out));
initial begin
// Initialize testbench variables
a <= 0;
b <= 0;
sel <= 0;
// Assign random values to DUT inputs with some delay
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 dilihat dari log simulasi bahwa desain multiplexer menggunakan case
pernyataan diinstansiasi. Dan ketika USE_CASE adalah nol, desain multiplexer menggunakan assign
pernyataan diinstansiasi. Ini terlihat dari pernyataan tampilan yang dicetak di log simulasi.
// When 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: Simulation is complete. // When 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: Simulation is complete.
Kasus hasilkan memungkinkan modul, blok awal dan blok selalu dipakai dalam modul lain berdasarkan case
ekspresi untuk memilih salah satu dari banyak pilihan.
// Design #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
// Design #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
// Top level design: Choose between half adder and 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
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 setengah penambah dipakai, cin tidak memiliki efek apa pun pada jumlah dan cout keluaran.
Log Simulasincsim> 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: Simulation is complete.
Verilog
case pernyataan memeriksa apakah ekspresi yang diberikan cocok dengan salah satu ekspresi lain dalam daftar dan bercabang sesuai. Biasanya digunakan untuk mengimplementasikan multiplexer. Konstruksi if-else mungkin tidak cocok jika ada banyak kondisi yang harus diperiksa dan akan disintesis menjadi
Parameter adalah konstruksi Verilog yang memungkinkan modul untuk digunakan kembali dengan spesifikasi yang berbeda. Misalnya, penambah 4-bit dapat diparameterisasi untuk menerima nilai jumlah bit dan nilai parameter baru dapat diteruskan selama pembuatan modul. Jadi, penambah N-bit bisa menjadi pen
Verilog adalah bahasa deskripsi perangkat keras dan tidak ada persyaratan bagi desainer untuk mensimulasikan desain RTL mereka agar dapat mengubahnya menjadi gerbang logika. Jadi apa yang perlu disimulasikan? Simulasi adalah teknik menerapkan stimulus input yang berbeda ke desain pada waktu yang
Desain module pr_en ( input [7:0] a, input [7:0] b, input [7:0] c, input [7:0] d, input [1:0] sel, output reg [7:0] out); always @ (a or b or c or d or sel) begin if (sel == 2b00) out <= a; else