# 軟硬體協同設計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〈軟硬體協同設計〉課堂參考講義