initial begin$dumpfile"waveform.vcd"; $dumpvars1; endendmodule 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ấ
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
Vũ Châu Duy Tùng Đào Việt Hoàng Trần Nhân Tông Nguyễn Ngọc Độ
Trang 2BÁO CÁO KẾT QUẢ LÀM VIỆC NHÓM
THỰC HIỆN
Trang 3Bài 1:
1.1 Đề bài:
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:
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}
- 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ủaI1 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õ racủ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:
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}
+ result=3'b001,3'b100: min_val = A; id_out = idA;
+ Các TH còn lại: min_val = 4'bx; id_out = 4'bx;
1.2.2.3 Module compare_4bit:
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}
1.2.2.4 Module compare_2bit:
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ố caocủ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 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;
min1 = arr[i*4 +: 4];
endelse if (arr[i*4 +: 4] < min2)
min2 = arr[i*4 +: 4];
endendmodule
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]);
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
Trang 16min_val = A;
id_out = idA;
end3'b010:
beginmin_val = B;
id_out = idB;
enddefault
beginmin_val = 4'bx;
id_out = 4'bx;
endendcase
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)
log 2
2Vớ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:
Sau đó ta chia cho 2 và kiểm tra bit tiếp theo
Khi viết code ta sẽ biến( )2 thành ( 15 2sau đó ta sẽ so sánh bằng với 231 kết quả
Trang 19Bắt đầu
k
x/2^k
Y(i)=0 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
case (state)BAT_DAU:
beginif(!(|in[15:1])) begin
state <= BAT_DAU;
Trang 21sqr <= sqr << 1;
endelse begin
count <= 12;
state <= KTRA_DEM;
inf <= 0;
endendKTRA_DEM:
begin
if(|count == 0) state <= KET_THUC;
else state <= BINH_PHUONG;
Trang 22frac[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:
beginflag <= 1;
Trang 24initial begin
$dumpfile("waveform.vcd");
$dumpvars(1);
endendmodule
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ìnhkế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ầnmề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
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ạicủa c.
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 +
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
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
Trang 33Tổng số thanh ghi dùng 24 chiếm <1%.
Trang 34Bà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
1.Viết code Verilog mô tả 2 cách trên Sử dụng phần mềm mô phỏng (ví dụ: ModelSim) 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 10giá trị
2 So sánh tài nguyên phần cứng của 2 cách trên khi thực thi trên FPGA Cyclone V5CGXFC7C7F23C8
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:
cout = x.y + cin.(x y)
Bảng chân trị của FullAdder:
Trang 35Cá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
x y
sum
Full Adder
cout cin
Trang 36wire [data:0] sum;
SerialAdder testAdd (m, n, reset, clk, sum);
Trang 37carry-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à:
= = ⨁ ⨁ ⨁ +1= +
Trang 38Code thực hiện
Trang 39`timescale 1ns/1ps
module CLA32bit(in1, in2, carry_in, sum, carry_out);
/ input data length parameter data = 32;
/ inputs
input [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 40Code testbench
module 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'd51; #2carry_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
Trang 41Đá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 42Giả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)
Trang 43A=A–2Y 10101 1010 0
bit
Lưu đồ giải thuật:
1.5.3 Code thực hiện và kết quả mô phỏng
Code thực hiện:
Trang 44module Modified_Booth_Multiplier(clk,rst,input1,input2,answer);
bu2_ặinput1(~so_a),.input2(16'd1),.answer(a_bu2));//bù 2 của a
//tong = chuoi_so + so_y
Trang 453'b001: so_y <= {so_a[15],so_a,17'd0};
3'b010: so_y <= {so_a[15],so_a,17'd0};
3'b011: so_y <= {so_a,18'd0};
3'b100: so_y <= {a_bu2,18'd0};
3'b101: so_y <= {a_bu2[15],a_bu2,17'd0};
3'b110: so_y <= {a_bu2[15],a_bu2,17'd0};
always begin #1 clk=~clk; end
// Instantiate the Unit Under Test (UUT)
Trang 47C¥zalus Prime Vzzsin 1a1.o euiid azs es/iz/zola in us miinn
Top-tenet Entity Name H‹afified_8 lh_Hultiptier
Totat btock memory bits 0 / 7,024,640 { 0 46)
Trang 48Phần riêng của mỗi nhóm:
Bài 1:
Trang 49Thuật toán Bellman-Ford:
Trang 50+ V=1:
Ứng với đường đi 2->1, ta có:
(1)(1) = min{0, 0 + 1} = 0+ V=2: (1)(2) =(0)(2) vì không có node nào dẫn đến node 2
Trang 51(2)(5) = min{0, 0 + 2} = 0 (2) = (0,0, −1,−2,0)
- Lúc này ta nhận thấy giá trị ở tất cả các nút không còn thay đổi nữa nghĩa là bài toán
đã hội tụ, kết quả thu được là:
1= 0
2= 03= −1
4= −2
5= 0
Kiểm chứng kết quả bằng Maltab: