---
# System prepended metadata

title: 軟硬體協同設計HW5

---

# 軟硬體協同設計HW5
### ●　作業標題：Improve code coverage of your design
### ●　班級姓名座號：國立高雄大學電機系大四 B1095117 黃致衡
### ●　授課老師：林宏益教授

---
## 一、作業內容：
###
針對上課講義內容所提及的 Finite State Machine codes 進行 code coverage 分析。

## 二、實作步驟：

### 1. 撰寫 simple_moore_fsm 的 RTL code (moore__fsm.v)
```
module  simple_moore_fsm(
    clk,
    rst_n,
    inpl,
    outp
    );

    input clk, rst_n, inpl;
    output outp;

    reg [1:0] curr_state, next_state;
    reg outp; 

    parameter IDLE = 2'd0;
    parameter S0 = 2'd1;
    parameter S1 = 2'd2;


    //state transient

    always @(posedge clk or negedge rst_n) 
    begin
        if (!rst_n)
            curr_state <= IDLE;
        else
            curr_state <= next_state;
    end

    always @(curr_state or inpl)
    begin
        case(curr_state)
            IDLE:       next_state = (inpl == 1'd1) ? S0 : IDLE;
            S0:         next_state = (inpl == 1'd1) ? S1 : IDLE;
            S1:         next_state = (inpl == 1'd1) ? S1 : IDLE;
            
            // VCS coverage off
            default:    next_state = IDLE;
            // VCS coverage on
            
        endcase
    end

    always @(curr_state)
    begin
        case(curr_state[1:0])
            IDLE:       outp = 1'd0;
            S0:         outp = 1'd0;
            S1:         outp = 1'd1;
            
            // VCS coverage off
            default:    outp = 1'd0;
            // VCS coverage on
            
        endcase
    end

endmodule
```
### 2. 再撰寫 simple_moore_fsm 的 Testbench (moore__fsm__tb.v)
```
module  simple_moore_fsm_tb;

    reg clk_in, rst_n, inp;
    wire fsm_out;

    parameter clk_duration = 10;

    simple_moore_fsm simple_moore_fsm_try(clk_in, rst_n, inp, fsm_out);


    initial 
        clk_in = 1'b0;
        always #(clk_duration/2)    clk_in = ~ clk_in;

    initial
    begin
        $dumpfile("hw_and_sw_hw5.vcd");
        $dumpvars;
        $fsdbDumpfile("hw_and_sw_hw5.fsdb");
        $fsdbDumpvars;
        $monitor("clk = %b, rst = %b, input = %b, output = %b", clk_in, rst_n, inp, fsm_out);
    end

    initial
    begin
        rst_n = 1'b0;   inp = 1'b0;
        #10 rst_n = 1'b1;  inp = 1'b0;
        #10 inp = 1'b1;
        #10 inp = 1'b0;
        #10 inp = 1'b1;
        #10 inp = 1'b1;
        #10 inp = 1'b1;
        #10 inp = 1'b0;
        #10
        $finish;
    end

endmodule
```
### 3. 使用 lcarus Verilog 經過 compile 產生 .vcd檔，並使用 GTKWave 預先查看合成前 simulation 的波型結果
![gtk](https://hackmd.io/_uploads/Sy43eiDET.png)
> 由此張波型結果雖可以一步一步推斷各個時間所產生的值，但無法直接了解其所處的狀態 (如：IDLE, S0, S1) 為何？

### 4. 將所有 Verilog 檔案與 filelist.f 上傳至 EDA cloud，並將上述步驟改於工作站進行

### 5. 設定所要執行的 makefile 檔案功能，並於工作站使用指令 UNIX% make vcs_kdb 進行編譯
```
.PHONY:clean vcs_kdb vcs_cov verdi_kdb verdi_cov

VCS = Rvcs
VERDI = Rverdi

#***** coverage option *****
COV_METRICS_SEL = line+cond+fsm+branch
#COV_METRICS_SEL = line+cond+fsm+branch+tgl  #for postsim


#***** VCS compile option *****
VCS_COMP_OPT =				\
			-full64			\
			-debug_acc+all	\
			-j4				\
			-lca			\
			-kdb			\
			-sverilog		\
			-Xkeyopt=rtopt	\
			-Mupdate		\
			-R   			\
			+v2k			\
			
			
#***** VCS simulate option *****
VCS_SIM_OPT =					\
			+vcs+fsdbon			\
			-timescale=1ns/1ps	\
			-l ./logfile/vcs_kdb_compiled.logfile/vcs_kdb_compiled\
			+vcs_flush+all		\
			
			
#***** VCS coverage option *****
VCS_COV_OPT =						\
			-cm	$(COV_METRICS_SEL)	\
			-cm_log	./logfile/vcs_cov_$(COV_METRICS_SEL)_compiled.log	\
			-cm_dir ./coverage/coverage.vdb							\
			-cm_name coverage
			
				
#***** VCS compilation  *****		
vcs_kdb:			
		$(VCS)				\
		$(VCS_COMP_OPT)		\
		$(VCS_SIM_OPT)		\
		-file filelist.f	\
		
vcs_cov:
		$(VCS)				\
		$(VCS_COMP_OPT)		\
		$(VCS_SIM_OPT)		\
		$(VCS_COV_OPT)		\
		-file filelist.f	\
		

#***** Verdi compilation  *****
verdi_kdb:
		$(VERDI) -f filelist.f -ssf novas.fsdb

verdi_cov:
	    $(VERDI) -cov -covdir ./coverage/coverage.vdb
		
		
clean:
       rm -rf unrSimv* csrc* ./logfile/* *key *fsdb *vcd *Log *bak *el *report no_trace* *.dump
	   rm -rf simv* verdi_* partition* dprof* clk* *DB *dir work *lib *.daidir nWave* DVE* *.out
	   rm -rf novas* cm.* ./coverage/* *.log *.vdb
```

### 6. 使用指令 UNIX% make verdi_kdb 開啟 Verdi 檢視波型運行結果與其產生的 FSM diagram
![waveform](https://hackmd.io/_uploads/B11HEjDVa.png)
![315482](https://hackmd.io/_uploads/rJ-UBoP4a.jpg)

> 藉由上課講義所提供的 FSM diagram，可驗證波型結果有成功運行到每個狀態，(moore__fsm.v) 與 (moore__fsm__tb.v) 撰寫正確無誤！

### 7. 使用指令 UNIX% make vcs_cov 進行 coverage 分析，並使用指令 UNIX% make verdi_cov 開啟 Verdi 檢視分析報告
> 分析結果顯示於「三、實作結果」。



## 三、實作結果：

### ◎ fullscore
![full score](https://hackmd.io/_uploads/rkKEwjPN6.png)

### ◎ line coverage
![line coverage](https://hackmd.io/_uploads/HkCxOiP4a.png)

### ◎ FSM coverage
![FSM coverage](https://hackmd.io/_uploads/Sy9M_ovE6.png)

### ◎ condition coverage
![condition coverage](https://hackmd.io/_uploads/BkwddsP4a.png)

### ◎ branch coverage
![branch coverage](https://hackmd.io/_uploads/H1F5diDVp.png)



## 四、實驗討論：

### 1. 要如何提升 Line coverage 數值？
###
如實驗結果，可見到在程式碼中大部分的程式碼都被標上了綠色的底色，代表該行程式碼有被執行到。而唯一一行沒有被執行到並被標上紅色底色的程式碼為 `default:    outp = 1'd0;` 考慮到若 case 法中若不使用此設定，可能造成電路在合成結果時容易產生非預期的 latch 可能，因此將其保留。

而在分析時的 Line coverage 分數在 97 分的位置，落在可以接受的範圍內，因此此狀況不予理會。

### 2. 要如何提升 FSM coverage 數值？
###

由於此作業一開始給的 testbench 程式碼僅有 75% 的 FSM coverage，因此將其修改到 100% 為此次作業的重點目標。

首先，將原程式碼進行分析時，在 FSM coverage 跑出了此狀況(如下圖)。

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

由上圖可知，在狀態由 S0 跳回 IDLE 時是沒有被運行到的，藉由查找原程式碼的 testbench，發現於 initial 語法中的設定全部皆設定為 100 time units。

此設定方法會使第 30 行的設定 (如下圖) 原意是要由狀態 S0 跳回 IDLE，但 CLK 寫入的速度比起訊號的更動速度還要快，導致其一直維持著 `inp = 1'b1;` 便錯誤地由狀態 S0 跳到 S1，後續的設定更是無法驗證到「由狀態 S0 跳回 IDLE」此路徑。因此我將其先改成 time units 等於 #10，使其過了 10 個 time units 馬上產生 `inp = 1'b0;` 在 CLK posedge 前成功「由狀態 S0 跳回 IDLE」。

![tb too long](https://hackmd.io/_uploads/HJRfhjwEa.png)

最後，考慮到訊號更動的 time units 若設定的與 CLK duration 不同步的話，容易在 sequential 電路中撰寫 testbench 時沒有成功驗證到所有預設的狀態，因此最後我將下列包含在 initial 裡面的設定都改成 10 個 time units，而成功達到 100% 的結果顯示於「三、實作結果」。

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

### 3. 要如何提升 Condition coverage 數值？
###
如實驗結果，可見到每個條件判斷句都成功執行到，因此達成率 100%。

### 4. 要如何提升 Branch coverage 數值？
###
如實驗結果，受限於程式碼 `default:    outp = 1'd0;` 該行於 Line coverage 分析時並未成功執行到乃肇因於 case 語法中的所有設定皆已涵蓋所有結果，因此該行於 Line coverage 分析時並未執行；同理，branch coverage 分析時也不會跳躍到該行，因此無法達成到 100%。

## 五、實驗心得：
### 
本次的作業學習到了數位IC設計前端所需的三大工具之一「VCS」，而對於此工具從未觸碰過的我其實在 makefile 的調整就一頭霧水，光 userguide 裡面所提供的功能更是不勝枚舉。

而本次的作業在調整分析時並不至於太難，但在 Verdi 這個軟體所具備的功能與操作方式，我僅學習到了冰山一角而已，看來在這條學習道路上，對於環境操作以及軟體熟悉程度，我還需要付出更多心力來學習。

## 六、參考文獻：

> EEF946〈軟硬體協同設計〉課堂參考講義














