# 數位系統實驗報告Lab10
:::info
學號: B093040044
系級: 資工113
姓名: 蔡明軒
:::
```
實驗日期: 2021/11/22
```
## 實驗一
### 內容
- 用Stuctural level modeling設計並驗證一個由兩個4-bit carry-look ahead adders組成的8-bit carry-look ahead adder
### 過程
1. 利用$C_{i+1}=G_i+P_iC_i$,推出各項carry
$C_1=G_0+P_0C_0$
$C_2=G_1+P_1C_1=G_1+P_1G_0+P_1P_0C_0$
$C_3=G_2+P_2C_2=G_2+P_2G_1+P_2P_1G_0+P_2P_1P_0C_0$
$C_4=G_3+P_3C_3=G_3+P_3G_2+P_3P_2G_1+P_3P_2P_1G_0+P_3P_2P_1P_0C_0$
2. 將以上式子寫成Verilog的module,名稱為carry_lookahead_generator
```verilog=
module carry_lookahead_generator(P,G,C0,C);
input[3:0] P,G;
input C0;
output[3:0] C;
wire[9:0] w;
and(w[0],P[0],C0);
or(C[0],w[0],G[0]);
and(w[1],P[1],P[0],C0);
and(w[2],P[1],G[0]);
or(C[1],G[1],w[1],w[2]);
and(w[3],P[2],P[1],P[0],C0);
and(w[4],P[2],P[1],G[0]);
and(w[5],P[2],G[1]);
or(C[2],G[2],w[3],w[4],w[5]);
and(w[6],P[3],P[2],P[1],P[0],C0);
and(w[7],P[3],P[2],P[1],G[0]);
and(w[8],P[3],P[2],G[1]);
and(w[9],P[3],G[2]);
or(C[3],G[3],w[6],w[7],w[8],w[9]);
endmodule
```
3. 根據$P_i=A_i\oplus B_i,G_i=A_iB_i$, 對陣列A,B的每個bit算出carry propagate ( P ) 及carry generator ( G ) ,之後再將P,G放入剛剛寫的carry_lookahead_generator,完成4-bit carry-look ahead adder
```verilog=
module four_bit_adder(A,B,C0,S,C4);
input[3:0] A,B;
input C0;
output[3:0] S;
output C4;
wire[3:0] P,G,C;
xor(P[0],A[0],B[0]);
and(G[0],A[0],B[0]);
xor(P[1],A[1],B[1]);
and(G[1],A[1],B[1]);
xor(P[2],A[2],B[2]);
and(G[2],A[2],B[2]);
xor(P[3],A[3],B[3]);
and(G[3],A[3],B[3]);
carry_lookahead_generator clg(P,G,C0,C);
buf(C4,C[3]);
xor(S[3],C[2],P[3]);
xor(S[2],C[1],P[2]);
xor(S[1],C[0],P[1]);
xor(S[0],C0,P[0]);
endmodule
```
4. 將8-bit的A,B分別切成一半,使用兩個4-bit carry-lookahead adder處理,其中,後半段陣列的adder(ADD_1)所輸出的$C_4$,會變成前半段陣列adder(ADD_2)的$C_0$
```verilog=
module eight_bit_adder(A,B,C0,S,C8);
input[7:0] A,B;
input C0;
output[7:0] S;
output C8;
wire C4;
four_bit_adder ADD1(A[3:0],B[3:0],C0,S[3:0],C4)
,ADD2(A[7:4],B[7:4],C4,S[7:4],C8);
endmodule
```
5. 撰寫testbench檔案,變數名稱和實驗提供的ppt相同
- 依助教需求,我產生了四組測試資料
| 測資 | A | B |
| --- | --- | ---- |
| 1 | 200 | 58 |
| 2 | 0 | 87 |
| 3 | 88 | 12 |
| 4 | 142 | 103 |
```verilog=
`timescale 1ns / 1ps
module tb;
reg[7:0] A;
reg[7:0] B;
reg C0;
wire[7:0]S;
wire C8;
eight_bit_adder UUT(.A(A),.B(B),.C0(C0),.S(S),.C8(C8));
initial begin
A=8'd200;B=8'd58; C0=1'b0;
#10 A=8'd0;B=8'd87; C0=1'b0;
#10 A=8'd88;B=8'd12; C0=1'b0;
#10 A=8'd142;B=8'd103; C0=1'b0;
#10 $finish;
end
endmodule
```
6. Run Synthesis and Simulation
7. 確認結果是否符合預期
### 結果
- 預期結果如下
| 測資 | A | B |S|C8|
| --- | --- | ---- |-|-|
| 1 | 200 | 58 |2|1|
| 2 | 0 | 87 |87|0|
| 3 | 88 | 12 |100|0|
| 4 | 142 | 103 |245|0|
- 輸出結果和上面的預期結果相同

## 實驗二
### 內容
- 設計並驗證一個 2-digit decimal adder
### 過程
1. 首先要實作1-bit的decimal_adder先對A,B兩組bit array做相加,並將答案存在K及temp,再利用$C=K+Z_8Z_4+Z_8Z_2$,確認temp是否需要再 +6 ,這裡是利用C生成一個長度為四命名為six的bit array,若C是1,six為0110,反之則為0000,最後將temp和six相加就會得到答案。
```verilog=
module decimal_adder(A,B,C0,Z,C);
input[3:0] A,B;
input C0;
output[3:0] Z;
output C;
wire K,w1,w2,w3;
wire[3:0] six,temp;
assign{K,temp} = A+B+C0;
and(w1,temp[3],temp[2]);
and(w2,temp[3],temp[1]);
or(C,K,w1,w2);
and(six[3],C,0);
and(six[2],C,1);
and(six[1],C,1);
and(six[0],C,0);
assign{w3,Z}=temp+six;
endmodule
```
2. 接著要將兩個1-bit的decimal_adder組合成2-bit的形式,這裡把A,B兩個長度為8的bit array切成一半,後半給ADD1處理,再將得到的carry傳輸到ADD2,和前半段的bit array一起處理。
```verilog=
module two_digit_decimal_adder(A,B,C0,Z,C);
input[7:0] A,B;
input C0;
output[7:0] Z;
output C;
wire temp;
decimal_adder ADD1(A[3:0],B[3:0],C0,Z[3:0],temp);
decimal_adder ADD2(A[7:4],B[7:4],temp,Z[7:4],C);
endmodule
```
3. 撰寫testbench,這裡我們將ppt所給的數字先轉成BCD,再輸進去testbench裡面
- 測資表
| 測資 | A | B |
| -------- | -------- | -------- |
| 1 | 32 | 41 |
| 2 | 25 | 57 |
| 3 | 86 | 79 |
```verilog=
`timescale 1ns / 1ps
module tb;
reg[7:0] A;
reg[7:0] B;
reg C0;
wire[7:0]Z;
wire C;
two_digit_decimal_adder UUT(.A(A),.B(B),.C0(C0),.Z(Z),.C(C));
initial begin
A=8'b00110010;B=8'b01000001; C0=1'b0;
#10 A=8'b00100101;B=8'b01010111; C0=1'b0;
#10 A=8'b10000110;B=8'b01111001; C0=1'b0;
#10 $finish;
end
endmodule
```
4. Run Synthesis and Simulation
5. 確認結果是否符合預期
### 結果
- 預期結果如下
| 測資 | A | B |S |C|
| --- | --- | ---- |- |-|
| 1 | 32 | 41 |73|0|
| 2 | 25 | 57 |82|0|
| 3 | 86 | 79 |65|1|
- 輸出結果與上面的預期結果相同(輸出為十六進位制)

## 實驗心得
>這次的實驗主要是實作上上週的正課課程,carry lookahead adder以及decimal adder。首先,實驗一為實作出8-bit的carry lookahead adder,在實作的過程中,我原本想要直接拿$C_1$的結果直接算出$C_2$,但在仔細思考過後,發現這樣會變成很多level的電路,導致速度較差,達不到carry lookahead adder的效果,於是我最後決定還是乖乖把$C_1$展開,實作速度較快的carry lookahead adder。
>我在實驗二花了不少的時間,最大的原因可能是因為我不太熟悉Behavioral Level Modeling,我把 {K,temp}=A+B+C0寫成了{K,temp}={A+B+C0},我找這個錯誤找了快一個小時,直到我向助教求助後才發現我多加了大括號,並解決掉輸出不對的問題。
>課堂結束後,我有試著把{A+B+C0}輸出出來(A,B都是長度為四的bit array),發現A+B就算是有進位的狀況,輸出結果最大的那一位仍然還是0,這很有可能就是我發生錯誤的原因。
- 測試畫面
