## 團隊 隊名 絕園的暴風雨 組長 林建圻 組員 柯柏宇 ## 前言 在本文中,首先會介紹多種演算法來實現 SME 的功能,並且對使用不同演算法的電路進行電路效能分析,進而比較出不同演算法的優缺點,接著會進行電路架構的細部分析,並且在最後使用 Coverage 驗證 Testbench 的完整度以及使用 Spyglass 驗證 Coding style。 String Matching Engine 其功能為將依序提供數個字串(後文以 String 表示)及關鍵字樣本(後文以 Pattern 表示),SME 電路需比對該 Pattern 是否包含在該 String 中,若有則回應比對成功(match)以及比對到的位置,更多細節可參考 2020 University/College IC Design Contest。 (註:AAO演算法參考其他組別) ## 設計實作摘要 |是否通過 RTL (合成前, pre-synthesis)驗證? |通過 | | - | - | |是否通過 gate-level(post-synthesis)驗證? |通過 | |Clock period (ns) |20 | |Number of cycles |451 | |Patterns score (Pattern 正確數目) |100 | |Area (um2) |25413\.472312 | |Power (mW) |0\.4774 | |Simulation time (ns)(合成後) |9020 | |是否引用其他組的設計構想或架構? |YES | |Coding style check and enhancement? |YES | |Code coverage evaluation and enhancement? |YES | ## 工作分配與貢獻 ![](https://hackmd.io/_uploads/Hkd2Yt3Ch.png) ## 分數 此份報告為國立中山大學的實用數位系統設計課程中的期末報告,取得106分,班上排名前三 ![](https://hackmd.io/_uploads/Bk8pqF3Cn.png) ## 設計構想報告 {%youtube mz3VBgJXZJA %} ## 期中進度報告 {%youtube GqZsPVbEH4w %} https://www.youtube.com/watch?v=mz3VBgJXZJA&ab_channel=Kerwin https://www.youtube.com/watch?v=GqZsPVbEH4w&ab_channel=Kerwin ## 壹、演算法 ### Brute Force ![](https://hackmd.io/_uploads/SJao2pCTn.png) #### 資料存放 當 isstring 為 1 時,會將 String 中的字元放入 Str\_reg,而 Str\_reg 有 33 個空間,Str_reg[0]和第 Str\_reg[33]個位置會固定存放空白,目的是為了「^」與 「$」的比對。當 ispattern 為 1 時,會將 Pattern 中的字元放入 Pat\_reg,Pat\_reg 有 8 個空間。 ![](https://hackmd.io/_uploads/B1zuaTRph.png) #### 一般比對方式 首先會將 Pattern 的開頭 Pat\_reg[0]作為起始位置,當前的起始位置就是比對位置,與 String 做比對,當起始位置比對成功時,會由起始位置的下一個字元做為比對位置,當比對位置比對成功時,會將比對位置移到下一個字元,若比對失敗會將比對位置返回起始位置,當 Pattern 全部比對完或是起始位置比對到 String 的底部時,就會輸出比對結果。 ![](https://hackmd.io/_uploads/HyuFap0ph.png) #### 特殊字符「**.**」 當比對位置的字元是「.」時,會無條件比對成功。 #### 特殊字符「**^**」 因為「^ 」只會在開頭出現,所以當偵測到「^」出現時,Pattern 要從 Str\_reg[0]開始比對,接著會將「^」轉換成「 」後,後續的比對方式與一般比對方式相同。 ![](https://hackmd.io/_uploads/HJne0a0a3.png) #### 特殊字符「**$**」 當偵測到「\$」出現時,會將「\$」轉換成「」後,後續的比對方式與一般比對方式相同。 ![](https://hackmd.io/_uploads/SyiUA60p3.png) #### 特殊字符「**\***」 當偵測到「\*」出現時,會將起始位置從 Pat\_reg[0] 改為「\*」後面的字元,接著與一般比對相同,當「\*」後面的字元比對成功時,就代表比對成功。 ![](https://hackmd.io/_uploads/ByzlJR062.png) ### **Shfit Or** 首先要對 Pattern 的每一個字元進行編碼,編碼長度會是 Pattern 的長度,當字元在 String 有出現時,會根據對應的位元編碼為 0,字元在 String 沒有出現時,會根據對應的位元編碼為 1,當Pattern 的所有字元的編碼完成時,會同時將 Pattern 中沒有出現的字元編碼為 1,不過會需要龐大數量的 Flip-Flop 來對 每一個字元的編碼結果做儲存,編碼的結果稱為編碼表。 比對的運算會需要一個輸出 out,out 的初始值會將所有位元填為 1。運算程序會先將 out 左移 1bit,接著將 Pattern 編碼後的字元與 out 進行 or 運算,當 Pattern 數量對應的 out 位元為 0 時,就表示比對成功。 ![](https://hackmd.io/_uploads/Hk2My0Apn.png) ### **AAO** ![](https://hackmd.io/_uploads/rk-HkACp3.png) #### 一般比對方式 當 isstring 為 1 時,會將 String 中的字元放入 Str\_reg,當 ispattern 為 1 時, 當 chardata 在輸入的同時,會同步進行比對運算,ispattern 為 0 時就會輸出結果。 當 chardata 輸入進來時,會將 chardata 與 String 中的每一個字元做比對, 當比對成功時,會將對應位元設為 1,反之設為 0,結果存放在 match\_line, match\_line 的位元數為 34 bit,match\_line[0] 和 match\_line[33] 會設為 0,目的是 用於「^」和「$」的比對。 ![](https://hackmd.io/_uploads/SJf21ARah.png) 接著會將 match\_line 右移 count\_p,count\_p 為計算當前是第幾個 chardata 的計數器。 ![](https://hackmd.io/_uploads/HyTh1ACan.png) 再將 match\_line 與 match\_reg 做 and 運算,match\_reg 的初值由 34bit 全為 1 組成,match\_reg 的用途是暫存比對結果,當 ispattern 為 1 時,會持續進行比對 運算並且將結果存在 match\_reg,當 ispattern 為 0 時,會輸出比對結果。 ![](https://hackmd.io/_uploads/BJqpyARTn.png) 當 match\_reg 中存在 1 時,就表示比對成功,因此將 match\_reg 本身做 or 運算,可以得到 match 的結果,match\_index 則是根據 match\_reg 最先出現 1 的 位元,輸出對應 match\_index。 #### 特殊字符「**.**」 當輸入的 chardata 為「.」時,match\_line 除了 match\_line[0] match\_line[33] 以外都會設成 1,表示直接比對成功。 ![](https://hackmd.io/_uploads/BkPyeRCph.png) #### 特殊字符「**^**」 當輸入的 chardata 為「^」時,會將與 String 比對的字元換成「 」再以相 同的方式得到 match\_line。 ![](https://hackmd.io/_uploads/ryb-lCCpn.png) #### 特殊字符「**$**」 當輸入的 chardata 為「$」時,會將與 String 比對的字元換成「 」再以相同的方式得到 match\_line。 ![](https://hackmd.io/_uploads/B1QGl0Ap2.png) #### 特殊字符「**\***」 當輸入的 chardata 為「\*」時,若此時 match=0 時,表示「\*」前比對不成功,此時會 match\_line 會為 0,因為比對不成功。 若此時 match=1 時,表示「\*」前比對成功,接著只要「\*」後面比對成功,match 就會為 1,因此需要清除前面已經比對成功的結果,接著後面的比對方式與一般比對相同。當「\*」出現在 Pattern 的最前面時,因為前面並沒有字元,match 不會為 1,所以也會執行與「\*」前比對成功一樣的過程。 ![](https://hackmd.io/_uploads/rkiVl0Cpn.png) ### 演算法比較 Brute Force 的比對方式簡單,但相對來說也會需要較多的 Cycle 數來進行比對,時間複雜度最差可以來到 m\*n,不過它的面積較小,且較容易實現其他特殊字符的比對,因此有較佳的擴充性,而且在電路架構上也更具彈性,可以利用多個比對器,採用平行運算的方式來減少 Cycle數。 Shift or 因為需要進行編碼,以及將編碼的結果進行儲存,甚至會對所有的字元進行編碼,無論字元是否有出現在 String 或 Pattern 中,會造成大量的 Flip- Flop 產生,也有資源浪費的問題存在。在資源的大量消耗下,原本預期的時間複雜度為 m+n,可以帶來較低的 Cycle 數,但是後來發現到 m+n 雖然看起來相對 Brute Force 的 m\*n 少很多,但是由於 String 和 Pattern 長度較短,而且 Brute Force 在實際比對時會根據 String 的複雜程度造成 Cycle 數的增減,因此在某些情況下 Brute Force 的 Cycle 數甚至會少於 Shift or,也就造成最後 Shift or 的 Cycle 數甚至與 Brute Force 相近。 AAO 的特色在於讀取 Pattern 的 Chardata 時,會同時與 String 進行比對, 在 Pattern 讀取結束後可以立刻輸出比對結果,而且不需要狀態機,使他擁有最小可達到的 Cycle 數。AAO 也會有編碼的運算,不過相較 Shift or 來說,編碼所需要的資源與 Cycle 數都小非常多,利用編碼後的結果可以很高效的運算出 比對結果。 ||Brute Force |Shift Or |AAO | | :- | - | - | - | |時間複雜度|M\*N |M+N |N | |面積 |小 |大 |小 | |Cycle 數 |中 |中 |小 | 註 1:M 為 String 的字元個數,N 為 Pattern 的字元個數 ## 貳、電路分析 ### 邏輯合成流程說明與合成參數 ![](https://hackmd.io/_uploads/H1mlbRR6n.png) ### **BF\_v1** #### 面積與邏輯閘數量 合成後面積約為 22211um2,gate count 約為 4443 個 NAND ![](https://hackmd.io/_uploads/HJJE-0RT2.png) #### 電路運算 **cycle** 數目和 **Score(Pattern** 正確性**) Cycle 數為 1771,Score 為 100 ![](https://hackmd.io/_uploads/SJ1UZ0Ra3.png) #### 延遲與最長路徑標示 Clock 週期設為 20 ns,可以看到 data arrival time 為 14.09ns,而 data required time 為 20.11ns,slack 為 6.02ns。 ![](https://hackmd.io/_uploads/BJjvWCR6h.png) ![](https://hackmd.io/_uploads/r11dZRCT2.png) #### 功率消耗 Dynamic Power 約為 450.2095 uW,Leakage Power 約為 16.7059 uW ![](https://hackmd.io/_uploads/rJyt-0A62.png) ### **BF\_v2** 基於 BF\_v1,起始位置比對使用多個比較器 #### 面積與邏輯閘數量 合成後面積約為 36384 um2,gate count 約為 7277 個 NAND ![](https://hackmd.io/_uploads/r1OlMAAa3.png) #### 電路運算 **cycle** 數目和 **Score(Pattern** 正確性) ![](https://hackmd.io/_uploads/B14ZMC0p3.png) #### 延遲與最長路徑標示 Clock 週期設為 20 ns,可以看到 data arrival time 為 16.36ns,而 data required time 為 20.09ns,slack 為 3.73ns。 ![](https://hackmd.io/_uploads/Bk_SfCCpn.png) ![](https://hackmd.io/_uploads/BJ5HGC0p3.png) #### 功率消耗 Dynamic Power 為 487.6187 uW,Leakage Power 為 23.0339 uW ![](https://hackmd.io/_uploads/H1vPG0Can.png) **BF\_v3** 基於 BF\_v2,使用多個比較器對起始位置後的字元進行平行比對 #### 面積與邏輯閘數量 合成後面積約為 40889um2,gate count 約為 8178 個 NAND ![](https://hackmd.io/_uploads/B1OcM0A6h.png) #### 電路運算 **cycle** 數目和 **Score(Pattern** 正確性) ![](https://hackmd.io/_uploads/rkPszCAa2.png) #### 延遲與最長路徑標示 Clock 週期設為 20 ns,可以看到 data arrival time 為 15.36ns,而 data required time 為 20.1ns,slack 為 4.74ns。 ![](https://hackmd.io/_uploads/SyDnzRRT2.png) ![](https://hackmd.io/_uploads/rJhTfCR6n.png) #### 功率消耗 Dynamic Power 為 513.4961 uW,Leakage Power 為 28.8539 uW ![](https://hackmd.io/_uploads/H1_RMAA62.png) ### **AAO** #### 面積與邏輯閘數量 合成後面積約為 25413.472312um2,gate count 約為 5083 個 NAND ![](https://hackmd.io/_uploads/HJJ-70Ra3.png) #### 電路運算 **cycle** 數目和 **Score(Pattern** 正確性) ![](https://hackmd.io/_uploads/Hk8MXA0Th.png) #### 延遲與最長路徑標示 Clock 週期設為 20 ns,可以看到 data arrival time 為 20.9ns,而 data required time 為 20.5ns,slack 為 0.04ns。 ![](https://hackmd.io/_uploads/ryI7Q0CTh.png) ![](https://hackmd.io/_uploads/H19XmAR63.png) ![](https://hackmd.io/_uploads/BkTmX0Aa2.png) #### 功率消耗 Dynamic Power 為 452.6618 uW,Leakage Power 為 24.7483uW ![](https://hackmd.io/_uploads/rJnNm0Cah.png) #### 比較 BF\_v1 的面積最小,在一般比對的情況下,只使用一個比較器進行比對, 相對而言 Cycle 數就是最大的,而 BF\_v2 採用平行運算的電路架構,在一般比對的情況下,會使用 6 個比較器和加法器來進行起始位置的跳躍,但是因為進行跳躍會有邊界的問題產生,因此需要額外的小於比較器以及加減法器進行邊界判斷。所以導致 BF\_v2 的面積相對 BF\_v1 上升了 63.8%,而 Cycle 數相對 BF\_v2 下降了 37.2%,Cycle 數下降的比例並沒有面積上升的多,因此也導致在分數的表現上 BF\_v1 還是較佳。 BF\_v3 基於 BF\_v2 的架構上,除了對起始位置進行平行運算,也對起始位置後的字元比對進行平行運算,因此在一般比對的情況下,多使用了 7 個相等比較器和加法器,且同樣會需要額外的小於比較器和加法器來進行邊界判斷, 所以 BF\_v3 相對 BF\_v2 的面積上升了 12.37%,而 Cycle 數下降了 14.45%,因此分數上升了 0.019%,在分數上兩者相距不大,而 BF\_v1 的分數還是較佳。 最後採用 AAO 的電路,雖然在一般比對的情況下,會使用到 32 個相等比較器,但是因為沒有狀態機以及儲存 Pattern 的暫存器,使面積略大於 BF\_v1, 但是 Cycle 數為所有電路架構中最小的,因此分數也是最高的。 ||BF\_v1 |BF\_v2 |BF\_v3 |AAO | | :- | - | - | - | - | |面積(um2) |22211 |36384 |40888 |25414 | |Cycle 數 |1771 |1291 |1128 |451 | |分數 |0\.0254 |0\.0213 |0\.0217 |0\.0873 | ## **參、架構介紹與說明** ### BF架構 ![](https://hackmd.io/_uploads/ryY-X-yA2.png) #### 資料輸入 Chardata 會根據 istring 和 ispattern 訊號存入不同記憶體,當 istring = 1 存 入 MEM string, 當 ispattern = 1 存入 MEM pattern,同時,特殊字元檢測會檢 測 Chardata 是否為特殊字元,並執行對應的處理,後將結果送入 MEM 。 ![](https://hackmd.io/_uploads/B1FS7WkR3.png) #### 記錄字元數 Counter 會在 char 輸入的同時,根據現在的輸入狀態是 isstring 或 ispattern 記錄 string 和 pattern char 的數量,並存入對應的暫存器,isstring = 1 存入 Str\_num ,ispattern =1 存入 Pat\_num 。 ![](https://hackmd.io/_uploads/SyIoXbJRh.png) #### 比對與輸出 FSM2 (有限狀態機 2) 會依據比對的情況使用 Check\_T 或 Check\_N 比較 器,Check\_T 用來找出首位符合比對要求的字符,Check\_N 用來找出下一個符 合比對要求的字符。 Comparator output 負責比對 output 結果與輸出時機,當 Number of match = pattern number 時,表示所有 pattern 都被比對到,輸出 match =1 ,valid = 1 以及對應的 match index;相對的,當比對失敗且 string 全都比對過,則輸出 match =0 ,valid = 0,match index 為任意值(根據電路比對過程)。每次的比對和輸出結果都會送回 FSM2 作為下次狀態判斷的依據。 ![](https://hackmd.io/_uploads/HkKa7ZJ0n.png) ### 狀態機 #### FSM1 (有限狀態機1) ![](https://hackmd.io/_uploads/Sy2gEZJC3.png) FSM1 主管電路的主要狀態轉換,狀態從 INIT 開始,根據 isstring 和 ispattern 進入不同資料輸入狀態,當 isstring =1 進入 input string reg,當 ispattern =1 進入 input pattern reg,後進入 Match 狀態進行字符比對,比對結束後進入狀態 DONE,將結果輸出給 HOST,狀態回到 INIT 。 #### FSM2 (有限狀態機 2) ![](https://hackmd.io/_uploads/H1PuEWk03.png) FSM2 主管比對模塊的狀態轉換,狀態從 S1 開始,先進入 S2 狀態找第一 個比對成功的字符,找到後進入 S3 找下個比對成功的字符,如果失敗則回到 S1。當 string 都比對過或 pattern 字符全都比對成功時回到 S1。 ### AAO 架構 ![](https://hackmd.io/_uploads/rkOnNbJR2.png) #### 資料輸入與前處理 當 isstring = 1 時,string char 會通過 mux 進入 string reg 中儲存;當 ispattern = 1 時,pattern char 會通過 mux 進入比較器與 string reg 進行比對,並將結果存於 match\_line reg 中。 同時,counter 會分別記錄 string char 的數量與 pattern char 輸入的次數,將結果分別存於 str\_num 和 count\_pat 中。 ![](https://hackmd.io/_uploads/rJRbHZ1Rn.png) #### 比對與結果輸出 Match_line 的資料會進入 shift 電路進行右移,資料右移 Count\_pat 次後與 Match reg 進行 AND 運算,將結果存於 Match reg,最後通過 OR 運算輸出 match 與通過 DECODER 輸出 match index。 ![](https://hackmd.io/_uploads/HJYmS-yRn.png) #### 星號模式開啟 當 pattern char == star 時,match reg 旁的 mux 會開啟,並將第二次比對進 行所需的數據傳給 match\_reg,同時重置 count\_pat。 最後仍通過 OR 運算與 DECODER 分別輸出 macth 和 match index。 ![](https://hackmd.io/_uploads/Bk3rrZyCn.png) #### 控制線判斷電路 ##### valid控制 valid 控制由一個 mux 控制,只有 reset 時才會歸零,其餘時間為高位。 ![](https://hackmd.io/_uploads/SJVjBbyRh.png) ##### 特殊字元檢測器 檢測特殊字元 $錢、^帽子、\*星號、星號位於首位等情況是否發生,發生時訊號為 1 , 未發生時訊號為 0 。 ![](https://hackmd.io/_uploads/HJsnB-JA3.png) ## 肆、Testbench與驗證完整度 藉由輸入不同組合的 pattern ,以此驗證各種情況下的正確性。並搭配 IMC coverage 結果,對 testbench 進行調整。 ![](https://hackmd.io/_uploads/HJs9IWJRh.png) #### 驗證流程 ![](https://hackmd.io/_uploads/r1nTIbkR2.png) 先撰寫 RTL code,進行 pre\_sim, 通過則接續進行 corner case、spyglass 驗 證,未通過則調整 RTL 重新驗證。通過後進行 IMC 驗證,未通過則調整 tb, 重新驗證。合成後進行 post\_sim,未通過則調整 RTL 重新進行驗證流程,通過則驗證流程結束。 #### Corner case 可分為以下幾種情況 ##### 1. 相似語句:出現相似語句 - String: pen pan - Pattern : pen ##### 2. 重複語句:重複同樣的語句 - String: pen pen pen - Pattern : pen ##### 3. 重複與相似語句 **:** 同樣與相似的字句重複出現 如以下例子: - String : pen pen pan pan pen pan - Pattern 1 : pen - Pattern 2 : pan - Pattern 3 : p.n - Pattern 4 : .p.n - Pattern 5 : ^p.n - Pattern 6 : p.n$ - Pattern 7 : ^p.n$ ##### 4.Pattern 由特殊字符組合: ^ $ \* . 四者交互搭配 - 如 : 「\^\.\$」、「\^\.\*.\$」、「\^\.\.」、「\*.\$」、「\^\.\*」、「\..\$」 ##### 5. 單一字符 - String : 只有一個字符,如: 「N」 - Pattern: 只有一個字符,如: 「N」、「.」、「^」、「$」、「\*」 ##### 6. 填滿字符 - String: 填滿 32 個字符 - Pattrn : 填滿 8 個字符 #### 字符與輸出訊號解答資料表 |字符與輸出訊號解答資料表|||| | - | :- | :- | :- | |TYPE |match |Match index |CONTENT | |str1 |||corner-case verification , pass? | |pat1 |1 |8 |a | |pat2 |0 |0 |b | |pat3 |1 |c |verifica | |pat5 |1 |c |^verific | |pat6 |0 |0 |verific$ | |pat7 |0 |0 |^verifi$ | |pat8 |1 |19 |^.$ | |pat9 |0 |0 |^..$ | |pat10 |0 |0 |^...$ | |pat11 |0 |0 |^....$ | |pat12 |1 |1b |^.....$ | |pat13 |0 |0 |^......$ | |pat14 |1 |0 |...\*... | |pat15 |1 |0 |\*.... | |pat16 |1 |0 |...\* | |pat17 |1 |0 |^.\*.$ | |str2 |||pen pan pem pen pan pem | |pat1 |1 |0 |pen | | - | - | - | - | |pat2 |1 |4 |pan | |pat3 |1 |8 |pem | |pat4 |1 |3 |.p.n | |pat5 |1 |0 |p.n | |pat6 |1 |0 |^p.n | |pat7 |1 |0 |p.n$ | |pat8 |1 |0 |^p,n$ | |pat9 |1 |0 |p\*n | |str3 |||a | |pat1 |1 |0 |a | |pat2 |0 |0 |b | |pat3 |0 |0 |abca | |pat4 |1 |0 |^.$ | |pat5 |0 |0 |^ | |pat6 |0 |0 |$ | |pat7 |1 |0 |\* | |pat8 |1 |0 |. | |pat9 |0 |0 |p | |str4 |||123456–123-789 | |pat1 |1 |6 |– | #### 波型展示 **STR 1: corner-case verification , pass?** ![](https://hackmd.io/_uploads/S1rhvbJRn.png) Isstring = 1 時, string char data 成功寫入 **PAT1: a** ![](https://hackmd.io/_uploads/B1S6DZyRh.png) ![](https://hackmd.io/_uploads/S1uaPZJA2.png) 預期:(match , match index) = (1 , 08) 取得:(match , match index) = (1 , 08),結果: 正確 **PAT2: b** ![](https://hackmd.io/_uploads/HyMCwZJCn.png) ![](https://hackmd.io/_uploads/rkUAwWJC3.png) 預期:(match , match index) = (0 , 00) 取得:(match , match index) = (0 , 00),結果: 正確 **PAT3: verifica** ![](https://hackmd.io/_uploads/BJC0vb1An.png) ![](https://hackmd.io/_uploads/B1bkOZ1An.png) 預期:(match , match index) = (1 , 0c) 取得:(match , match index) = (0 , 0c),結果: 正確 **PAT5~ PAT12:** ![](https://hackmd.io/_uploads/HkaJ_b1A3.png) <table><tr><th colspan="1"></th><th colspan="1">type </th><th colspan="1">match </th><th colspan="1">match index </th><th colspan="1">char </th><th colspan="1">正確性 </th></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat5 </td><td colspan="1">1 </td><td colspan="1">c </td><td colspan="1">^verific </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">c </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat6 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">verific$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat7 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">^verifi$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat8 </td><td colspan="1">1 </td><td colspan="1">19 </td><td colspan="1">^.$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">19 </td><td colspan="1"></td></tr> </table> <table><tr><th colspan="1">預期 </th><th colspan="1">pat9 </th><th colspan="1">0 </th><th colspan="1">0 </th><th colspan="1">^..$ </th><th colspan="1" rowspan="2">O </th></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat10 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">^...$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat11 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">^....$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat12 </td><td colspan="1">1 </td><td colspan="1">1b </td><td colspan="1">^.....$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">1b </td><td colspan="1"></td></tr> </table> **PAT13~ PAT17:** ![](https://hackmd.io/_uploads/SyH8uWk03.png) <table><tr><th colspan="1"></th><th colspan="1">type </th><th colspan="1">match </th><th colspan="1">match index </th><th colspan="1">char </th><th colspan="1">正確性 </th></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat13 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">^......$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat14 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">...*... </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat15 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">*.... </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat16 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">...* </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> <table><tr><th colspan="1">預期 </th><th colspan="1">pat17 </th><th colspan="1">1 </th><th colspan="1">0 </th><th colspan="1">^.*.$ </th><th colspan="1" rowspan="2">O </th></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> **STR2 : pen pan pem pen pan pem** **PAT1~ PAT9:** ![](https://hackmd.io/_uploads/S1RPd-kCn.png) <table><tr><th colspan="1"></th><th colspan="1">type </th><th colspan="1">match </th><th colspan="1">match index </th><th colspan="1">char </th><th colspan="1">正確性 </th></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat1 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">pen </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat2 </td><td colspan="1">1 </td><td colspan="1">4 </td><td colspan="1">pan </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">4 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat3 </td><td colspan="1">1 </td><td colspan="1">8 </td><td colspan="1">pem </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">8 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat4 </td><td colspan="1">1 </td><td colspan="1">3 </td><td colspan="1">.p.n </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">3 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat5 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">p.n </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat6 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">^p.n </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat7 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">p.n$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> <table><tr><th colspan="1">預期 </th><th colspan="1">pat8 </th><th colspan="1">1 </th><th colspan="1">0 </th><th colspan="1">^p,n$ </th><th colspan="1" rowspan="2">O </th></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat9 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">p*n </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> **STR3 : a** **PAT1~ PAT9:** ![](https://hackmd.io/_uploads/ryrqd-JR2.png) <table><tr><th colspan="1"></th><th colspan="1">type </th><th colspan="1">match </th><th colspan="1">match index </th><th colspan="1">char </th><th colspan="1">正確性 </th></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat1 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">a </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat2 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">b </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat3 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">abca </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat4 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">^.$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> <table><tr><th colspan="1">預期 </th><th colspan="1">pat5 </th><th colspan="1">0 </th><th colspan="1">0 </th><th colspan="1">^ </th><th colspan="1" rowspan="2">O </th></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat6 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">$ </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat7 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">* </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat8 </td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1">. </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">0 </td><td colspan="1"></td></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat9 </td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1">p </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">0 </td><td colspan="1">0 </td><td colspan="1"></td></tr> </table> **STR4 : 123456–123-789** **PAT1:** ![](https://hackmd.io/_uploads/H1sn_W1Ch.png) <table><tr><th colspan="1"></th><th colspan="1">type </th><th colspan="1">match </th><th colspan="1">match index </th><th colspan="1">char </th><th colspan="1">正確性 </th></tr> <tr><td colspan="1">預期 </td><td colspan="1">pat1 </td><td colspan="1">1 </td><td colspan="1">6 </td><td colspan="1">– </td><td colspan="1" rowspan="2">O </td></tr> <tr><td colspan="1">取得 </td><td colspan="1"></td><td colspan="1">1 </td><td colspan="1">6 </td><td colspan="1"></td></tr> </table> ## 伍、**Spyglass** ### 第一部分: AAO 電路的 spyglass message 結果 #### Design read error SYNTH\_5255、 Error AnalyzeBBOX (不影響 RTL 和合成後模擬的正確性) (在現有架構下,不好解決) ![](https://hackmd.io/_uploads/Bke7Fby0h.png) #### Lint warning match\_line is assigned multiple times (電路正常的現象) ![](https://hackmd.io/_uploads/rJYVYZ1R3.png) #### Spyglass 完整訊息 ![](https://hackmd.io/_uploads/ByNIK-yCn.png) 【原因】: 由於寫法架構的限制,讓比對時可能會發生 index 超出 string 暫存器的邊界,進而導致錯誤。以下圖為例,str\_reg 和 match\_line 是 34 bytes 的 MEM,而 str\_num 根據電路先前的運作,最高可達 34,會超出上述兩個 MEM 的邊界,然而受制下圖的 for loop 還有控制其他電路,因此如不更改電路架構,則難以改善超出 MEM 的 index 邊界的問題。 ****問題寫法 示意圖**** ![](https://hackmd.io/_uploads/HkhPtWJA3.png) 【解決方法】: 改變電路架構和寫法,index 數不同的電路分開撰寫 ### 第二部分: 遭遇問題與解決方法 #### 錯誤訊息 ##### 1. **blocking error** 【原因】: 在 sequential circuit 中,用 blocking 描述都會出現這個錯誤 【描述】: 在 sequential circuit 中使用 blocking 描述 ![](https://hackmd.io/_uploads/BJ9atbJ0n.png) 【解決方法】: 把 blocking 描述改成 non-blocking 描述。 ****出錯的程式碼 示意圖**** ![](https://hackmd.io/_uploads/BJhkq-yR3.png) ****修改後的程式碼 示意圖**** ![](https://hackmd.io/_uploads/ryDZqbyC3.png) ##### 2. combinational loop exist 【描述】: 產生 combinaitonal loop ![](https://hackmd.io/_uploads/By9mq-kRn.png) 【解決方法】: 不要使用會產生 combinational loop 的寫法,如在 combinational circuit 中使用 feedback。 此種寫法會產生 combinational loop ![](https://hackmd.io/_uploads/S1LVqbyA3.png) ![](https://hackmd.io/_uploads/rkFH9-yCh.png) 可能產生問題**:** RTL 模擬正常,但合成後的模擬訊號異常,準位與預想不同,並且持續發 生不希望的訊號變化。如下圖所示 ![](https://hackmd.io/_uploads/H1ZdcZJR3.png) ##### 3.inferlatch 【原因】: 當某個訊號未完整被定義時,預設為任意值,也就讓 latch 功能 產生,故當訊號未定義完全就會出現 latch。 【描述】: 出現 latch ![](https://hackmd.io/_uploads/Skfcc-k02.png) 【解決方法】: 填滿 if 語句 或 case 語句 , 或事前電路規劃完善,不要產生一定需要使用 latch 的情形。 ##### 4. SYNTH\_5255 【原因】: 使用 for loop 對 MEM 某個暫存器進行定義時,其 index 超出暫存器或 MEM 的範圍。 【補充】: 因 index 超出暫存器部分屬不合法,故超出部分不能進行合 成,所以出現不能合成的警告,Error AnalyzeBBOX 與 SYNTH\_5255 是聯動錯誤。 【描述】: index 超出 reg 宣告數量,此部分不可合成 ![](https://hackmd.io/_uploads/H1eR9bkAn.png) 【解決方法】: 調整 for loop 邊界定義,或是調整暫存器的大小。 出錯程式碼與可進行調整部分 示意圖 ![](https://hackmd.io/_uploads/HJb1sWyRh.png) #### 警告訊息 ##### 1. **multiple assign** 【原因】: 在同個 always block 中,上半段對狀態機中的訊號定義,但下半 段又對狀態機中的訊號進行定義,進而出現重複定義的問題。 【描述】: 在同個 always block 中,done 變數被重複定義 ![](https://hackmd.io/_uploads/H1EMj-yC3.png) 【解決方法】: 事前設計規劃上,「控制模塊」 與 「工作模塊」要分開 寫,只在控制模塊中清楚定義每個狀態或某個情況下的訊號值為多少,清楚定 義且只在單一模塊進行宣告,就可避免 multuple assign 的產生;或是不要在同 個 always block 進行重複宣告。 ![](Aspose.Words.f2781829-48f6-4d68-997b-c4e522a9dc4b.086.png)![](Aspose.Words.f2781829-48f6-4d68-997b-c4e522a9dc4b.087.jpeg) ##### 2. **asynchronous reset** 【原因】: 循序電路宣告時,除了 clk 外,還使用 reset 進行宣告 【描述】: 出現非同步的 reset 訊號 對進行控制進行控制 ![](https://hackmd.io/_uploads/rkIIs-yA2.png) 【可能產生問題】: 輸入 flip-flop 的 EN 啟動訊號不乾淨,會有延遲現象 產生,這是我們不樂於看見的,如以下電路示意圖。 ![](https://hackmd.io/_uploads/rySuoZJAh.png) 【解決方法】: 不要使用非同步寫法,改用以下電路的實現方式。 ![](https://hackmd.io/_uploads/Skocs-yA3.png) ##### 3. reg is always assigned over the same signal 【原因】: 想要保持暫存器永遠為某個常數時,就可能出現此警告。 【描述】: 對同個暫存器持續定義相同的常數值 ![](https://hackmd.io/_uploads/HkaaiWJCh.png) 【解決方法】: 如果是電路必要的實現方式,可忽略此警告;如果不是, 請不要進行這種定義宣告,如下圖所示。 ![](https://hackmd.io/_uploads/r1uAjWy03.png) ##### 4. **unequal length in anthnetuc comparison operator** 【原因】: 進行大小等於邏輯比較時,兩側的暫存器 bits 數不相等。 【描述】: 進行比較的變數的 bit 數不相等 ![](https://hackmd.io/_uploads/Hyik2-1Rn.png) 【解決方法】: 調整變數的 bits 數,使兩側的 bits 數相等,如下圖 match[2:0],就是選取適當的 bit 使 match\_num[2:0] 與 pat\_num 的 bits 相等。 ## 陸、Code coverage #### 第一部分: AAO 電路的 IMC message 結果 Overall average grade 100% ![](https://hackmd.io/_uploads/rk7I3bJR2.png) Imc 電路完整度訊息 (a) ![](https://hackmd.io/_uploads/rytInZJ0h.png) Imc 電路完整度訊息 (b) #### 第二部分: 遭遇問題與解決方法 ![](https://hackmd.io/_uploads/SkPv2-JR3.png) 最初完整度訊息 ##### 1. Toggle ![](https://hackmd.io/_uploads/rJaqnWJ0n.png) ![](https://hackmd.io/_uploads/SkYshWyR3.png) ![](https://hackmd.io/_uploads/rkhshW102.png) ![](https://hackmd.io/_uploads/rkbn3-y02.png) ![](https://hackmd.io/_uploads/SyBh3ZyR3.png) 驗證度不完全的變數 此驗證不完全的訊息,發生原因可分為兩種可能性, 1) 變數沒用到 => 評估變數的使用性,如無用則刪除 2) 暫存器某 bit 或 byte 沒用到 => 調整 testbench ,使暫存器的 bit 或 byte 能被使用到 ![](https://hackmd.io/_uploads/ryAJTZ1R3.png) 暫存器某部分未用到 如上圖所示,chardata[7]未被使用到。 ##### 2. **block** 某行的 **true or false** 可能性驗證度 **0** 【解決方法】觀察出錯的程式碼, 調整 testbench,讓其條件能夠被觸發。 以本電路為例,調整 pattern 的種類和數量,以及 string 的字元,讓未驗證到的 條件能夠被觸發。 ![](https://hackmd.io/_uploads/ryqfTZyR3.png) block 驗證度 message 以上圖為例,程式 101 行的 true 情況並未驗證到,故應根據調整 101 行程 式,對 testbench 進行調整,以下圖為例,可以調整輸入 pattern 和 string 的數 量與排序,使程式 101 行出現 true 的可能。