# 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部分**:
觀察輸出
觀察輸出波型

**vivado部分**:
觀察輸出波型:

結果全部吻合預期----->合成schematic


七、心得-這是第一次使用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 -暴力輸入**

----->結果吻合預期
觀察波形圖

----->同樣吻合預期
2.放入vivado做模擬
run simulation 確認輸出與輸入埠正確
----->查看波形

----->符合預期
RTL ANALYSIS 的schematic 圖






----->10個多工器吻合預期
IMPLEMENTATION
schematic:

分析報告與心得:

在分析報告中,我的logic power為0.032w,雖然不是特別耗能,但是我覺得我的if else 語句造成elaborated schematic 圖超級長!,應該是RTL CODE沒有設計好,也許有更好的解法尚未想到。
## FPGA 驗證
**當preset=1 reset=1** **輸出:1111000000**

**reset_n=1 preset=0**
**輸入:0000 輸出:0111111111**

**輸入:0001 輸出:1011111111**

# 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**


## 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
```
**結果:**

## Schematic
RTL

IMPLEMENTATION

POWER

## 工作站模擬
Verdi Tool


Wave

**結果與預期相符--->成功!!**
## FPGA 驗證
**reset_n=0**
全部------>顯示H

**reset_n=1**
輸入:0000------>顯示0

**reset_n=1**
輸入:0001------>顯示1

**reset_n=1**
輸入:0010------>顯示2

**reset_n=1**
輸入:0011------>顯示3

**reset_n=1**
輸入:0100------>顯示4

**reset_n=1**
輸入:0101------>顯示5

**reset_n=1**
輸入:0110------>顯示6

**reset_n=1**
輸入:0111------>顯示7

**reset_n=1**
輸入:1000------>顯示8

**reset_n=1**
輸入:1001------>顯示9

**reset_n=1**
輸入:1010------>顯示A

**reset_n=1**
輸入:1011------>顯示b

**reset_n=1**
輸入:1100------>顯示C

**reset_n=1**
輸入:1101------>顯示d

**reset_n=1**
輸入:1110------>顯示E

**reset_n=1**
輸入:1111------>顯示F

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

在FSM Coverage看到,過程中並沒有執行到s0 ----> IDLE
## 推測------>看波型

看出inp 輸入延遲太長,導致inp一直為1,沒有回到0,讓s0回到IDLE。
## 提升覆蓋率------>修改testbench
**INP輸入延遲改成10ps**

**波型確認**

覆蓋率確認

**---->皆有執行**
## 為何不能到達Line、Branch無法到達100%

**軟體無法忽略default敘述,因為testbench沒有跑到可是卻有這行敘述,所以無法到達100%**
## 解決:忽略default這個覆蓋率
**修改編譯選項
--->新增 VCS coverage off/on
意義:模擬但不統計覆蓋率**
**覆蓋率確認**

--->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

## Lint

## Schematic

# 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通訊協議來實現資料傳輸

本次是實現9600bps的通訊協議
## 架構

## 原版程式
目的:將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
```

```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
```

```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
```
## 波型驗證圖






## Area and Power report
Design Compiler
最小面積使用與最小動態功率Constraint




---->沒有設面積2900up

|
## 第二版
思考狀態機的縮減,將接收資料狀態合併成一個狀態--->用編碼減少狀態
```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


面積由原本的2473縮小為2354,縮小率大約為4.8%.
## 第三版
1. 合併狀態後思考著編碼方式的差別,因為one-hot編碼,每個編碼都只有一個高位元所以邏輯上不會合成出複雜的decoder電路。參考課本第299頁


隱憂:相較第二版的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


與原面積相比,由2473降至2306,縮小率約為6.75%.
## UART在FPGA上的實測






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