Tải bản đầy đủ (.docx) (53 trang)

(TIỂU LUẬN) báo cáo bài tập lớn môn xử lí tín hiệu số với FPGA

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.31 MB, 53 trang )

Trường Đại học Bách Khoa
Đại học Quốc Gia Thành Phố Hồ Chí Minh

BÁO CÁO BÀI TẬP LỚN
Mơn: Xử lí tín hiệu số với FPGA
GVHD: Thầy Trịnh Vũ Đăng Nguyên

Thực hiện bởi: nhóm 4
Phạm Thanh Nhàn
Vũ Châu Duy Tùng
Đào Việt Hồng
Trần Nhân Tông
Nguyễn Ngọc Độ


BÁO CÁO KẾT QUẢ LÀM VIỆC NHÓM

STT
1
2
3
4
5


Bài 1:

1.1.

Đề bài:




1.2.

Lưu đồ giải thuật:

1.2.1. Giải thuật 1:
-

Khai báo:
input [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min1, min2, index_min1; reg [63:0] arr;

reg [3:0] min1, min2, index_min1;
integer i;

- Mỗi khi có sự thay đổi ở tất cả các ngõ vào, ta có:


-

Đánh giá tài nguyên:


-

Kết quả mô phỏng:


1.2.2. Giải thuật 2:

-

Khai báo:
input [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min1, min2, index_min1; wire [3:0] index_min2;

wire [63:0] arr, new_arr;
assign arr = {I15, I14, I13, I12, I11, I10, I9, I8, I7, I6, I5, I4, I3, I2, I1, I0};
-

Ta dùng module find_min_in_arr để tìm min1 và index_min1 trong arr

-

Ta dùng module replace15_by_index để thay thế giá trị tại vị trí index_min1 thành
15, thu được chuỗi mới new_arr

-

Ta dùng module find_min_in_arr để tìm min2 trong new_arr

1.2.2.1 .
-

Module find_min_in_arr:

Khai báo:
input [63:0] arr;
wire [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min, index_min;

wire [3:0] min_val_a [7:0], id_out_a [7:0];
wire [3:0] min_val_b [3:0], id_out_b [3:0];
wire [3:0] min_val_c [1:0], id_out_c [1:0];
assign {I15, I14, I13, I12, I11, I10, I9, I8, I7, I6, I5, I4, I3, I2, I1, I0}
= arr;

-

Trong module này, ta tiến hành so sánh từng cặp giá trị để tìm min và id của giá trị
min đó, với id là số tự nhiên tương ứng với chỉ số của từng input, ví dụ: id của I0
là 0, của I1 là 1, …, của I15 là 15.

-

Có 16 input nên ta sẽ chia làm 4 round, round 1 có 16 input nên chia ra thành 8 cặp
để so sánh, ngõ ra của round 1 được đưa vào round 2 và lúc này chỉ còn 4 cặp để
so sánh. Tương tự vậy đến round 4 ta chỉ còn 2 input tạo thành một cặp giá trị để
so sánh, ngõ ra của phép so sánh này cũng chính là ngõ ra của module.

-

Module được sử dụng để so sánh cặp giá trị là find_min_index


1.2.2.2.
-

Module find_min_index:

Khai báo:

input [3:0] A, B, idA, idB;
output [3:0] min_val, id_out;
wire Oe, Og, Ol;
wire [2:0] result;
reg [3:0] min_val, id_out;

-

Dùng module compare_4bit để so sánh A và B, giá trị trả về dưới dạng one hot
vector {Oe, Og, Ol} tương ứng với các trạng thái A=B, A>B và A
-

Gán result = {Oe, Og, Ol}
+

result=3'b001,3'b100: min_val = A; id_out = idA;

+

result=3'b010: min_val = B; id_out = idB;

+

Các TH còn lại: min_val = 4'bx; id_out = 4'bx;

1.2.2.3.
-

Module compare_4bit:


Khai báo:
input [3:0] A, B;
output Oe, Og, Ol;
wire [1:0] A0, A1, B0, B1;
wire [1:0] R0, R1;

-

Phân tách mỗi ngõ vào A, B thành 2 phần {A1, A0} và {B1, B0}:
assign A0 = A[1:0];
assign A1 = A[3:2];
assign B0 = B[1:0];
assign B1 = B[3:2];

-

Ứng với từng cặp (A1, B1), (A0, B0), ta đưa vào module compare_2bit thu được 2
output R1, R0

-

Cặp giá trị R1, R0 được đưa vào ngõ vào của module compare_result để đưa ngõ
ra về dạng {Oe, Og, Ol}

1.2.2.4.
-

Module compare_2bit:


Khai báo:
input [1:0] A, B;


output [1:0] R;
-

Phép toán dựa trên bảng chân trị và bìa K:

assign R[1] = (~A[0]&B[0])|(A[0]&~B[0])|(~A[1]&B[1])|(A[1]&~B[1]);
assign R[0]=(~A[1]&~A[0])|(~A[1]&B[0])|(~A[1]&B[1])|(B[1]&~A[0])|(B[1]&B[0]);
-

Giải thích:
+ Khi A=B: R=1;
+ Khi A>B: R=2;
+ Khi A
-

Bảng chân trị:

A[1]
0
0
0
0
0
0
0

0
1
1
1
1
1
1
1
1

1.2.2.5.
-

Module compare_result:

Khai báo:
input [1:0] R0, R1;
output Oe, Og, Ol;

-

Phép toán dựa trên bảng chân trị và bìa K:
assign Oe = ~R1[1]&R1[0]&~R0[1]&R0[0];
assign Og = (R1[1]&~R1[0])|(~R1[1]&R1[0]&R0[1]&~R0[0]);
assign Ol = (R1[1]&R1[0])|(R1[0]&R0[1]&R0[0]);


-

Giải thích:

+ Theo ý tưởng của module này, R1 là kết quả so sánh của cặp số 2 bit trọng số cao

của cặp giá trị 4 bit cần so sánh, R0 là kết quả so sánh của cặp số 2 bit trọng số thấp
+ Khi R1=0 hoặc R0=0 thì ngõ ra là vơ định
+ Khi R1=1 thì kết quả phép so sánh phụ thuộc vào R2
+ Khi R1=2 thì kết quả so sánh là lớn hơn
+ Khi R1=3 thì kết quả so sánh là nhỏ hơn
-

Bảng chân trị:

R1[1]
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1

R1[0]

0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1

1.2.2.6.
-

Module replace15_by_index:

Khai báo:
input [63:0] arr_in;
output [63:0] arr_out;
input [3:0] index;

-

Phép toán:

assign arr_out = arr_in | (15 << index*4);

-

Giải thích:
+ Module này dùng để thay giá trị của số 4 bit (trong 1 chuỗi gồm 16 số 4 bit nối với nhau)
thành 15 dựa trên chỉ số vị trí index của nó trong chuỗi số.
+ Module này dùng như 1 phương pháp xoá đi giá trị nhỏ nhất trong một chuỗi gồm
nhiều số 4 bit liên tếp nhau.




Đánh giá tài nguyên và kết quả mô phỏng giải thuật 2:


1.3.

Code Verilog:
Giải thuật 1:
`timescale 1ns / 100ps
module min_finder_1(I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, min1, min2,
index_min1);
input [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min1, min2, index_min1;
reg [63:0] arr;
reg [3:0] min1, min2,
index_min1; integer i;
always@(I0 or I1 or I2 or I3 or I4 or I5 or I6 or I7 or I8 or I9 or I10 or I11 or I12 or I13
or I14 or I15)

begin
min1 = 15;
min2 = 15;
arr = {I15, I14, I13, I12, I11, I10, I9, I8, I7, I6, I5, I4, I3, I2, I1, I0};
for (i=0; i<16; i=i+1)
if (arr[i*4 +: 4] < min1)
begin
index_min1 = i;
min1 = arr[i*4 +: 4];
end
else if (arr[i*4 +: 4] < min2)
min2 = arr[i*4 +: 4];
end
endmodule
module test_bench_1(min1, min2, index_min1);
output [3:0] min1, min2, index_min1;
reg [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
min_finder_1 test3(I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, min1,
min2, index_min1);
initial
begin
I0=2; I1=3; I2=1; I3=2; I4=5; I5=6; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9; #1
I0=1; I1=4; I2=2; I3=1; I4=2; I5=12; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9; #1
I0=5; I1=2; I2=10; I3=0; I4=4; I5=1; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9;
end
endmodule
-



- Giải thuật 2:
`timescale 1ns / 100ps
module test_bench_2(min1, min2, index_min1);
output [3:0] min1, min2, index_min1;
reg [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
min_finder_2 test4(I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, min1,
min2, index_min1);
initial
begin
I0=2; I1=3; I2=1; I3=2; I4=5; I5=6; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9; #1
I0=1; I1=4; I2=2; I3=1; I4=2; I5=12; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9; #1
I0=5; I1=2; I2=10; I3=0; I4=4; I5=1; I6=9; I7=9; I8=9; I9=9; I10=9; I11=9;
I12=9; I13=9; I14=9; I15=9;
end
endmodule
module min_finder_2(I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, min1, min2,
index_min1);
input [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min1, min2, index_min1;
wire [3:0] index_min2;
wire [63:0] arr, new_arr;
assign arr = {I15, I14, I13, I12, I11, I10, I9, I8, I7, I6, I5, I4, I3, I2, I1, I0};

find_min_in_arr fma1(arr, min1, index_min1);
replace15_by_index rbi(arr, index_min1, new_arr);
find_min_in_arr fma2(new_arr, min2, index_min2);

endmodule
module find_min_in_arr(arr, min, index_min);
input [63:0] arr;
wire [3:0] I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15;
output [3:0] min, index_min;
wire [3:0] min_val_a [7:0], id_out_a [7:0];
wire [3:0] min_val_b [3:0], id_out_b [3:0];
wire [3:0] min_val_c [1:0], id_out_c [1:0];
assign {I15, I14, I13, I12, I11, I10, I9, I8, I7, I6, I5, I4, I3, I2, I1, I0} = arr;
// round 1
find_min_index match_a0(I0, I1, 0, 1, min_val_a[0], id_out_a[0]);
find_min_index match_a1(I2, I3, 2, 3, min_val_a[1], id_out_a[1]);
find_min_index match_a2(I4, I5, 4, 5, min_val_a[2], id_out_a[2]);


find_min_index match_a3(I6, I7, 6, 7, min_val_a[3], id_out_a[3]); find_min_index
match_a4(I8, I9, 8, 9, min_val_a[4], id_out_a[4]); find_min_index match_a5(I10,
I11, 10, 11, min_val_a[5], id_out_a[5]); find_min_index match_a6(I12, I13, 12, 13,
min_val_a[6], id_out_a[6]); find_min_index match_a7(I14, I15, 14, 15,
min_val_a[7], id_out_a[7]); // round 2

find_min_index match_b0(min_val_a[0], min_val_a[1], id_out_a[0], id_out_a[1],
min_val_b[0], id_out_b[0]);
find_min_index match_b1(min_val_a[2], min_val_a[3], id_out_a[2], id_out_a[3],
min_val_b[1], id_out_b[1]);
find_min_index match_b2(min_val_a[4], min_val_a[5], id_out_a[4], id_out_a[5],
min_val_b[2], id_out_b[2]);
find_min_index match_b3(min_val_a[6], min_val_a[7], id_out_a[6],
id_out_a[7], min_val_b[3], id_out_b[3]);
// round 3

find_min_index match_c0(min_val_b[0], min_val_b[1], id_out_b[0],
id_out_b[1], min_val_c[0], id_out_c[0]);
find_min_index match_c1(min_val_b[2], min_val_b[3], id_out_b[2],
id_out_b[3], min_val_c[1], id_out_c[1]);
// round 4
find_min_index match_d(min_val_c[0], min_val_c[1], id_out_c[0], id_out_c[1], min,
index_min);
endmodule
module replace15_by_index(arr_in, index,
arr_out); input [63:0] arr_in;
output [63:0] arr_out;
input [3:0] index;
assign arr_out = arr_in | (15 << index*4);
endmodule
module find_min_index(A, B, idA, idB, min_val,
id_out); input [3:0] A, B, idA, idB;
output [3:0] min_val, id_out;
wire Oe, Og, Ol;
wire [2:0] result;
reg [3:0] min_val, id_out;
compare_4bit compare_4bit_1(A, B, Oe, Og,
Ol); assign result = {Ol, Og, Oe}; always @(*)
case (result)
3'b001,3'b100:
begin


min_val = A;

id_out = idA;

end
3'b010:
begin
min_val = B;
id_out = idB;
end
default
begin
min_val = 4'bx;
id_out = 4'bx;
end
endcase
endmodule
module compare_4bit(A, B, Oe, Og, Ol);
input [3:0] A, B;
output Oe, Og, Ol;
wire [1:0] A0, A1, B0, B1;
wire [1:0] R0, R1;
assign A0 = A[1:0];
assign A1 = A[3:2];
assign B0 = B[1:0];
assign B1 = B[3:2];
compare_2bit compare1(A1, B1, R1);
compare_2bit compare0(A0, B0, R0);
compare_result cr(R1, R0, Oe, Og, Ol);
endmodule
module compare_result(R1, R0, Oe, Og, Ol);
input [1:0] R0, R1;
output Oe, Og, Ol;
assign Oe = ~R1[1]&R1[0]&~R0[1]&R0[0];

assign Og = (R1[1]&~R1[0])|(~R1[1]&R1[0]&R0[1]&~R0[0]);
assign Ol = (R1[1]&R1[0])|(R1[0]&R0[1]&R0[0]);
endmodule
module compare_2bit(A, B, R);
input [1:0] A, B;
output [1:0] R;
assign R[1] = (~A[0]&B[0])|(A[0]&~B[0])|(~A[1]&B[1])|(A[1]&~B[1]);
assign R[0] = (~A[1]&~A[0])|(~A[1]&B[0])|(~A[1]&B[1])|(B[1]&~A[0])|
(B[1]&B[0]); endmodule


Câu 2:
Tính giá trị log2( ), với

là số 16 bit không dấu

Giả sử log2( ) = , …, Vậy ta có thể quy q trình tính log2( ) về 2 phần : tính phần
nguyên (integer) k (4 bit) và phần phân số (fractional part) (12 bit).
( ) = log2
log2

Với phần nguyên ta áp dụng tính chất số nhị phân n bit có 2 giá trị từ 0 đến 2 − 1, ta
có thể tím ra phần ngun với ngun tắc của bộ priority encoder 16 to 4
Code:
module log2_itg(in1,out1);
input [15:0]in1;
output reg[3:0] out1;
always@(in1 or out1)
begin
if(in1[15]==1'b1) out1=4'b1111;

else if(in1[14]==1'b1) out1=4'b1110;
else if(in1[13]==1'b1) out1=4'b1101;
else if(in1[12]==1'b1) out1=4'b1100;
else if(in1[11]==1'b1) out1=4'b1011;
else if(in1[10]==1'b1) out1=4'b1010;
else if(in1[9]==1'b1) out1=4'b1001;
else if(in1[8]==1'b1) out1=4'b1000;
else if(in1[7]==1'b1) out1=4'b0111;
else if(in1[6]==1'b1) out1=4'b0110;
else if(in1[5]==1'b1) out1=4'b0101;
else if(in1[4]==1'b1) out1=4'b0100;
else if(in1[3]==1'b1) out1=4'b0011;
else if(in1[2]==1'b1) out1=4'b0010;


else if(in1[1]==1'b1) out1=4'b0001;
else if(in1[0]==1'b1) out1=4'b0000;

else
out1=4'bzzzz;
end
endmodule
Với phần phân số: Đặt

Giả sử log2 = →

2

= ,1≤ <2


=2,0≤ <1

Y có thể biểu diễn dưới dạng nhị phân:
=∑

12



× 2 =1 × 2

=1

−1

−2

+2 × 2

+3 × 2

−3

+ ⋯, trong đó yi = 1 hoặc 0

→ = 2 1×2−1+ 2×2−2+ 3×2−3+⋯
→ 2 = 2 1 × 2 2×2−1+ 3×2−2+ 4×2−3+⋯

Nếu:{


1
=1→ 2=2×2 2×2

1

Sau đó ta chia cho 2 và kiểm tra bit tiếp theo
2

Khi viết code ta sẽ biến( ) thành (
tương tự với
Giải thuật:

2

( )
2

2

so sánh v


Bắt đầu

k

x/2^k

i>=0?


YES
X=x*x

Y(i)=0

i=i-1

No

X>=2?

YES
Y(i)=1
x=x>>1
i=i-1

Code:
module log_2(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,temp;
wire [31:0] sqr1;
reg[2:0] state;
reg[3:0] count;
wire[3:0] cout1;
wire[3:0] itg;

No


Kết thúc


reg[11:0] frac;
parameter[2:0] BAT_DAU = 0,KTRA_DEM = 1,BINH_PHUONG =
2,SO_SANH = 3,KET_THUC = 4;

log2_itg ITG1 (in,itg);
subtractor SB1 ( .a(count), .b(cout1) );
Multiplier Multi1 ( .a(sqr), .b(sqr), .result(sqr1) );

always @(posedge clk)
if(rst) begin
state <= BAT_DAU;
inf <= 0;
flag <= 0;
sqr <= in;
end
else begin
case (state)
BAT_DAU:
begin
if(!(|in[15:1])) begin
state <= KET_THUC;
frac <= 0;
if(!in[0]) inf <= 1;
end
// biến x/2^k thành x/2^k*2^15
else if(!sqr[15]) begin

state <= BAT_DAU;


sqr <= sqr << 1;
end
else begin
count <= 12;
state <= KTRA_DEM;
inf <= 0;
end
end
KTRA_DEM:
begin
if(|count == 0) state <= KET_THUC;
else state <= BINH_PHUONG;
end
BINH_PHUONG:
begin
{sqr,temp}<= sqr1 ;
state <= SO_SANH;
frac <= frac << 1;
end
SO_SANH:
begin
casex(sqr[15:14]) // so sánh với x^31
2'b1x:

// b= 2^31, tương đướng với
(x/2^k)>2


begin
frac[0] <= 1;
end
2'b01: // b= 2^30, tương đướng với (x/2^k)<2


begin
frac[0] <= 0;
sqr <= {sqr[14:0],temp[15]};
end
default:
begin

frac[0] <= 1'bz;
end
endcase
state <= KTRA_DEM;
count <= count1 ;
end
KET_THUC:
begin
flag <= 1;
out <= {itg,frac};
end
default: state <= BAT_DAU;
endcase
end
endmodule
Code testbench:
module testbench;

reg rst,clk;
reg[15:0] in;
wire[15:0] out;


wire flag,inf;
log_2 LOG2 (clk,rst,in,out,flag,inf);
initial begin
rst = 0;
in = 4; rst = 1; #2; rst = 0; #200;
in = 6557; rst = 1; #2; rst = 0; #200;
in = 1278; rst = 1; #2; rst = 0; #200;
in = 25698; rst = 1; #2; rst = 0; #200;
in = 32768; rst = 1; #2; rst = 0; #200;

in = 0; rst = 1; #2; rst = 0; #200;
in = 1; rst = 1; #2; rst = 0; #200;
in = 1024; rst = 1; #2; rst = 0; #200;
in = 256; rst = 1; #2; rst = 0; #200;
in = 13; rst = 1; #2; rst = 0; #200;
in = 51; rst = 1; #2; rst = 0; #200;
in = 32; rst = 1; #2; rst = 0; #200;
in = 101; rst = 1; #2; rst = 0; #200;
in = 2; rst = 1; #2; rst = 0; #200;
in = 65535; rst = 1; #2; rst = 0; #200;

$finish;
end
initial begin
forever begin

clk = 0; #1;
clk = 1; #1;
end
end


initial begin
$dumpfile("waveform.vcd");
$dumpvars(1);
end
endmodule
Kết quả mô phỏng:

Kết quả mô phỏng MATLAP:

Kết quả mơ phỏng có sự tương đồng với kết quả tính toán được, với sai số lớn nhất
10^-4


Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone V 5CGXFC7C7F23C8:


×