---
# System prepended metadata

title: FINAL PROJECT

---

# HW-1

***Four-bit Full Adder***
b1105167 張家凱
一、目的－使用verilog實現four-bit full adder

二、工具-vscode,xilinx-vivado

三、方法與步驟－詳細說明
  **vscode部分**:
  先寫出four_bit_adder.v檔，裡面包含包含兩模組，一個是全加器模組，另   一個是four_bit_adder模組(引用全加器模組)。接著建立新的file寫出    testbench檔-four_bit_adder_tb.v，同個模式再寫出makefile檔。
  **vivado部分**:
  利用vivado開啟four_bit_adder.v與four_bit_adder_tb.v進行simulation，並合成Schematic。

四、結果－觀察輸出、輸出波型與Schematic。
  **vscode部分**:
  觀察輸出![](https://hackmd.io/_uploads/rJHIEj8l6.png)
  觀察輸出波型
  ![](https://hackmd.io/_uploads/Hyme_jLgT.png)
 **vivado部分**:
  觀察輸出波型:
 ![](https://hackmd.io/_uploads/Hy-UGV_g6.png)

  
  結果全部吻合預期----->合成schematic
  ![](https://hackmd.io/_uploads/HkVjOs8lT.png)
  ![](https://hackmd.io/_uploads/Bk60XZ3xp.png)


七、心得－這是第一次使用verilog完成作業，儘管語法學起來不難但仍有許多沒有預期到的bug!!!，後來發現是testbench的技巧尚未純熟，導致vscode那邊無法compile，希望自己可以能更加精進。

八、參考文獻－軟硬體協同設計上課講義-林宏益教授編
# HW-2
**一、目的** -用verilog實現BCD to Decimal Decoder with Preset/Reset並提供vivado模擬報告。
**二、工具**-vscode,xilinx-vivado
**三、方法與步驟**-詳細說明
1.先在vscode寫出RTL檔與testbench並驗證其結果
RTL CODE:
```verilog=
module bcd_to_decimal (
           A, // I 1-bit first  inout  bit
           B, // I 1-bit second  input bit
           C, // I 1-bit third   input bit
           D, // I 1-bit fourth   input bit
           reset_n,
           preset,
           O // O 10-bit  output
       );

input A,B,C,D,reset_n,preset;
output [9:0]O;
reg [9:0]O;

always @(A or B or C or D or reset_n or preset)
begin

    casez ({reset_n, preset})
        2'b0x   :
            O = 10'b00_0000_0000;
        2'b11 :
            O = 10'b00_0000_1111;
        2'b10 :
            if ({D, C, B, A} == 4'b0000)
                O = 10'b11_1111_1110;
            else if({D, C, B, A} == 4'b0001)
                O = 10'b11_1111_1101;
            else if({D, C, B, A} == 4'b0010)
                O = 10'b11_1111_1011;
            else if({D, C, B, A} == 4'b0011)
                O = 10'b11_1111_0111;
            else if({D, C, B, A} == 4'b0100)
                O = 10'b11_1110_1111;
            else if({D, C, B, A} == 4'b0101)
                O = 10'b11_1101_1111;
            else if({D, C, B, A} == 4'b0110)
                O = 10'b11_1011_1111;
            else if({D, C, B, A} == 4'b0111)
                O = 10'b11_0111_1111;
            else if({D, C, B, A} == 4'b1000)
                O = 10'b10_1111_1111;
            else if({D, C, B, A} == 4'b1001)
                O = 10'b01_1111_1111;
            else
                O = 10'b11_1111_1111;
        default:
            O = 10'b11_1111_1111;
    endcase

end

endmodule 

```
**testbench -暴力輸入**
![](https://hackmd.io/_uploads/Bk6JUMQWT.png)
----->結果吻合預期
觀察波形圖
![](https://hackmd.io/_uploads/HJpSUzXZp.png)
----->同樣吻合預期
2.放入vivado做模擬
run simulation 確認輸出與輸入埠正確
----->查看波形
![](https://hackmd.io/_uploads/HJIvxvmWp.png)
----->符合預期

RTL ANALYSIS 的schematic 圖
![](https://hackmd.io/_uploads/H1UpWvQZT.png)
![](https://hackmd.io/_uploads/H1ylfDm-T.png)
![](https://hackmd.io/_uploads/SkeWfPX-T.png)
![](https://hackmd.io/_uploads/HkmZzwXZT.png)
![](https://hackmd.io/_uploads/BJuZGPXZT.png)
![](https://hackmd.io/_uploads/S16ZzD7Zp.png)
----->10個多工器吻合預期

IMPLEMENTATION 
schematic:
![](https://hackmd.io/_uploads/Bk164wQZ6.png)




分析報告與心得:
![](https://hackmd.io/_uploads/HkV3SD7Wa.png)
在分析報告中，我的logic power為0.032w，雖然不是特別耗能，但是我覺得我的if else 語句造成elaborated schematic 圖超級長!，應該是RTL CODE沒有設計好，也許有更好的解法尚未想到。

## FPGA 驗證

**當preset=1 reset=1** **輸出:1111000000**
![](https://hackmd.io/_uploads/SkUiwdpz6.jpg)
                                                     
**reset_n=1 preset=0**
**輸入:0000 輸出:0111111111**
![](https://hackmd.io/_uploads/B1RpUdTMT.jpg)

**輸入:0001 輸出:1011111111**
![](https://hackmd.io/_uploads/r1wdddTGa.jpg)


# HW-3、4

## 目的

當reset_n=1，則輸入有效
當輸入:
**D=0 C=0 B=0 A=0** 則七段顯示器顯示0----->
輸出:
**a=0 b=0 c=0 d=0 e=0 f=0 g=1 dp=1**
(因共陰故0的地方亮)
     ...以此類推...

當reset_n=0，則輸入無效
輸入:
**D=x C=x B=x A=x** 七段顯示器顯示H---->
輸出:
**a=1 b=0 c=0 d=1 e=0 f=0 g=0 dp=1**
![](https://hackmd.io/_uploads/B1K4LdoGa.png)

![](https://hackmd.io/_uploads/ryufr_oG6.png)


## HDL CODE說明

``` verilog 
module segment7 (
           A,
           B,
           C,
           D,
           reset_n,
           disp
);

input reset_n,A,B,C,D;
reg   [7:0] disp;
output [7:0] disp;
wire [4:0] BCD_code;

assign BCD_code={reset_n,D,C,B,A};

always @(BCD_code)
case (BCD_code)
    5'b10000:
        disp=8'b0000_0011;
    5'b10001:
        disp=8'b1001_1111;
    5'b10010:
        disp=8'b0010_0101;
    5'b10011:
        disp=8'b0000_1101;
    5'b10100:
        disp=8'b1001_1001;
    5'b10101:
        disp=8'b0100_1001;
    5'b10110:
        disp=8'b0100_0001;
    5'b10111:
        disp=8'b0001_1111;
    5'b11000:
        disp=8'b0000_0001;
    5'b11001:
        disp=8'b0000_1001;
    5'b11010:
        disp=8'b0001_0001;
    5'b11011:
        disp=8'b1100_0001;
    5'b11100:
        disp=8'b0110_0011;
    5'b11101:
        disp=8'b1000_0101;
    5'b11110:
        disp=8'b0110_0001;
    5'b11111:
        disp=8'b0111_0001;


    default :
        disp=8'b10010001//五個位元32個數已經定義16個
                        //故0xxxx都是8'b10010001---->顯示H
endcase

endmodule
```


## Testbench Code說明

1.檢測當reset_n=0 輸出是否正確
2.檢測reset_n=1 時的所有輸出
``` verilog 
module segment7_tb();

reg reset_n, D, C, B, A;
wire [7:0] disp;

integer i;//給reset_n=1時的迴圈用

initial
begin

    $dumpfile("segment7.vcd");
    $dumpvars(0, display_unit);
    $monitor("reset_n = %b, D = %b C = %b B = %b A = %b | a = %b b = %b c = %b d = %b e = %b f = %b g = %b dp = %b"
             , reset_n, D, C, B, A, disp[7],disp[6],disp[5],disp[4],disp[3],disp[2],disp[1],disp[0]);


    #10;
    reset_n=1'b0;
    A = 1'b0;
    B = 1'b0;
    C = 1'b0;
    D = 1'b0;  //測試reset有沒有用
    #10;
    reset_n=1'b0;
    A = 1'b0;
    B = 1'b1;
    C = 1'b0;
    D = 1'b1;  //測試reset有沒有用

    #10;
    reset_n=1'b1;


    for (i = 0; i <= 15 ; i = i + 1 ) //迴圈輸入從0000~1111
    begin
        D = i[3];
        C = i[2];
        B = i[1];
        A = i[0];
        #10;
    end
    #10 $finish;

end
segment7  display_unit (
              .A(A),
              .B(B),
              .C(C),
              .D(D),
              .reset_n(reset_n),
              .disp(disp)
          );


endmodule
```
**結果:**
![](https://hackmd.io/_uploads/H1b12_izp.png)
## Schematic

RTL 
![](https://hackmd.io/_uploads/HJCgjx3zp.png)
IMPLEMENTATION
![](https://hackmd.io/_uploads/H17Faxhz6.png)
POWER
![](https://hackmd.io/_uploads/rkjapghMT.png)
## 工作站模擬

Verdi Tool
![](https://hackmd.io/_uploads/S1mnyuafa.png)
![](https://hackmd.io/_uploads/Skh-l_6zp.png)
Wave
![](https://hackmd.io/_uploads/HkUWEupfa.png)

**結果與預期相符--->成功!!**

## FPGA 驗證

**reset_n=0**
全部------>顯示H
![S__16121859.jpg](https://hackmd.io/_uploads/Hkk8kdM7a.jpg)

**reset_n=1**
輸入:0000------>顯示0
![S__16121861.jpg](https://hackmd.io/_uploads/B10Mg_fX6.jpg)

**reset_n=1**
輸入:0001------>顯示1
![S__16121862.jpg](https://hackmd.io/_uploads/r1sQxOzQT.jpg)

**reset_n=1**
輸入:0010------>顯示2
![S__16121863.jpg](https://hackmd.io/_uploads/B1TAe_G76.jpg)

**reset_n=1**
輸入:0011------>顯示3
![S__16121864.jpg](https://hackmd.io/_uploads/ByTyW_zQa.jpg)

**reset_n=1**
輸入:0100------>顯示4
![S__16121865.jpg](https://hackmd.io/_uploads/HJBQb_zmp.jpg)

**reset_n=1**
輸入:0101------>顯示5
![S__16121866.jpg](https://hackmd.io/_uploads/rkL4buzXT.jpg)

**reset_n=1**
輸入:0110------>顯示6
![S__16121867.jpg](https://hackmd.io/_uploads/r1R4ZdGXp.jpg)

**reset_n=1**
輸入:0111------>顯示7
![S__16121868.jpg](https://hackmd.io/_uploads/B1ZLbdzQ6.jpg)

**reset_n=1**
輸入:1000------>顯示8
![S__16121869.jpg](https://hackmd.io/_uploads/HJcLZOzmT.jpg)

**reset_n=1**
輸入:1001------>顯示9
![S__16121870.jpg](https://hackmd.io/_uploads/H1Xvb_zmp.jpg)

**reset_n=1**
輸入:1010------>顯示A
![S__16121872.jpg](https://hackmd.io/_uploads/BJ5KW_MQ6.jpg)

**reset_n=1**
輸入:1011------>顯示b
![S__16121873.jpg](https://hackmd.io/_uploads/r1fq-OM7a.jpg)

**reset_n=1**
輸入:1100------>顯示C
![S__16121874.jpg](https://hackmd.io/_uploads/rkekfOzQT.jpg)

**reset_n=1**
輸入:1101------>顯示d
![S__16121875.jpg](https://hackmd.io/_uploads/HJgQG_fXa.jpg)

**reset_n=1**
輸入:1110------>顯示E
![S__16121876.jpg](https://hackmd.io/_uploads/SyZUMdfX6.jpg)

**reset_n=1**
輸入:1111------>顯示F
![S__16121877.jpg](https://hackmd.io/_uploads/S1L5MOzQa.jpg)


# HW-5
## FSM Coverage 只有75%原因

![370099462_2526763234178725_2726113974856680153_n](https://hackmd.io/_uploads/HkHDJyoNp.png)
在FSM Coverage看到，過程中並沒有執行到s0 ----> IDLE

## 推測------>看波型

![87](https://hackmd.io/_uploads/r1ksMksNT.png)
看出inp 輸入延遲太長，導致inp一直為1，沒有回到0，讓s0回到IDLE。

## 提升覆蓋率------>修改testbench

**INP輸入延遲改成10ps**
![image](https://hackmd.io/_uploads/HJYi3yo4T.png)


**波型確認**
![88](https://hackmd.io/_uploads/SJ3eJgjN6.png)

覆蓋率確認
![image](https://hackmd.io/_uploads/rJ5CSJjNT.png)
**---->皆有執行**

## 為何不能到達Line、Branch無法到達100%

![image](https://hackmd.io/_uploads/H1C3I1o4T.png)
**軟體無法忽略default敘述，因為testbench沒有跑到可是卻有這行敘述，所以無法到達100%**

## 解決:忽略default這個覆蓋率

**修改編譯選項
--->新增 VCS coverage off/on 
意義:模擬但不統計覆蓋率**


**覆蓋率確認**
![image](https://hackmd.io/_uploads/By0Jfxi4T.png)
--->SUCCEED!!

# HW-6(UART)

##  FPGA呈現

[影片連結](https://youtu.be/bnsP-E6n6Qc)

## Verilog code

```verilog=
//top module
`timescale 1ns / 1ps
module rx_top(
           input clk,
           input rst,
           input rx_pin_in,
           output [7:0] seg7
       ) ;
wire rx_pin_H2L;
H2L_detect rx_in_detect(
               .clk( clk ),
               .rst( rst ),
               .pin_in( rx_pin_in ),
               .sig_H2L( rx_pin_H2L )
           );
wire rx_band_sig;
wire clk_bps;
rx_band_gen rx_band_gen(
                .clk( clk ),
                .rst( rst ),
                .band_sig( rx_band_sig ),
                .clk_bps( clk_bps )
            );
wire [7:0] rx_data;
rx_ctl rx_ctl(
           .clk( clk ),
           .rst( rst ),
           .rx_pin_in( rx_pin_in ),
           .rx_pin_H2L( rx_pin_H2L ),
           .rx_band_sig( rx_band_sig ),
           .rx_clk_bps( clk_bps ),
           .rx_data( rx_data ),
           .rx_done_sig( rx_done_sig )
       );
ASCII2seg7 u_ASCII2seg7(
               .rst( rx_done_sig ),
               .ASCII( rx_data ),
               .seg7_out(seg7)
           );
endmodule
```
```verilog=
`timescale 1ns / 1ps
module rx_band_gen(
    input clk,
    input rst,
    input band_sig,
    output reg clk_bps
    );
    parameter SYS_RATE = 125000000;
    parameter BAND_RATE = 9600;
    parameter CNT_BAND = SYS_RATE / BAND_RATE;
    parameter HALF_CNT_BAND = CNT_BAND / 2;
    reg [13:0]cnt_bps;
    always @( posedge clk or posedge rst )
    if( rst )
        begin
            cnt_bps <= HALF_CNT_BAND;
            clk_bps <= 1'b0;
        end
    else if( !band_sig )
        begin
            cnt_bps <= HALF_CNT_BAND;
            clk_bps <= 1'b0;
        end
    else if( cnt_bps == CNT_BAND )
        begin
            cnt_bps <= 14'd0;
            clk_bps <= 1'b1;
        end
    else
        begin
            cnt_bps <= cnt_bps + 1'b1;
            clk_bps <= 1'b0;
        end
endmodule
```

```verilog=
`timescale 1ns / 1ps
module H2L_detect(
    input clk,
    input rst,
    input pin_in,
    output sig_H2L
    );
    reg pin_pre;
    assign sig_H2L = !pin_in & pin_pre;
    always @( posedge clk or posedge rst )
    if( rst )
        pin_pre <= 1'b0;
    else
        pin_pre <= pin_in;
endmodule
```
```verilog=
module ASCII2seg7 (
    rst,
    ASCII,
    seg7_out
    );

input rst;
input [7:0] ASCII;
reg [7:0] seg7;
output [7:0] seg7_out;
always@( posedge rst )
begin
//if ( rst ) begin
    case (ASCII)
        8'b0011_0000:
            seg7=8'b00000011;
        8'b0011_0001:
            seg7=8'b10011111;
        8'b0011_0010:
            seg7=8'b00100101;
        8'b0011_0011:
            seg7=8'b00001101;
        8'b0011_0100:
            seg7=8'b10011001;
        8'b0011_0101:
            seg7=8'b01001001;
        8'b0011_0110:
            seg7=8'b01000001;
        8'b0011_0111:
            seg7=8'b00011111;
        8'b0011_1000:
            seg7=8'b00000001;
        8'b0011_1001:
            seg7=8'b00001001;
        8'b0100_0001:
            seg7=8'b00010001;
        8'b0100_0010:
            seg7=8'b11000001;
        8'b0100_0011:
            seg7=8'b11100101;
        8'b0100_0100:
            seg7=8'b10000101;
        8'b0100_0101:
            seg7=8'b01100001;
        8'b0100_0110:
            seg7=8'b01110001;
        default:
            seg7=8'b01100001;
    endcase

end
assign seg7_out=seg7;
endmodule
```
```verilog=
`timescale 1ns / 1ps
module rx_ctl(
           input clk,
           input rst,
           input rx_pin_in,
           input rx_pin_H2L,
           output reg rx_band_sig,
           input rx_clk_bps,
           output reg[7:0] rx_data,
           output reg rx_done_sig
       ) ;
localparam [3:0] IDLE = 4'd0, BEGIN = 4'd1, DATA0 = 4'd2,
           DATA1 = 4'd3, DATA2 = 4'd4, DATA3 = 4'd5,
           DATA4 = 4'd6, DATA5 = 4'd7, DATA6 = 4'd8,
           DATA7 = 4'd9, END = 4'd10, BFREE = 4'd11;
reg [3:0] pos;
always@( posedge clk or posedge rst )
    if( rst )
    begin
        rx_band_sig <= 1'b0;
        rx_data <= 8'd0;
        pos <= IDLE;
        rx_done_sig <= 1'b0;
    end
    else
    case( pos )
        IDLE:
            if( rx_pin_H2L)
            begin
                rx_band_sig <= 1'b1;
                pos <= pos + 1'b1;
                rx_data <= 8'd0;
            end
        BEGIN:
            if( rx_clk_bps)
            begin
                if( rx_pin_in == 1'b0 )
                begin
                    pos <= pos + 1'b1;
                end
                else
                begin
                    rx_band_sig <= 1'b0;
                    pos <= IDLE;
                end
            end
        DATA0,DATA1,DATA2,DATA3,DATA4,DATA5,DATA6,DATA7:
            if( rx_clk_bps)
            begin
                rx_data[ pos - DATA0 ] <= rx_pin_in;
                pos <= pos + 1'b1;
            end
        END:
            if( rx_clk_bps)
            begin
                rx_done_sig <= 1'b1;
                pos <= pos + 1'b1;
                rx_band_sig <= 1'b0;
            end
        BFREE:
        begin
            rx_done_sig <= 1'b0;
            pos <= IDLE;
        end
    endcase
endmodule
```
## testbench

```verilog=
`timescale 1ns / 1ps
module rx_top_tb();
  reg            clk;	
  reg            rst;	
  reg            uart_rx;
  wire [7:0]     seg7;
  integer         i;
  reg [7:0]      data_test=8'b0;
  // 100MHz 9600bps 
  rx_top u_rx_top(
    .clk(clk),
    .rst(rst), 
    .rx_pin_in(uart_rx), 
    .seg7(seg7)
    );	
  initial begin
    clk=0;
      for (i=0;i<256;i=i+1) begin //8 bit 測256個資料
        rst=1;          
        #15 rst=0;uart_rx=1;
        
        #260415 uart_rx=0;
        
        #260415 uart_rx = data_test[0];
        #260415 uart_rx = data_test[1];
        #260415 uart_rx = data_test[2];
        #260415 uart_rx = data_test[3];
        #260415 uart_rx = data_test[4];
        #260415 uart_rx = data_test[5];
        #260415 uart_rx = data_test[6];
        #260415 uart_rx = data_test[7];
        
        #260415 uart_rx=1; 
        data_test = data_test + 1;
    end
    $finish;
  end
  
  always #10 clk=~clk;
endmodule
```
## Coverage
![image](https://hackmd.io/_uploads/HyOWtt8Yp.png)
## Lint
![image](https://hackmd.io/_uploads/HyH7ttLta.png)


## Schematic 

![image](https://hackmd.io/_uploads/SkmbLhG8a.png)


# Reading experience
人月神話閱讀心得(張家凱,李旼學)
---
## 張家凱

 關於人月神話的解釋，這是讓我非常印想深刻的一段，且就在開頭的第二章，所謂的人月就是人與時間的關係，在當工作可以被切分且工作的人「彼此不用溝通的條件下」，假設一個小任務一個人可以三天做完，那麼三人一天便可以做完，然而在軟體工程如果這樣來衡量工作規模是相當危險的，因為溝通成本也會隨著人數增長而提高(包括人員對產品概念性的不同)，所以有的時候添加人手是拖延了進度而不是縮短。


而這也帶出了溝通的重要性，一直延伸到了為何巴別塔會失敗(Why Did The Tower of Babel Fail?)，巴別塔故事中作者提到這項建設具備了許多成功的條件
1. 明確的目標
2. 人力
3. 材料
4. 足夠的時間
5. 充分的技術

然而最終為何失敗呢?他們缺少了「溝通」與「組織」，當人與人之間不能溝通，就無法合作，合作失敗意味著工作停頓，於是最終團隊土崩瓦解。作者同時也提到了各種方法等，包含建立交流
1. 非正式方法(良好的電話聯繫制度)
2. 會議(例行性的專案會議)
3. 工作手冊


建立良好組織架構減少溝通成本
1. 人力的配置
2. 專業分工

在第一版的二十年後，作者依然說著:「專案如果要成功，人的品質，以及人的組織與管理，遠遠比他們所運用的工具或技術來的重要。」，這也是讓我最終感動的地方，即使過了二十年依舊不變的定理，我也歸納、濃縮了幾個重點
1. 人的品質： 作者認為，優秀的工程師遠比普通的工程師更能夠提高專案的效率。他指出，優秀的人才可以在短時間內完成高質量的工作，而招聘優秀的人才比增加人數更為關鍵。
2. 人的組織： 良好的組織結構是確保專案成功的關鍵因素。有效的溝通和協作可以防止資訊不對等和做重複工作，提高整個團隊的效能，以免拖累軟體工程的進度。
3. 管理： 專案管理也是本書的核心價值，作者指出，良好的專案管理包括計畫、組織、追蹤和控制。管理者需要有適當的計畫和組織，以確保專案能夠按時交付。

總而言之，雖然「人月神話」還強調了許多概念，但是礙於篇幅我不能一一細說，且許多較為古老的技術，實在難以想像，但我相信在一個專案成功的例子中，人的品質、組織結構以及有效的管理比使用的工具或技術更為重要，這也是作者花好幾個章節所提到的。即使擁有最先進的技術，如果沒有優秀的人才和有效的管理，專案仍然可能陷入困境。此外這個概念也激勵著我成為更好的「新鮮人」，因為反過來說，公司應該不太願意培養一個「二流人才」，來拖累他們的產品進度，並成為一個「負資產」，而這也是我目前的心得，期許書中的概念能陪伴我之後的工作歲月。

---
## 李旼學
---
人月神話這本書，講述了軟體工程中專案管理的重要性。第一章的焦油坑，便比較了個人單獨寫出的程式與一系統產品的差別，若將程式產品化，所需成本為三倍，而將其進行整合測試等過程凝聚成一個系統，也就是系統化的過程，所需的成本也是三倍，而兩者是分開獨立計算的，所以要推出一個系統產品，複雜度是直線上升的。

因此，如何在一個龐大的軟體開發中，進行有效的管理，是一個至關重要的課題。而作者便在第二章提出人月的觀點，也就是人與時間之間的關係。在傳統的觀念中，我們或許會直覺地認為人多好辦事，但在軟體開發的世界並非如此，作者在文中說過一句有趣的話:生小孩就是要九個月，你叫多少媽生都是一樣，也就是人力與時間並非是線性關係，那只發生在工作可被切分而且無須溝通成本的情況下，如果在實際工程中採用此模型衡量成本與規模，無疑是一件危險的事情。舉一個在作業系統學到的Amdahl's Law，其在討論是否一直增加核心數，就能提升電腦的效能，結論是提升的效能變非是一個線性關係，而是與其serial(串列)的部分息息相關，若是serial port的部分越多，則增加的效能越少，所以我們應該要考慮的是增加parallel port的部分，也就是進行平行化處理，若將人比喻成core，似乎不論是人或是機器的法則，都意外地相近呢。

而作者也以本身經驗，對軟體開發時程進行以下的分配:
1.1/3 整體規劃
2.1/6 撰寫程式
3.1/4 組件測試與初步系統測試
4.1/4 系統測試以及完成組件
可以看出撰寫程式的時間其實是最少的，花最多的反而是對專案的時程內容等等規劃的時間，也就是所謂的工欲善其事，必先利其器，有良好的規劃與安排，對整體開發的構思，才能友善提高整體品質，減少無謂的溝通成本。而在組件與系統的測試也是十分重要的一個環節，開發的軟體產品必須經過維護以及測試，確保及功能的正確性，才能作為產品去銷售，在課堂中從撰寫verilog code，到現在正在教學的vcs,verdi, dc compiler作驗證，我想我們也是在run過一個小小小專案所必備的流程。

基於以上的概念，在處理一個專案時，如何最大化提升效率呢? 作者便提出了外科手術團隊的概念，以一人為主體，其他人則各司其職，作一個輔助的部分，處理一些小的專案，這樣明確的分工制度，除了能減少溝通成本，也能因為少數人進行決策，維持對產品的概念的整體性，減少不同人對產品概念的看法不同，在認知上造成差異的錯誤。

老實說，我並沒有看完整本書，但從前面大部分篇章，都能看到作者對團隊組織結構以及管理層面的探討。技術可能與時俱進，需要不斷去更新，但對專案組織等等的管理，卻是一個整體概念變化不大的部分，這也是為什麼人月神話經過了40年的光陰，仍然能被教授推薦閱讀的原因，這也是在職場與人co-working時很重要的部分，期許自己能先精進實力，爾後在職場的時光，能細品本書的字字句句。

# Final project
## UART 的實現與面積、功率的縮小

利用UART通訊協議來實現資料傳輸
![image](https://hackmd.io/_uploads/HyNXBMMFp.png)
本次是實現9600bps的通訊協議

## 架構

![image](https://hackmd.io/_uploads/Sy5xb6XFT.png)


## 原版程式

目的:將PC端的傳輸訊號(ASCII)傳入至FPGA上(receiver端)，輸入1到9顯示1到9，輸入A到E顯示A~E，其他輸入顯示E。
```verilog=
//TOP MODULE
`timescale 1ns / 1ps

module rx_top(
    input clk,
    input rst,
    input rx_pin_in,
    output [7:0] seg7
    );
    wire [7:0] rx_data;  
    wire rx_band_sig;
    wire clk_bps;
    
    rx_band_gen rx_band_gen(
        .clk( clk ),
        .rst( rst ),
        .band_sig( rx_band_sig ),
        .clk_bps( clk_bps )
    );
    H2L_detect rx_in_detect(
        .clk( clk ),
        .rst( rst ),
        .pin_in( rx_pin_in ),
        .sig_H2L( rx_pin_H2L )
    );
    rx_ctl rx_ctl(
        .clk( clk ),
        .rst( rst ),
        .rx_pin_in( rx_pin_in ),
        .rx_band_sig( rx_band_sig ),
        .rx_clk_bps( clk_bps ),
        .rx_data( rx_data ),
        .rx_done_sig( rx_done_sig )
    );
    
    ASCII27 ASCII27(
        .rst( rx_done_sig ),
        .ascii( rx_data ), //rx_data訊號->ASCII
        .seg7(seg7)
    );
endmodule
```
```verilog=
//製造9600bps的除頻器

module rx_band_gen(
    input clk,
    input rst,
    input band_sig,
    output reg clk_bps
    );
    parameter SYS_RATE = 125000000;//FPGA 之系統頻率
    parameter BAND_RATE = 9600;
    parameter CNT_BAND = SYS_RATE / BAND_RATE;
    parameter HALF_CNT_BAND = CNT_BAND / 2;
    reg [13:0]cnt_bps;
    always @( posedge clk or posedge rst )
    if( rst )
        begin
            cnt_bps <= HALF_CNT_BAND;
            clk_bps <= 1'b0;
        end
    else if( !band_sig )
        begin
            cnt_bps <= HALF_CNT_BAND;
            clk_bps <= 1'b0;
        end
    else if( cnt_bps == CNT_BAND )
        begin
            cnt_bps <= 14'd0;
            clk_bps <= 1'b1;
        end
    else
        begin
            cnt_bps <= cnt_bps + 1'b1;
            clk_bps <= 1'b0;
        end

    
```

![image](https://hackmd.io/_uploads/S1VsoXGY6.png)

```verilog=
//偵測start 訊號
module H2L_detect(
    input clk,
    input rst,
    input pin_in,
    output sig_H2L
    );
    reg pin_pre;
    assign sig_H2L = !pin_in & pin_pre;
    always @( posedge clk or posedge rst )
    if( rst )
        pin_pre <= 1'b0;
    else
        pin_pre <= pin_in;
endmodule
```
```verilog=
//UART 狀態機

module rx_ctl(
           input clk,
           input rst,
           input rx_pin_in,
           input rx_pin_H2L,
           output reg rx_band_sig,
           input rx_clk_bps,
           output reg[7:0] rx_data,
           output reg rx_done_sig
       ) ;
localparam [3:0] IDLE = 4'd0, BEGIN = 4'd1, DATA0 = 4'd2,
           DATA1 = 4'd3, DATA2 = 4'd4, DATA3 = 4'd5,
           DATA4 = 4'd6, DATA5 = 4'd7, DATA6 = 4'd8,
           DATA7 = 4'd9, END = 4'd10, BFREE = 4'd11;
reg [3:0] pos;
always@( posedge clk or posedge rst )
    if( rst )
    begin
        rx_band_sig <= 1'b0;
        rx_data <= 8'd0;
        pos <= IDLE;
        rx_done_sig <= 1'b0;
    end
    else
        case( pos )
        IDLE://等待start 訊號，H2L發生跳到BEGIN
            if( rx_pin_H2L)
            begin
                rx_band_sig <= 1'b1;//產生rx_clk_bps訊號
                pos <= pos + 1'b1;
                rx_data <= 8'd0;
            end
        BEGIN:
            if( rx_clk_bps)
            begin
                if( rx_pin_in == 1'b0 )
                begin
                    pos <= pos + 1'b1;
                end
                else
                begin
                    rx_band_sig <= 1'b0;
                    pos <= IDLE;
                end
            end
        DATA0,DATA1,DATA2,DATA3,DATA4,DATA5,DATA6,DATA7://儲存rx_data
            if( rx_clk_bps)
            begin
                rx_data[ pos - DATA0 ] <= rx_pin_in;//rx_pin_in資料儲存至rx_data
                pos <= pos + 1'b1;
            end
            END://完成接收，rx_done_sig輸出1，
                //rx_band_sig輸出0，停止產收rx_clk_bps訊號，跳到BFREE。
            if( rx_clk_bps)
            begin
                rx_done_sig <= 1'b1;
                pos <= pos + 1'b1;
                rx_band_sig <= 1'b0;
            end
        BFREE://rx_done_sig輸出0，回到IDLE
        begin
            rx_done_sig <= 1'b0;
            pos <= IDLE;
        end
    endcase
endmodule
```



![image](https://hackmd.io/_uploads/rJJt0XzFa.png)

```verilog=
//鍵盤數字ASCII轉七段顯示器數字(共陽)之模組
module ASCII2seg7 (
    rst,
    ASCII,
    seg7_out
    );

input rst;
input [7:0] ASCII;
reg [7:0] seg7;
output [7:0] seg7_out;
always@( posedge rst )
begin

    case (ASCII)
        8'b0011_0000:
            seg7<=8'b00000011;
        8'b0011_0001:
            seg7<=8'b10011111;
        8'b0011_0010:
            seg7<=8'b00100101;
        8'b0011_0011:
            seg7<=8'b00001101;
        8'b0011_0100:
            seg7<=8'b10011001;
        8'b0011_0101:
            seg7<=8'b01001001;
        8'b0011_0110:
            seg7<=8'b01000001;
        8'b0011_0111:
            seg7<=8'b00011111;
        8'b0011_1000:
            seg7<=8'b00000001;
        8'b0011_1001:
            seg7=8'b00001001;
        8'b0100_0001:
            seg7=8'b00010001;
        8'b0100_0010:
            seg7=8'b11000001;
        8'b0100_0011:
            seg7=8'b11100101;
        8'b0100_0100:
            seg7=8'b10000101;
        8'b0100_0101:
            seg7=8'b01100001;
        8'b0100_0110:
            seg7=8'b01110001;
        default:
            seg7=8'b01100001;
    endcase

end
assign seg7_out=seg7;
endmodule
```
## 波型驗證圖

![1](https://hackmd.io/_uploads/BkOw2uXtT.jpg)

![2](https://hackmd.io/_uploads/BJUu6dmtT.jpg)

![3](https://hackmd.io/_uploads/SyktTOXFp.jpg)

![4](https://hackmd.io/_uploads/S11RaO7FT.jpg)

![5](https://hackmd.io/_uploads/H1SJAOQtp.jpg)

![6](https://hackmd.io/_uploads/B1YgRumKT.jpg)

## Area and Power report
 Design Compiler

最小面積使用與最小動態功率Constraint
![image](https://hackmd.io/_uploads/HyQsq5mFp.png)

![image](https://hackmd.io/_uploads/ryhJo9XFp.png)
![image](https://hackmd.io/_uploads/r1E-i5Qt6.png)







![3B50837D-AA84-4E5A-A6FD-6EF2FB09A9CB](https://hackmd.io/_uploads/Sk2APK7K6.jpg)
---->沒有設面積2900up


![12](https://hackmd.io/_uploads/SJfskKXF6.jpg)







   |









## 第二版

思考狀態機的縮減，將接收資料狀態合併成一個狀態--->用編碼減少狀態

```verilog=
module rx_ctl(
    input clk,
    input rst,
    input rx_pin_in,
    input rx_pin_H2L,
    output reg rx_band_sig,
    input rx_clk_bps,
    output reg[7:0] rx_data,
    output reg rx_done_sig
);

localparam [3:0]
    IDLE = 4'd0,
    BEGIN = 4'd1,
    DATA = 4'd2,  // 合併所有數據狀態
    END = 4'd3,
    BFREE = 4'd4;

reg [3:0] pos;
    reg [2:0] data_bit_count; // 計數器用於追蹤數據位

always@(posedge clk or posedge rst) begin
    if(rst) begin
        rx_band_sig <= 1'b0;
        rx_data <= 8'd0;
        pos <= IDLE;
        rx_done_sig <= 1'b0;
        data_bit_count <= 3'd0;
    end
    else begin
        case(pos)
            IDLE: begin
                if(rx_pin_H2L) begin
                    rx_band_sig <= 1'b1;
                    pos <= BEGIN;
                    rx_data <= 8'd0;
                    data_bit_count <= 3'd0;
                end
            end
            BEGIN: begin
                if(rx_clk_bps) begin
                    if(rx_pin_in == 1'b0) begin
                        pos <= DATA;
                    end
                    else begin
                        rx_band_sig <= 1'b0;
                        pos <= IDLE;
                    end
                end
            end
            DATA: begin
                if(rx_clk_bps) begin
                    rx_data[data_bit_count] <= rx_pin_in;
                    if(data_bit_count == 3'd7) begin
                        pos <= END;
                    end
                    else begin
                        data_bit_count <= data_bit_count + 1'b1;
                    end
                end
            end
            END: begin
                if(rx_clk_bps) begin
                    rx_done_sig <= 1'b1;
                    pos <= BFREE;//也可寫<=pos+1
                    rx_band_sig <= 1'b0;
                end
            end
            BFREE: begin
                rx_done_sig <= 1'b0;
                pos <= IDLE;
            end
        endcase
    end
end

endmodule

```
## Second ver. Area and Power report
![messageImage_1705379431048](https://hackmd.io/_uploads/rJCyPKQtp.jpg)


![14](https://hackmd.io/_uploads/HyG2xKQYp.jpg)

面積由原本的2473縮小為2354,縮小率大約為4.8%.



## 第三版

1. 合併狀態後思考著編碼方式的差別，因為one-hot編碼，每個編碼都只有一個高位元所以邏輯上不會合成出複雜的decoder電路。參考課本第299頁
![17](https://hackmd.io/_uploads/SknBEtmKT.jpg)

![18](https://hackmd.io/_uploads/B1g_NFmYp.jpg)



隱憂:相較第二版的2進制只需要3位元，one-hot需要5位元---->面積下降不大。

好處:也因為邏輯轉換上較為簡單(每次只有一個1變0，一個0變1，而二進位可能有多位轉換)我們可以推測，功率會比較小。
```verilog=
module rx_ctl(
    input clk,
    input rst,
    input rx_pin_in,
    input rx_pin_H2L,
    output reg rx_band_sig,
    input rx_clk_bps,
    output reg [7:0] rx_data,
    output reg rx_done_sig
);

// 使用one-hot編碼定義狀態
localparam [4:0]
    IDLE = 5'b00001,
    BEGIN = 5'b00010,
    DATA = 5'b00100,  // 合併所有數據狀態
    END = 5'b01000,
    BFREE = 5'b10000;

reg [4:0] pos; 
reg [2:0] data_bit_count; // 計數器用於追蹤數據位

always @(posedge clk or posedge rst) begin
    if (rst) begin
        rx_band_sig <= 1'b0;
        rx_data <= 8'd0;
        pos <= IDLE;
        rx_done_sig <= 1'b0;
        data_bit_count <= 3'd0;
    end else begin
        case (pos) // 使用one-hot狀態機
            IDLE: begin
                if (rx_pin_H2L) begin
                    rx_band_sig <= 1'b1;
                    pos <= BEGIN;
                    rx_data <= 8'd0;
                    data_bit_count <= 3'd0;
                end
            end
            BEGIN: begin
                if (rx_clk_bps) begin
                    if (rx_pin_in == 1'b0) begin
                        pos <= DATA;
                    end else begin
                        rx_band_sig <= 1'b0;
                        pos <= IDLE;
                    end
                end
            end
            DATA: begin
            if (rx_clk_bps) begin
                rx_data[data_bit_count] <= rx_pin_in;
                if (data_bit_count == 3'd7) begin
                    pos <= END;
                end else begin
                    data_bit_count <= data_bit_count + 1'b1;
                end
            end
        end
        END: begin
            if (rx_clk_bps) begin
                rx_done_sig <= 1'b1;
                pos <= BFREE;
                rx_band_sig <= 1'b0;
            end
        end
        BFREE: begin
            if (rx_clk_bps) begin
                rx_done_sig <= 1'b0;
                pos <= IDLE;
            end
        end
    endcase
   end
end

endmodule
```

## Third Ver. Area and Power report
![14D05D22-82A3-453C-8F2C-6A6D485D45F6](https://hackmd.io/_uploads/H1WhuKmKp.jpg)




![16](https://hackmd.io/_uploads/HksHfFmtT.jpg)

與原面積相比,由2473降至2306,縮小率約為6.75%.

## UART在FPGA上的實測

![100](https://hackmd.io/_uploads/SJChg9QKp.jpg)

![101](https://hackmd.io/_uploads/rkZCx5QKT.jpg)

![102](https://hackmd.io/_uploads/S1lgW9XFa.jpg)

![103](https://hackmd.io/_uploads/H1D4-9QYp.jpg)

![104](https://hackmd.io/_uploads/ByXr-qmKa.jpg)

![105](https://hackmd.io/_uploads/H12BZ57Y6.jpg)


[demo影片](https://youtu.be/bnsP-E6n6Qc?si=9rLoodm-iH_VMuvb)

