ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC BÁCH KHOA
KHOA ĐIỆN – ĐIỆN TỬ
---
---
BÁO CÁO XỬ LÝ TÍN HIỆU SỐ VỚI FPGA
BÀI TẬP LỚN
Giáo viên hướng dẫn
: Nguyễn Lý Thiên Trường
Nhóm thực hiện
: 10
Danh sách thành viên
: Nguyễn Hà Nhất Phương
1813622
Nguyễn Bùi Thanh Sơn
1813849
Nguyễn Minh Thành
1814021
Trần Văn Thành
1814035
Võ Hồng Thịnh
1810552
TP. Hồ Chí Minh, Tháng 08/2021
Danh sách thành viên:
STT
Họ và Tên
MSSV
Email
1
Nguyễn Hà Nhất Phương
1813622
2
Nguyễn Bùi Thanh Sơn
1813849
3
Nguyễn Minh Thành
1814021
4
Trần Văn Thành
1814035
5
Võ Hoàng Thịnh
1810552
Danh sách phân công nhiệm vụ:
STT
Họ và Tên
Nhiệm vụ cụ thể
1
Nguyễn Hà Nhất Phương
Phần chung: Bài 1
2
Nguyễn Bùi Thanh Sơn
Phần chung: Bài 5
3
Nguyễn Minh Thành
Phần chung: Bài 4
4
Trần Văn Thành
Phần chung: Bài 3
5
Võ Hồng Thịnh
Phần chung: Bài 2
Phần bài tập riêng cả nhóm làm chung qua các buổi google meet.
Đại học Bách khoa TPHCM
Trang 1
MỤC LỤC
NỘI DUNG ................................................................................................................................
4
1 Phần chung cho tất cả các nhóm ......................................................................................
4
1.1
Bài 1 .............................................................................................................................
4
1.1.1
Đề bài ....................................................................................................................
4
1.1.2
Giải thuật thứ nhất ................................................................................................
5
1.1.3
Giải thuật thứ hai ................................................................................................
10
Bài 2 ...........................................................................................................................
16
1.2
1.2.1
Đề bài ..................................................................................................................
16
1.2.2
Cơ sở lý thuyết ....................................................................................................
16
1.2.3
Giải thuật tính tốn .............................................................................................
18
1.2.4
Code mơ phỏng ...................................................................................................
19
1.2.5
Kết quả mô phỏng ..............................................................................................
21
1.2.6
Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6. ...............................................................................................................
1.3
Bài 3 ...........................................................................................................................
23
24
1.3.1
Đề bài ..................................................................................................................
24
1.3.2
Giải thuật tính căn tính tốn từng chữ số (Digit-by-digit calculation) ...............
24
1.3.3
Code thực hiện và kết quả mô phỏng .................................................................
26
1.3.4
Kết quả đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6. ...............................................................................................................
1.4
Bài 4 ...........................................................................................................................
30
31
1.4.1
Đề bài ..................................................................................................................
31
1.4.2
Cơ sở lý thuyết ....................................................................................................
31
1.4.3
Chi tiết thiết kế ...................................................................................................
32
1.4.4
Code thực hiện và kết quả mô phỏng .................................................................
33
1.4.5
Kết quả đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6 ................................................................................................................
Đại học Bách khoa TPHCM
Trang 2
38
1.5
Bài 5........................................................................................................................... 40
1.5.1
Đề bài..................................................................................................................40
1.5.2
Cơ sở lý thuyết....................................................................................................40
1.5.3
Code thực hiện và kết quả mô phỏng..................................................................42
1.5.4
Kết quả đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6................................................................................................................45
2
Phần riêng cho từng nhóm..............................................................................................46
Đại học Bách khoa TPHCM
Trang 3
NỘI DUNG
1
Phần chung cho tất cả các nhóm
1.1
Bài 1
1.1.1 Đề bài
Cho sơ đồ khối của hệ thống tìm số nhỏ nhất thứ nhất (min1), số nhỏ nhất thứ 2
(min2) và vị trí của số nhỏ nhất thứ nhất (index_min1) trong số khơng dấu ngõ vào như
hình bên dưới.
Hình 1.1. Bộ min_finder
Lưu ý:
Thực thi hệ thống trên với = 10
Các ngõ vào I0, I1,…, In-1 là các số nhị phân 4 bit khơng dấu.
Trường hợp ngõ vào có nhiều hơn 2 giá trị min1, thì ngõ ra index_min1 chỉ vị trí
ngõ vào có chỉ số nhỏ hơn.
1.
Đề xuất 2 giải thuật thực thi hệ thống trên (sơ đồ khối, giải thích chi tiết).
2. Viết code Verilog mô tả 2 giải thuật đã đề xuất ở trên. Sử dụng phần mềm mô phỏng kiểm
tra chức năng hệ thống (chụp lại hình kết quả mô phỏng).
3. Đánh giá tài nguyên phần cứng khi thực thi 2 giải thuật đề xuất trên FPGA Cyclone II
EP2C35F672C6.
Đại học Bách khoa TPHCM
Trang 4
1.1.2 Giải thuật thứ nhất
Hình 1.2. Sơ đồ giải thuật thứ nhất bộ min_finder
Đầu tiên, ta ghép 2 phần gồm giá trị của port và số thứ tự của port đó vào để thực hiện so
sánh, gọi là IN[i]. Khi so sánh, nếu phần giá trị của 2 port bằng nhau, ta sẽ so sánh số thứ tự
của port đó.
Tiếp theo, ta lưu min_1 và index_min1 tương ứng với giá trị của port 0 và số thứ tự của nó:
0 và min_2 là giá trị của port 1.
Ta lần lượt so sánh cặp min_1, index_min1 và giá trị min_2 với giá trị tương ứng (có hoặc
khơng có số thứ tự) của các port từ 1 đến 9. Khi đó sẽ có 2 trường hợp xảy ra:
Thứ nhất, cặp min_1, index_min1 lớn hơn IN[i]. Khi đó, ta thay min_1, index_min1 bởi các
giá trị tương ứng của port thứ i và thay min_2 bởi min_1.
Thứ hai, cặp min_1, index_min1 bé hơn IN[i]. Ta sẽ tiếp tục so sánh giá trị của port thứ i
với min_2. Nếu min_2 lớn hơn giá trị của port thứ i thì ta cập nhật giá trị đó cho min_2 và
ngược lại thì ta giữ nguyên min_2.
Đại học Bách khoa TPHCM
Trang 5
Code thực hiện:
module
min_finder(rst,clk,in0,in1,in2,in3,in4,in5,in6,in7,in8,in9,min1,min2,index_
min1,nflag);
localparam n = 10;
input rst,clk;
input[3:0] in0,in1,in2,in3,in4,in5,in6,in7,in8,in9;
output reg[3:0] min1,min2;
output reg[3:0] index_min1;
output reg nflag;
reg[7:0]
reg_in0,reg_in1,reg_in2,reg_in3,reg_in4,reg_in5,reg_in6,reg_in7,reg_in8,reg
_in9,temp;
reg[7:0] reg_min1;
reg[3:0] reg_min2;
wire cp1,cp2,flag_0;
reg[3:0] count;
mf_compare CP1 (reg_min1,reg_in1,cp1);
cp CP2 (reg_min2,reg_in1[3:0],,cp2);
assign flag_0 = |(count);
always @(posedge clk) begin
if(rst||(~flag_0)) begin
reg_in0 = {4'b0000,in0};
reg_in1 = {4'b0001,in1};
reg_in2 = {4'b0010,in2};
reg_in3 = {4'b0011,in3};
reg_in4 = {4'b0100,in4};
reg_in5 = {4'b0101,in5};
reg_in6 = {4'b0110,in6};
reg_in7 = {4'b0111,in7};
reg_in8 = {4'b1000,in8};
reg_in9 = {4'b1001,in9};
end
else begin
temp = reg_in0;
reg_in0 = reg_in1;
reg_in1 = reg_in2;
reg_in2 = reg_in3;
reg_in3 = reg_in4;
reg_in4 = reg_in5;
reg_in5 = reg_in6;
reg_in6 = reg_in7;
reg_in7 = reg_in8;
reg_in8 = reg_in9;
reg_in9 = temp;
end
end
always @(posedge clk) begin
if(rst) begin
count = 4'b1001;
nflag = 1'b1;
end
else if(flag_0) count = count - 1;
else begin
{index_min1,min1} = reg_min1;
min2 = reg_min2;
nflag = 1'b0;
end
end
Đại học Bách khoa TPHCM
Trang 6
always @(negedge clk) begin
if (rst) begin
reg_min1 = {4'b0000,in0};
reg_min2 = in1;
end
else if(cp1&flag_0) begin
reg_min2 = reg_min1[3:0];
reg_min1 = reg_in1;
end
else if(cp2&flag_0) reg_min2 = reg_in1[3:0];
end
endmodule
module mf_compare(in0,in1,out);
input[7:0] in0,in1;
output reg out;
wire[1:0] eq, grt;
cp COMP0 (in0[3:0],in1[3:0],eq[0],grt[0]);
cp COMP1 (in0[7:4],in1[7:4],eq[1],grt[1]);
always @* begin
if(eq[0])
out <= grt[1];
else
out <= grt[0];
end
endmodule
module cp(in0,in1,eq,grt);
//grt = 1 if in1
input[3:0] in0,in1;
output eq,grt;
wire[4:0] node_eq, node_ge;
assign node_eq[0] = 1'b1;
assign node_ge[0] = 1'b1;
cp_slice SLICE0
(node_eq[0],node_ge[0],in0[0],in1[0],node_eq[1],node_ge[1]);
cp_slice SLICE1
(node_eq[1],node_ge[1],in0[1],in1[1],node_eq[2],node_ge[2]);
cp_slice SLICE2
(node_eq[2],node_ge[2],in0[2],in1[2],node_eq[3],node_ge[3]);
cp_slice SLICE3
(node_eq[3],node_ge[3],in0[3],in1[3],node_eq[4],node_ge[4]);
assign eq = node_eq[4];
assign grt = node_ge[4]&(~eq);
endmodule
module cp_slice(eq_i,ge_i,in0,in1,eq,ge);
input eq_i,ge_i,in0,in1;
output eq,ge;
wire node1;
assign node1 = ~(in0^in1);
assign eq = eq_i&node1;
assign ge = (node1&ge_i)|(in0&(~in1));
endmodule
Code testbench:
module testbench;
reg rst,clk;
reg[3:0] in0,in1,in2,in3,in4,in5,in6,in7,in8,in9;
Đại học Bách khoa TPHCM
Trang 7
wire[3:0] min1,min2;
wire[3:0] index_min1;
wire nflag;
min_finder MF
(rst,clk,in0,in1,in2,in3,in4,in5,in6,in7,in8,in9,min1,min2,index_min1,nflag
);
initial begin
rst = 0;
in0 = 1; in1 = 2; in2 = 9; in3 = 5; in4 = 7; in5 = 15; in6 = 4; in7
= 8; in8 = 11; in9 = 12; rst = 1; #2; rst = 0; #100
in0 = 11; in1 = 0; in2 = 5; in3 = 5; in4 = 7; in5 = 5; in6 = 4; in7
= 11; in8 = 11; in9 = 12; rst = 1; #2; rst = 0; #100
in0 = 11; in1 = 9; in2 = 9; in3 = 7; in4 = 7; in5 = 7; in6 = 7; in7
=
11; in8 = 11; in9 = 12; rst = 7; #2; rst = 0; #100 $finish;
end
initial begin
forever begin
clk = 0; #1;
clk = 1; #1;
end
end
initial begin
$dumpfile("waveform.vcd");
$dumpvars(1);
end
endmodule
Mơ phỏng dạng sóng:
Ở
đây em sử dụng website EDA Playground (tool Icarus Verilog 0.9.7) để mô phỏng dạng
sóng.
Hình 1.3. Mơ phỏng dạng sóng giải thuật thứ nhất cho bộ min_finder
Đại học Bách khoa TPHCM
Trang 8
Hình 1.4. Mơ phỏng dạng sóng giải thuật thứ nhất cho bộ min_finder
Đánh giá phần cứng:
Hình 1.5. Đánh giá phần cứng giải thuật thứ nhất cho bộ min_finder
Ở
đây, ta thấy thiết kế sử dụng 122 logic elements (chiếm chưa đến 1% số logic elements
của thiết bị), bao gồm: 109 hàm tổ hợp và 101 thanh ghi. Ngoài ra tổng số pins là 55 (chiếm 12%
số pins của thiết bị).
Đại học Bách khoa TPHCM
Trang 9
1.1.3 Giải thuật thứ hai
Hình 1.6. Sơ đồ giải thuật thứ hai bộ min_finder
Đầu tiên, ta lần lượt so sánh min_1 và giá trị min_2 với giá trị của các port từ 1 đến 9. Khi
đó sẽ có 2 trường hợp xảy ra:
Thứ nhất, min_1 lớn hơn giá trị của port thứ i. Khi đó, ta thay min_1 bởi giá trị của port thứ
i và thay min_2 bởi min_1.
Đại học Bách khoa TPHCM
Trang 10
Thứ hai, min_1 bé hơn giá trị của port thứ i. Ta sẽ tiếp tục so sánh giá trị của port thứ i với
min_2. Nếu min_2 lớn hơn giá trị của port thứ i thì ta cập nhật giá trị đó cho min_2 và ngược
lại thì ta giữ ngun min_2.
Sau đó, với giá trị đã có của min_1, ta tìm từ port 0 đến port 9 sao cho giá trị của port đó
bằng min_1, thì số thứ tự của port đầu tiên tìm được chính là index_min1.
Code thực hiện:
module
min_finder(rst,clk,in0,in1,in2,in3,in4,in5,in6,in7,in8,in9,min1,min2,index_
min1,nflag);
localparam n = 10;
input rst,clk;
input[3:0] in0,in1,in2,in3,in4,in5,in6,in7,in8,in9;
output reg[3:0] min1,min2;
output reg[3:0] index_min1;
output reg nflag;
reg[7:0]
reg_in0,reg_in1,reg_in2,reg_in3,reg_in4,reg_in5,reg_in6,reg_in7,reg_in8,reg
_in9,temp;
reg[7:0] reg_min1;
reg[3:0] reg_min2;
wire cp1,cp2,flag_0;
reg[3:0] count;
mf_compare CP1 (reg_min1,reg_in1,cp1);
cp CP2 (reg_min2,reg_in1[3:0],,cp2);
assign flag_0 = |(count);
always @(posedge clk) begin
if(rst||(~flag_0)) begin
reg_in0 = {4'b0000,in0};
reg_in1 = {4'b0001,in1};
reg_in2 = {4'b0010,in2};
reg_in3 = {4'b0011,in3};
reg_in4 = {4'b0100,in4};
reg_in5 = {4'b0101,in5};
reg_in6 = {4'b0110,in6};
reg_in7 = {4'b0111,in7};
reg_in8 = {4'b1000,in8};
reg_in9 = {4'b1001,in9};
end
else begin
temp = reg_in0;
reg_in0 = reg_in1;
reg_in1 = reg_in2;
reg_in2 = reg_in3;
reg_in3 = reg_in4;
reg_in4 = reg_in5;
reg_in5 = reg_in6;
reg_in6 = reg_in7;
reg_in7 = reg_in8;
reg_in8 = reg_in9;
reg_in9 = temp;
end
end
always @(posedge clk) begin
if(rst) begin
count = 4'b1001;
Đại học Bách khoa TPHCM
Trang 11
end
nflag = 1'b1;
end
else if(flag_0) count = count - 1;
else begin
{index_min1,min1} = reg_min1;
min2 = reg_min2;
nflag = 1'b0;
end
always @(negedge clk) begin
if (rst) begin
reg_min1 = {4'b0000,in0};
reg_min2 = in1;
end
else if(cp1&flag_0) begin
reg_min2 = reg_min1[3:0];
reg_min1 = reg_in1;
end
else if(cp2&flag_0) reg_min2 = reg_in1[3:0];
end
endmodule
module mf_compare(in0,in1,out);
input[7:0] in0,in1;
output reg out;
wire[1:0] eq, grt;
cp COMP0 (in0[3:0],in1[3:0],eq[0],grt[0]);
cp COMP1 (in0[7:4],in1[7:4],eq[1],grt[1]);
always @* begin
if(eq[0])
out <= grt[1];
else
out <= grt[0];
end
endmodule
module cp(in0,in1,eq,grt);
//grt = 1 if in1
input[3:0] in0,in1;
output eq,grt;
wire[4:0] node_eq, node_ge;
assign node_eq[0] = 1'b1;
assign node_ge[0] = 1'b1;
cp_slice SLICE0
(node_eq[0],node_ge[0],in0[0],in1[0],node_eq[1],node_ge[1]);
cp_slice SLICE1
(node_eq[1],node_ge[1],in0[1],in1[1],node_eq[2],node_ge[2]);
cp_slice SLICE2
(node_eq[2],node_ge[2],in0[2],in1[2],node_eq[3],node_ge[3]);
cp_slice SLICE3
(node_eq[3],node_ge[3],in0[3],in1[3],node_eq[4],node_ge[4]);
assign eq = node_eq[4];
assign grt = node_ge[4]&(~eq);
endmodule
module cp_slice(eq_i,ge_i,in0,in1,eq,ge);
input eq_i,ge_i,in0,in1;
output eq,ge;
wire node1;
Đại học Bách khoa TPHCM
Trang 12
assign node1 = ~(in0^in1);
assign eq = eq_i&node1;
assign ge = (node1&ge_i)|(in0&(~in1));
endmodule
Code testbench:
module testbench;
reg rst,clk;
reg[3:0] in0,in1,in2,in3,in4,in5,in6,in7,in8,in9;
wire[3:0] min1,min2;
wire[3:0] index_min1;
wire nflag;
min_finder MF
(rst,clk,in0,in1,in2,in3,in4,in5,in6,in7,in8,in9,min1,min2,index_min1,nflag
);
initial begin
rst = 0;
in0 = 1; in1 = 2; in2 = 9; in3 = 5; in4 = 7; in5 = 15; in6 = 4; in7
= 8; in8 = 11; in9 = 12; rst = 1; #2; rst = 0; #100
in0 = 11; in1 = 0; in2 = 5; in3 = 5; in4 = 7; in5 = 5; in6 = 4; in7
= 11; in8 = 11; in9 = 12; rst = 1; #2; rst = 0; #100
in0 = 11; in1 = 9; in2 = 9; in3 = 7; in4 = 7; in5 = 7; in6 = 7; in7
=
11; in8 = 11; in9 = 12; rst = 7; #2; rst = 0; #100
$finish;
end
initial begin
forever begin
clk = 0; #1;
clk = 1; #1;
end
end
initial begin
$dumpfile("waveform.vcd");
$dumpvars(1);
end
endmodule
Mơ phỏng dạng sóng:
Ở
đây em sử dụng website EDA Playground (tool Icarus Verilog 0.9.7) để mơ phỏng dạng
sóng.
Đại học Bách khoa TPHCM
Trang 13
Hình 1.7. Mơ phỏng dạng sóng giải thuật thứ hai cho bộ min_finder
Hình 1.8. Mơ phỏng dạng sóng giải thuật thứ hai cho bộ min_finder
Đánh giá phần cứng:
Hình 1.9. Đánh giá phần cứng giải thuật thứ hai cho bộ min_finder
Đại học Bách khoa TPHCM
Trang 14
Ở
đây, ta thấy thiết kế sử dụng 122 logic elements (chiếm chưa đến 1% số logic elements
của thiết bị), bao gồm: 109 hàm tổ hợp và 101 thanh ghi. Ngoài ra tổng số pins là 55 (chiếm 12%
số pins của thiết bị). Từ đó, ta nhận thấy rằng phần cứng sử dụng của hai thiết kế là khá tương
đương nhau.
Đại học Bách khoa TPHCM
Trang 15
1.2
Bài 2
1.2.1 Đề bài
Tìm hiểu ít nhất 1 giải thuật và viết code Verilog tính gần đúng giá trị log2(x), với x
là số 16 bit không dấu.
Sử dụng phần mềm mô phỏng kiểm tra chức năng hệ thống (chụp lại hình kết
quả mơ phỏng). Đánh giá sai số giữa kết quả mô phỏng này với kết quả dùng phần mềm Matlab.
Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6.
1.2.2 Cơ sở lý thuyết
Phép toán logarit được sử dụng rộng rãi trong xử lý tín hiệu số. Có nhiều ứng dụng
khoa học u cầu tính tốn logarit.
Một phép tốn logarit nhị phân có thể được xác định theo phương trình (1):
= log2( ) (1)
Đảo phương trình (1) ta được phương trình (2):
(2)
=2
y
có thể được biểu diễn dưới dạng nhị phân như có thể thấy trong phương trình (3):
= ∑∞
2− =
=1
2−1 + 2−2
1
với:
= 0 hoặc
2
Đại học Bách khoa TPHCM
−1
+ 22−2+ 32−3+⋯
+⋯
3
=1
Đưa phương trình (3) vào phương trình (2) ta được phương trình (4) như sau:
= 2 12
+ 2−3
(4)
Trang 16
Từ phương trình (3) và (4) có thể suy ra rằng giá trị lớn nhất của y là 1 (tổng của một
cấp tiến hình học với tỷ lệ chung 0,5 khi tất cả các bit của y là 1) và do đó giá trị lớn nhất của
x là 2.
Phương trình bình phương (4) cho phương trình (5) như có thể thấy dưới đây:
2
2 + 2 + 2 +⋯
Từ phương trình (5) cho biết giá trị của có thể được biểu thị trong 2 trường hợp:
−1
= 2 12 2
3
−2
3
−3
(5)
2
=0;
2
=1;
2
= 2 22−1+
32
−2
−3
+ 32 +⋯
(6)
{1
= 2 × 2 22−1+
32
−2
+ 32
−3
+⋯
1
2
Theo phương trình (6) nếu giá trị
trị của x sẽ chia cho 2, ngược lại, nếu
2
> 2, thì bit thứ i của là 1 ở lần lặp thứ i và giá
≤ 2,
= 0.
Vì thuật toán nhị phân hoạt động cho 0 ≤ ≤ 1, nếu x lớn hơn 1, x sẽ được chia tỷ lệ như có thể thấy bên dưới:
= 2 × , với 0 ≤
(Ta có với mọi giá trị của x, 2 ≤ < 2
Đại học Bách khoa TPHCM
+1
≤ 1 hay
2(
)= +
2(
) (7)
⇔ ≤ log2 < + 1, nói cách khác k chính là phần nguyên của kết quả ngõ ra của bài toán)
Trang 17
1.2.3 Giải thuật tính tốn
Từ các phương trình đã trình bày ở mục 1.2.2, ta sẽ xây dựng được lưu đồ giải thuật
để tìm y khi biết x như sau:
Đại học Bách khoa TPHCM
Trang 18
1.2.4 Code mô phỏng
Code thực hiện
module log2(clk,rst,in,out,flag,inf);
input[15:0] in;
input clk, rst;
output reg[15:0] out;
output reg flag, inf;
reg[15:0] sqr_x,temp;
reg[2:0] state;
reg[3:0] count;
wire[3:0] itg;
reg[11:0] frac;
=
parameter[2:0] INIT = 0, PRESQUARE = 1, SQUARE = 2, CHECK_BIT = 3, DONE
4;
log2_itg INTEGER_PART (in,itg);
always @(posedge clk) begin
if(rst) begin
state <= INIT;
inf <= 0;
flag <= 0;
sqr_x <= in;
end
else begin
case(state)
INIT: begin
if(!(|in[15:1])) begin
state <= DONE;
frac <= 0;
if(!in[0]) inf <= 1;
end
else if(!sqr_x[15]) begin
state <= INIT;
sqr_x <= sqr_x << 1;
end
else begin
count <= 12;
state <= PRESQUARE;
inf <= 0;
end
end
PRESQUARE: begin
if(|count == 0) state <= DONE;
else state <= SQUARE;
end
SQUARE: begin
{sqr_x,temp} <= sqr_x[15:0]*sqr_x[15:0];
state <= CHECK_BIT;
frac <= frac<<1;
end
CHECK_BIT: begin
casex(sqr_x[15:14])
2'b1x: begin
frac[0] <= 1;
end
2'b1: begin
frac[0] <= 0;
sqr_x <= {sqr_x[14:0],temp[15]};
end
Đại học Bách khoa TPHCM
Trang 19