initial begin $dumpfile"waveform.vcd"; $dumpvars1; 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 n
Trang 1Trườ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 [1813312]
Vũ Châu Duy Tùng [1614015] Đào Việt Hoàng [1812253]
Trần Nhân Tông [1915574]
Nguyễn Ngọc Độ [1913131]
Trang 2BÁO CÁO KẾT QUẢ LÀM VIỆC NHÓM
THỰC HIỆN
Trang 3Bài 1:
Trang 51.2 Lưu đồ giải thuật:
Trang 6- Đánh giá tài nguyên:
Trang 7- Kết quả mô phỏng:
Trang 81.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
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
Trang 91.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<B
- Gán result = {Oe, Og, Ol}
- Khai báo:
input [3:0] A, B;
output Oe, Og, Ol;
wire [1:0] A0, A1, B0, B1;
- 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}
- Khai báo:
input [1:0] A, B;
Trang 10output 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]);
Trang 11- 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
+ 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 tiếp nhau
Trang 12❖ Đánh giá tài nguyên và kết quả mô phỏng giải thuật 2:
Trang 13input [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;
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);
Trang 14- 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);
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]);
Trang 15find_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]);
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
Trang 16min_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;
Trang 17Câ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 quá 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 (2𝑘 × 𝑥 ) = 𝑘 + log 2𝑘 2 2𝑘 𝑥
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 nguyên với nguyên tắc của bộ priority encoder 16 to 4
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;
Trang 18else if(in1[1]==1'b1) out1=4'b0001;
else if(in1[0]==1'b1) out1=4'b0000;
Y có thể biểu diễn dưới dạng nhị phân:
Khi viết code ta sẽ biến( 𝑥 )2 thành ( 𝑥 15 sau đó ta sẽ so sánh bằng với 22 31 kết quả tương tự với 𝑥 2 so sánh với 2 2𝑘 2 𝑘 × 2 )
Giải thuật:
(2𝑘)
𝑦 = ∑
Trang 19X=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;
Trang 20reg[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
begin if(!(|in[15:1])) begin
state <= BAT_DAU;
Trang 21sqr <= 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
end
BINH_PHUONG:
begin {sqr,temp}<= sqr1 ;
state <= SO_SANH;
frac <= frac << 1;
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
end
frac[0] <= 1;
2'b01: // b= 2^30, tương đướng với (x/2^k)<2
Trang 22end KET_THUC:
begin flag <= 1;
frac[0] <= 1'bz;
state <= KTRA_DEM; count <= count1 ;
out <= {itg,frac};
end default: state <= BAT_DAU;
Trang 24initial 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
Trang 25Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone V 5CGXFC7C7F23C8:
Trang 26Bài 3
Đề 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ị biểu thức
√𝑥2 + 𝑦2, với x và y là các số 16 bit không dấu
1 Sử dụng phần mềm mô phỏng kiểm tra chức năng hệ thống (chụp lại màn 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
2 Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II EP2C35F672C6
Giải thuật tính căn tính toán từng chữ số (Digit-by-digit calculation)
Đây là một phương pháp để tìm từng chữ số của căn bậc hai theo một chuỗi Có một số lợi thế như:
• Nó có thể dễ dàng cho tinh toán thủ công
• Mỗi chữ số của gốc được tìm thấy đều đúng, sẽ không bị thay đổi sau này
• Có thể sử dụng để kiểm tra một số nguyên đã cho có phải số bình phương không
Nguyên tắc cơ bản:
Xét trường hợp tìm căn của một số z, là bình phương của hai số xy Trong đó x là chữ số hàng chục, y là chữ số hàng đơn vị: 𝑧 = (10𝑥 + 𝑦)2 = 100𝑥2 + 20𝑥𝑦 +
𝑦2
Sử dụng thuật toán từng chữ số, đầu tiên xác định giá trị của x x là chữ số lớn
Lần lặp tiếp theo, ghép các chữ số, nhân x với 2 và đặt nó ở vị trí hàng chục và tiếp tục tìm giá trị của y
Vì đây là một trường hợp đơn giản căn bậc 2 là xy, thuật toán dừng lại ở đây
Hệ thập phân (Hệ cơ số 10)
Bắt đầu với cặp chữ số từ bên trái, thực hiện theo từng cặp
1 Bắt đầu từ bên trái, hạ chứ số ngoài cùng bên trái xuống chưa được sử dụng (nếu các chữ số đã được dùng hãy viết “00”) và viết chúng vào bên phải phần
Trang 27còn lại của bước trước (bước đầu không có phần dư) Đây là giá trị hiện tại của c
2 Tìm các số q, y và x, như sau:
Gọi q là phần căn tìm được đến hiện tại, bỏ qua dấu thập phân (bước đầu q
=0)
Xác định chữ số lớn nhất x sao cho 𝑥(20𝑞 + 𝑥 ) ≤ 𝑐 Ta có 𝑦 = 𝑥(20𝑞 + 𝑥 )
Đặt chữ số x là chữ số tiếp theo của căn bậc Do đó 𝑞 = 10𝑞 + 𝑥
3 Trừ y với c để tạo thành phần dư mới
4 Nếu phần dư bằng không và không còn chữ số nào để hạ thì thuật toán kết thúc Nếu chưa quay lại bước 1 tính toán lần nữa
Kề thừa thuật toán từng chứ số:
X: Giá trị đầu vào và giá trị muốn tính căn
A: Giá trị hiện tại đang tính toán
Trang 28T: Kết quả phép thử dấu
Q: Căn bậc 2
Bắt đầu với cặp chữ số từ bên trái, thực hiện theo từng cặp 2 chữ số
1 Dịch trái X 2 bit sang vị trí của A Gán T = A – {Q,01}
Vậy căn của 110.012 (6.2510) là 10.12 (2.510)
Code thực hiện và kết quả mô phỏng
Trang 32Nhận xét: Kết quả thu được trên ModelSim có kết quả nhỏ hơn khi dùng ngôn ngữ
Python đê tính do đây là thuật toán tính căn từng chữ số, thiết kế chỉ lấy 8 bit sau dấu phẩy làm đồ chính xác chưa cao Để khắc phục có thể tăng số bit sau dấu phẩy để tăng độ chính xác
Kết quả đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone II
EP2C35F672C6
Code sử dụng 57 pins (1 chân clk, 32 chân thể hiện 16 bit của x và y, 24 chân thể hiện giá trị căn) chiếm 21%
Tổng số phần tử logic 564 chiếm dưới 1%
Tổng số thanh ghi dùng 24 chiếm <1%
Trang 33Bài 4
Cho 2 số M và N, mỗi số 32 bit không dấu Thực hiện phép toán cộng: M + N bằng 2 cách:
• Cách 1: cộng nối tiếp từng bit (hệ tuần tự)
• Cách 2: cộng song song 32 bit cùng lúc (hệ tổ hợp) bằng giải thuật Carry Look-Ahead Adder
kiểm tra chức năng hệ thống (chụp lại hình kết quả mô phỏng) SV kiểm tra với ít nhất 10 giá trị
5CGXFC7C7F23C8
Cơ sở thiết kế:
Các mạch cộng cơ bản được xây dựng trên mạch cộng toàn phần FullAdder
Mạch FullAdder có:
- 3 ngõ vào x, y, cin (bit nhớ đầu)
- 2 ngõ ra sum (tổng của phép tính) và cout (bit nhớ của phép cộng)
Với biểu thức ngõ ra:
sum = x y cin
cout = x.y + cin.(x y)
Bảng chân trị của FullAdder:
Trang 34x
sum
cout cin
Cách 1: cộng nối tiếp từng bit:
Khi cộng nối tiếp từng bit của hai số, đầu tiên thực hiện cộng 2 bit LSB (và cộng bit nhớ cin ban đầu nếu có), sau đó tổng 2 bit LSB (sum) sẽ được đưa ra ở một thanh ghi dịch còn bit nhớ “cout” sẽ quay về “cin” để cộng chung với 2 bit kế tiếp bit LSB Mạch ghi dịch ngõ ra dịch chuyển sang phải qua mỗi lần cộng, số nhớ cuối cùng sẽ là MSB của tổng Mạch cần hoạt động cùng 1 xung nhịp để cho mạch làm việc đồng bộ Khi ngõ vào
là 1 số n bit sẽ tạo ra số (n+1) bit không dấu với MSB là bit nhớ cuối
Code thực hiện:
Trang 35wire [data:0] sum;
SerialAdder testAdd (m, n, reset, clk, sum);
endmodule
Trang 36No Carry Generate
No Carry Propogate
Pi = 1 khi A = 1 hoặc B = 1 hoặc carry-out bằng C, P được gọi là cờ Propogate vì carry-
in được truyền (propogate) ở tầng cộng thứ i
Giá trị Tổng (sum) và carry-out có thể được viết dưới G và P là:
Trang 37input [data -1 :0] in1;
input [data -1 :0] in2;
input carry_in;
//outputs
output [data -1 :0] sum;
output carry_out;
wire [data -1 :0] G; // carry generate
wire [data -1 :0] P; // carry propagate
wire [data :0] carry_tmp; // carry temporary
for(j = 0; j < data; j = j + 1) begin: carry_generator
assign G[j] = in1[j] & in2[j];
assign P[j] = in1[j] | in2[j];
assign carry_tmp[j+1] = G[j] | P[j] & carry_tmp[j]; end
//carry out
assign carry_out = carry_tmp[data];
//Sum
for(i = 0; i < data; i = i+1) begin: sum_without_carry
assign sum[i] = in1[i] ^ in2[i] ^ carry_tmp[i]; end
endgenerate
endmodule
Trang 38module testbench();
parameter data = 16;
reg carry_in;
reg [data-1:0] in1;
reg [data-1:0] in2;
#2 carry_in = 0; in1 = 32'd23; in2 = 32'd11;
#2 carry_in = 1; in1 = -32'hFFFF; in2 = 32'd11;
#2 carry_in = 0; in1 = 32'd23; in2 = 32'd51;
#2 carry_in = 1; in1 = -32'd17; in2 = 32'd44;
#2 carry_in = 0; in1 = 32'd23; in2 = 32'd11;
#2 carry_in = 1; in1 = -32'd3; in2 = 32'd1;
#2 carry_in = 0; in1 = 32'd23; in2 = 32'd51;
#2 carry_in = 1; in1 = -32'd23; in2 = 32'd11;
#2 carry_in = 0; in1 = 32'd43; in2 = 32'd01;
#2 carry_in = 1; in1 = -32'd03; in2 = -32'd11; end
endmodule
Code testbench
Trang 39Đánh giá tài nguyên phần cứng khi thực thi trên FPGA Cyclone V
5CGXFC7C7F23C8:
Kết quả mô phỏng:
Trang 40Giải thuật nhân Modified Booth hay còn gọi là Radix-4 sẽ đối
chiếu 3 bit có trọng số thấp nhất của số nhân Y với bộ mã hóa,
cho ra kết quả như bảng bên Sau đó tiến hành cộng số bị nhân A
với (0, ±1, ±2) xY tương ứng, và dịch phải toán học 2 bit
Lặp lại cho đến khi: Số lần lặp = (số bit/2)