Mức trừu tượng đôi khi còn được gọi là mức hành vi trừu tượng (behavieral levels of abstraction). Theo nhận xét cá nhân mình thì ranh giới giữa các mức trừu tượng đôi khi không rõ ràng và việc phân loại các mức trừu tượng cũng có khác biệt chút ít (không nhiều) ở các tài liệu khác nhau. Thêm vào đó, các bạn cũng chú ý là Verilog HDL có những thành phần có thể tổng hợp (dùng để mô tả thiết kế) được và có những thành phần không thể tổng hợp được (dùng để viết testbench, mô phỏng). Vì vậy, khi đọc những phân tích dưới đây các bạn nên tự nhận định để phân biệt điều này.
Verilog HDL cho phép mô tả nhiều mức trừu tượng khác nhau. Hình sau đây sẽ cho thấy khả năng mô tả của Verilog HDL ở các mức trừu tượng khác nhau.
Thông thường, bạn sẽ thấy Verilog được trình bày theo ba mức chính là:
- Mức hành vi (behavioral level hay Algorithm/Function level)
Ở đây, mình xin nhấn mạnh là code mô tả hành vi có thể hoặc không thể tổng hợp được. Trong một số tài liệu có ghi, mức mô tả hành vi thường dùng cho testbench và mô phỏng, điều này có thể gây hiểu lầm là mô tả hành vi không sử dụng để mô tả mạch tổng hợp được.
Mức hành vi sử dụng các phát biểu như if-else, case, for, while, forever, repeat, always, initial, task, function, ... và các loại phép gán để mô tả các thuật toán hoặc chức năng mong muốn.
Ví dụ về mô tả hành vi không thể tổn hợp được (sử dụng cho mô phỏng):
Mã (verilog):
module clock_gen;
reg clock;
initial
clock = 1'b0;
always
#10 clock = ~clock;
initial
#1000 $finish;
endmodule
reg clock;
initial
clock = 1'b0;
always
#10 clock = ~clock;
initial
#1000 $finish;
endmodule
Mã (verilog):
module half_add (S, C, A, B);
input A, B;
output S, C;
reg S, C;
always @ (A or B)
begin
S = A ^B;
C = A & B;
end
input A, B;
output S, C;
reg S, C;
always @ (A or B)
begin
S = A ^B;
C = A & B;
end
- Mức truyền thanh ghi (Register Transfer Level – RTL)
Hiện nay, RTL code được hiểu là bất kỳ code nào có thể tổng hợp được (có thể viết bằng Verilog hay VHDL). Theo cách hiểu này thì một code dù viết theo kiểu mô tả hành vi, mô tả mức cổng hay kiểu mô tả nào khác mà có thể tổng hợp được thành mạch cụ thể thì được gọi là RTL code.
Ví dụ:
Mã (verilog):
module encoder_p (a_group, b_group, c_group,
valid, result);
`include "com_function.h"
//Ports
input [3:0] a_group, b_group, c_group;
output valid;
output reg [1:0] result;
//The valid signal
assign a_valid = or_gate(a_group[3:0]);
assign b_valid = or_gate(b_group[3:0]);
assign valid = a_valid|b_valid|or_gate(c_group[3:0]);
//The result signal
always @ (*) begin
casez ({a_valid, b_valid})
2'b1?: result[1:0] = encoder(a_group[3:0]);
2'b01: result[1:0] = encoder(b_group[3:0]);
2'b00: result[1:0] = encoder(c_group[3:0]);
default: result[1:0] = 2'b00;
endcase
end
endmodule
valid, result);
`include "com_function.h"
//Ports
input [3:0] a_group, b_group, c_group;
output valid;
output reg [1:0] result;
//The valid signal
assign a_valid = or_gate(a_group[3:0]);
assign b_valid = or_gate(b_group[3:0]);
assign valid = a_valid|b_valid|or_gate(c_group[3:0]);
//The result signal
always @ (*) begin
casez ({a_valid, b_valid})
2'b1?: result[1:0] = encoder(a_group[3:0]);
2'b01: result[1:0] = encoder(b_group[3:0]);
2'b00: result[1:0] = encoder(c_group[3:0]);
default: result[1:0] = 2'b00;
endcase
end
endmodule
- Mức cổng (Gate)
Mã (verilog):
module mux2_1 (o1,in1,in2,S0); //module
output o1;
input in1,in2,S0;
and a1 (Q, in1, S0); //and instantiation
not n1 (P,S0); // not instantiation
and a2 (R, in2, P); // and instantiation
or o1 (o1, Q, R); // or instantiation
endmodule
output o1;
input in1,in2,S0;
and a1 (Q, in1, S0); //and instantiation
not n1 (P,S0); // not instantiation
and a2 (R, in2, P); // and instantiation
or o1 (o1, Q, R); // or instantiation
endmodule
Các mức mô tả khác: Ngoài 3 mức cơ bản trên đây thì còn các mức trừu tượng khác mà các bạn có thể gặp như:
- Mức luồng dữ liệu (Data-flow)
Ví dụ:Mã (verilog):
module deco2_4 (EN, A0, A1, D0, D1, D2, D3);//module
input EN, A0, A1;
output D0, D1, D2, D3;
assign D0 =(EN & ~A1 & ~A0);
assign D1 =(EN & ~A1 & A0);
assign D2 =(EN & A1 & ~A0);
assign D3 =(EN & A1 & A0);
endmodule
input EN, A0, A1;
output D0, D1, D2, D3;
assign D0 =(EN & ~A1 & ~A0);
assign D1 =(EN & ~A1 & A0);
assign D2 =(EN & A1 & ~A0);
assign D3 =(EN & A1 & A0);
endmodule
Mô tả RTL code còn có thể được xem là sự kết hợp giữa mô tả mức hành vi (behavioral) và mô tả mức dataflow.
- Mức Switch (hay Transistor)
Mã (verilog):
module my_nand (input x, y, output f);
supply1 vdd;
supply0 gnd;
wire a;
// NAND gate body
pmos p1 (f, vdd, x);
pmos p2 (f, vdd, y);
nmos n1 (f, a, x);
nmos n2 (a, gnd, y);
endmodule
supply1 vdd;
supply0 gnd;
wire a;
// NAND gate body
pmos p1 (f, vdd, x);
pmos p2 (f, vdd, y);
nmos n1 (f, a, x);
nmos n2 (a, gnd, y);
endmodule
nguồn: http://icdesignvn.com/