---
# System prepended metadata

title: 數位系統實驗報告Lab10

---

# 數位系統實驗報告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|

- 輸出結果和上面的預期結果相同
![](https://i.imgur.com/sMzy2uh.png)


## 實驗二

### 內容

- 設計並驗證一個 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|

- 輸出結果與上面的預期結果相同(輸出為十六進位制)
![](https://i.imgur.com/u4DX330.png)

## 實驗心得

>這次的實驗主要是實作上上週的正課課程，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，這很有可能就是我發生錯誤的原因。

- 測試畫面
![](https://i.imgur.com/qX4QJSu.png)

