【数字设计验证】System Verilog(sv)稍微进阶的笔记(一)
文章目錄
- 1. EDA工具對代碼的處理與輸出
- 1.1 Compile
- 1.2 Simulation
- 1.3 Synthesis
 
- 2. System Verilog Coding Guide
- 2.1 狀態機【Design】
- 2.2 Behavorial Verilog再到Always模塊【Design】
- 2.3 便捷寫法【Design】
- 2.4 變量運算【Both DV】
- 2.5 Verilog Stratified Event Queue【Verification】
- 2.6 Fork methods【Verification】
- 2.7 Assertion【Verification】
- 2.8 import package & `include【Both DV】
- 2.9 Random Testing【Verification】
- 2.10 Fuction & Task【Verification】
- 2.11 Coding for Synthesis【Design】
 
- 3. Extension
- 3.1 Automatic buildup/Test Script Cases
- 3.2 Code Coverage
- 3.3 TBD
 
接觸硬件描述語言(HDL)也有幾個年頭了,由于之后research會偏向Architecture,做偏軟件的活,算是走入一個新的階段,因此想寫一篇關于SV的筆記進行總結復習。選擇SV的原因在于它目前是業界主流。SV是Verilog的繼承擴展版本,類似于Cpp和C的關系,擴展內容可以分為Declaration Enhancement(多了變量類型),和Programming Enhancement(一些寫法的shortcut,硬件行為描述的支持,運算符,directive等等),具體參見下圖,Coding會在Part 2詳細說明。總之sv對design和verification的支持都很顯著,本文會挑個人覺得比較有用的點去記,所以這不是一個入門的指導,我會跳過蠻多基礎的東西,Bear in mind!!!。
 
1. EDA工具對代碼的處理與輸出
在講Coding前,還是稍微skim一下它的工作步驟,只想看sv的Coding Guide的話直接跳到Part 2,這里不細說底層的運行,因為這與不同EDA工具和FAB的lib有關系 (例如說Synopsy和Cadence的綜合程序算法就不大一樣),目前還沒有能力和興趣去探究,主要還是說一些已經standardized的東西。我們使用HDL的最終目的在于生成可靠可知的IC layout,我們將layout及其設計步驟抽象為代碼,人寫完代碼后借由一系列Computer Aided Design(CAD)工具(在EE領域我們特指它為EDA)再將代碼轉變為layout的輸出文件。因為我們需要其可靠可知,所以設計流程中的一些中間產物也是很重要的。因此這里將對HDL代碼的處理分步為:Compile, Simulation和Synthesis。對應著不同類的EDA工具對應的功能目的和輸出結果。
PS: HDL可服務于不同類型的DIC實現:Full Custom, Semi-Custom和Programmable。這更分化了不同的EDA功用,但是大道至簡,殊途同歸,后文主要還是講general的部分和一些經驗tips方便回憶
 
1.1 Compile
第一步是編譯,實際上對于這一名詞不同工具我們也能看到不同的結果。比如說對于vivado或者dc shell這類需要后續制作netlist等的軟件,當我們輸入filelist進行編譯后除了進行syntax analysis外,還會附帶生成對應的RTL Schematic,也就是說我們可以看到電路的hierarchy,甚至有些情況Compile就直接是Synthesis操作本身。而對于仿真器而言,Compile的含義很多只代指對與各個文件的代碼分析,當要去執行Simulation的時候才會load各個模塊生成Schematic和對應的Hierarchy。
這里仿真軟件舉的例子為Modelsim(vsim這個軟件的組分也是比較多的,包括compiler, linter, simulator, waveform visioner等,支持GUI或者TCL對于各個模塊的調用)。它在compile worklib后點擊View–Schematic依舊是空的,在Run Simulation過后可以在Sim窗口中看到目標top module 的Hierarchy結構還有schematic。而Dc shell和vivado等可以直接set top module并查看這些東西。Anyway,在這里我還是想將對RTL代碼Compile的概念統一描述,就當是Syntax Analyze 和 Linter,進行糾錯并整合信息方便后面的程序進行處理。Compile是可以分辨一些directives(主要應用于Syn),挑出基本的組分。此外,關于Tb層面的compile,默認的timescale為1ns/xx(時間單位/仿真精度)。還有package和#include之于compile的區別,會在Part 2提及,Makefile的特性,我們重復compile不需要update沒有更改的成員。在編寫code的時候利用文本插件(推薦Vim或者VSC等,能裝插件就行)的輔助可以很快通過第一次compile(減少很多syntax層面的typo)。
1.2 Simulation
當然在通過1.1的Compile后我們只是獨自對各個file進行檢查,想要把DUT作為一個整體,還需要各個模塊進行完整的interconnection。因此當我們在Modelsim跑某個testbench時,即便Compile全部PASS,也會出現例如組件名字mismatch,端口連接mismatch或不能識別某個名字等的情況??傊?#xff0c;針對DUT部分,我們需要將它作為電路進行編寫并進行嚴格的連接,這些組件都能在Simulation后的hierarchy中單獨顯示,合理地劃分組件和功能能更方便Debug,SV對于Simulation有非常多額外的支持。
這里標記一些用Simulation Tool的小tips。
- 首先跑Sim后,代碼和各組件建立了映射關系,因此我們可以通過看代碼添加所需的信號,也可以郵件代碼中的一些信號trace driver或reference,這個對于debug一些陌生的代碼很有好處,可以快速地了解信號,寄存器之間的關系,反之亦然-go to source。
- 在寫代碼的時候,除了一些需要用parameters customize Hardware,盡量添加信號位寬的標注可以方便Debug發現忘記添加變量聲明的情況。或者說直接添加以下代碼取消掉SV對default type的設置。
這樣的話如果我們不小心用了未聲明的變量就會直接報錯,而非默認為logic[0:0],在一些現有的代碼中,有人習慣直接用未聲明的變量做interconnection,個人認為這不是個好習慣,盡管說這些變量不具備其他的功能,但標注出來對debug而言會更方便。
-  添加Divider在waveform中可以方便區分不同module的信號,也可以在preference設置代碼名稱的path深度來簡化信號來源的描述。信號的默認名字一般就是main/sub/signal name。我一般習慣設置max path長度為2~3,一般來講記性越差,工程越大,所需要的path長度更大吧。一次性拉了過多的信號的話,可以通過set property改變wave的顏色使重要成員顯著 
 
-  做self check的時候可以多使用 $stop or $fatal(“log”)并fork timeout thread來做debug,step by step的debug是我們所喜歡的方式 
- $strobe $display $monitor 在event-driven simulation下發生在哪個queue呢(時刻),參見Stratified Event Queue,它詳細描述了Simulation的運行規范,這里就記住strobe和monitor能發生在非阻塞賦值后就行。
- $stop $finish stop類似于斷點,可以continue。finish類似于terminate當前thread,在GUI中它通常會問我們finish后要不要exit。Debug還是stop用的比較多
- class 中的變量無法生成add到wave,我們需要將它轉為interface才可以拉出來看到波形。這不太方便,因此要注意信號盡量例化或連接到外面。
- 后仿真需要注意精度的問題,會對結果產生出入。而且對Netlist仿真有時候就很玄學,應該和Lib有關系,個人看法還是圖個樂呵。除此之外盡量也不要依靠內部信號,很容易出現X value,內部信號名很多也會被優化或者處理掉,尤其是synthesize flatten的情況,DUT變成了一層。如果一定要refer一個內部信號,可以在綜合時加入一下代碼,或者一些軟件可以識別RTL代碼中的dont touch,下面一些代碼是dc shell一些代碼是vivado的,使用的時候參見其TCL文檔即可。
1.3 Synthesis
這里只講Code->Netlist這一步也就是,后續Netlist->layout的APR部分不在此列,以DC shell為例子。在Compile并進行完成前仿后,我們將RTL代碼mapping到對應庫的門級網標中,這一步我們實際上無論是Semi-Custom,Full Custom抑或是FPGA,都是必要的,因為從Code到Gate List是比較外層的由抽象到具象的程序,到了具體的implementation再分化。但無論如何,Netlist所依賴的Lib各不相同,對于Full Custom而言,那就不是單純依賴Fab提供的Lib了,而是需要更多人工的設計。以DC shell為例子的話,Synthesis在以下方面可以額外注意下,基礎共通部分我不贅述,隨便看一個完整的腳本代碼再參照資料就可以理解:
2. System Verilog Coding Guide
扯了那么多有的沒的,終于到正題了,也就是Coding的部分,如前文所說,SV是Verilog的擴展,因此這個PART的內容也會夾雜Verilog本身的東西,只挑選我認為很重要或者比較有意思的內容。開頭我先列一點優秀的文字資料,雖說coding是一門實踐的技術,但就我的感覺來看,實踐過后回歸理論,能夠很有效的補全知識漏洞。
- IEEE SV官方指南:IEEE 1800-2017 SV官方鏈接 有些東西網上搜的不太明白可以查一查。
- 2013 SNUG會議文章 “Synthesizing systemverilog busting the myth that systemverilog is only for verification”,關于System Verilog的使用,例子很豐富,講解很詳細:PDF link
- 2000 SNUG會議文章 “Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!”,Verilog的Coding Guideline:PDF link
2.1 狀態機【Design】
從結構上來看,數電狀態機就是時序邏輯+組合邏輯形成的環路,最簡單的狀態機例子就是計數器,counter即是它的狀態,一般來講寄存器保有current state,Comb的輸出決定next state。Moore SM和Mealy SM的區別就在于狀態機輸出的構成,Moore的輸出只由current state決定,比如說計數器的counter,告之當前時刻。而Mealy的輸出還由外部輸入決定,比如說給計數器輸出添加一個mask,這樣就可以選定時間的scale,從輸出性質來講,Moore為同步,Mealy可能為異步,如果外部輸入的是同步信號,那其實輸出的也就同步了。
 
從功能上來看,我認為狀態機就是時序邏輯的一個拓展的實例。在數電中,我們用時鐘和寄存器來進行timing control,規范在不同時間(CLK)電路進行不同的配置和操作。重點在于規范,這就是我們除開FF和latch以外禁止做comb環路的原因,在組合環路中我們很難準確預測什么時刻電路會做什么,因此引入時鐘信號和時序單元來規范一切。而狀態機也是如此,這個環路使我們能夠設計電路什么時刻會干什么,下一時刻又會發生什么,所以我說他是時序功能的延續,是電路時序控制的一個抽象,抽象為Bubble Diagram能更讓人理解功能。Bubble Diagram的規范寫法如下圖所示。
 
從Coding來看,我要說的無非就是兩段/三段式,Enum type,Latch規避以及Case語法變種。
下面是一個case的代碼例子:
當case_exp為000,11x和11z時,x輸出的為133,inside輸出的結果為144,如是casez則結果為143。從這可以看出Sim中這三者的差異,實際就是exp判定xz的差異,但Post Sim的話他們就全部一樣了。
2.2 Behavorial Verilog再到Always模塊【Design】
我們將Verilog代碼區分為Behavioral和Structural,Structural代碼就是模塊元件之間的連接的形式,比如說Netlist就是純純的structural,是比較底層的電路抽象,除此之外的都是Behavioral代碼,我們描述具體行為來生成電路,是一種更高的抽象方法,其中always模塊便是Behavioral的最大組成部分,我們用它來表示時序和綜合電路,包括latch。此外的話多為輔助,比如說用assign表示組合邏輯,是種方便的alternative。下面說一些always模塊編寫的guideline。
always_ff,always_comb和always_latch:之前我們提到code和RTL電路的mapping一致性,這里SV的拓展也是為它而生,我們用不同的always_來map想要的電路類型,倘若我們的代碼行為與硬件mapping不一致,它同理也會報warning,非綜合型的代碼也無法在這個block仿真,但無法說通過這個directive來決定想要綜合出的元件類型,它能做到的也只是輔助。
posedge和negedge:他們并不止是1-0 0-1,在tb中適用更多。
 
不同變量的行為,我們盡可能將對應always分離,這樣可以規避不需要的situation判定,從而減少潛在bug和資源消耗。下面舉一個最簡單的復位打拍電路為例,對應他們的電路圖,我們可以看到Synthesis的差異
可以看到在復位的情況我們沒有定義q2的行為,所以綜合工具會給他自動保持q2<=q2,因此除非我們知道要做這種回路,否則的話還是分離或者是定義其對應的行為。
2.3 便捷寫法【Design】
在原有的印象中,RTL代碼相對于高級編程語言是非常冗余且傳統的,但實際上隨著版本的更新迭代,SV如今也是提供了豐富的便捷的代碼編寫用法。SV支持的Oop涵蓋很廣且通用就不在這個子Part提及了。
- vector和generate:當需要重復例化模塊或者重復一些行為語句時,可以使用向量或者generate語句來實現。若是比較規范的需求,則可以直接用vector來做,若是一些需要不同situation控制的地方,則需要用generate語句。
- 變量拼接(Concatenation):拼接我們經常用,就是利用{},高位到低位,下面就列舉它的一些handy usecases
- Instantiation:例化模塊時,我們需要添加對應模塊的IO和parameters,為了方便有這幾種方法:
 使用插件直接生成對應例化代碼,如VSC Open Command Palette --> system verilog auto instantiate…看具體不同插件的使用方法了,在vsc一般就是在ctrl+shift+p(command palette shortcut)后調用即可。推薦將parameter寫在module內部,因為有時候插件沒那么聰明哈哈,不過這種生成的腳本挺好寫的,自己弄個也不麻煩就是了,還能把變量declaration加上去了。
 
2.4 變量運算【Both DV】
SV提供了豐富的Arithmetic Operator,除了介紹基本的符號和規則外,我同樣也會寫一些handy usecases
4-value logic:包含了XZ后,AND OR等波爾運算會稍微復雜一點點,X就是Unknown,如01沖突會給X。Z是高阻態,懸浮信號,易被外來的下拉或者上拉信號改變,因此總線中很常用。
 
Strength Value:這個一般也就在TB中會用,實際的driving force肯定和器件相關,我們可以給primitive添加這些directives來給定輸出拉高拉低的strength。
 
表1:運算符補充
| exponent | ** | 指數運算符 Range of unsigned = 2 ** width-1 或 $pow(2,width)-1 | 
| modulus | % | 求余運算符 | 
| Shift | <<< >>> | >>> 符號右移only works of operand and dest declared as signed. 等同于加了個sign extension | 
| Equality | === !== | === and !== compare x’s and z’s explicitly not as don’t care. Use in testbench | 
| Bitwise | & | ^ ~ | Applies bit by bit, ~ is unary ^ is xor,按位與或…就是把dest所有bit用operator連接 | 
| set membership | inside() | if (data inside {[0:255}) … if (data inside {3’b1?1}) … if (data inside array) … | 
| streaming | << >> | bitstream operator, 會將目標變量當作比特流來處理,>>正序 <<倒序 a = { << byte { b }}; reverse by byte | 
| Wild equality | ==? !=? | deem xz as wildcards if (data =?= 8’b1xxx_z1xz) begin | 
| assignment | *= += | similar to cpp like a+=1 ---- a = a + 1 | 
看著比較高級的運算符(斜體)通常就只在TB或parameter中用,也不是禁止在DUT用,但和design規范相關。運算符優先級和其他語言比較類似,不在這贅述,但是我個人的習慣就是加括號,增加可讀性,明確優先度。
2.5 Verilog Stratified Event Queue【Verification】
這部分來源于SV官方文檔 IEEE Standard,定義了軟件的Simulation Spec,已知我們的simulation是event driven的,這個Queue就定義了各類event與它們的判定優先級。當我們編寫SV時,或多或少會遇到race的情況,因此了解這個優先級和組成有益于我們編寫和解讀代碼,避免看到仿真結果一臉懵的情況。為了詳細說明,這里再列舉了需要的Simulation Terminology。
- Processes:我們可以在仿真軟件的Sim窗口中查看到這些元素。
 Objects that can be evaluated,包括modules tasks functions primitives,tb的inital和always blocks還有procedural assignments
- Update Event
 LHS assignment,對應變量值的變化更新,可以是net可以是reg
- Evaluation Event
 RHS computation,計算右邊的式子。
- Scheduling an event
 將Event(上述)放入Event Queue
- Simulation Time
 仿真用的時間系,不是說我們現實的時間
- Simulation Cycle
 Complete processing all currently active events。一次simulation time 可以有多個cycle
- Explicit zero delay #0
 將當前sim time后面event強行放入inactive狀態
列舉完了Terminologies,下面我們解釋這個stratified event queue,event分五個Region,隨機執行active region中的events,當一次simulation cycle結束后(當前simulation time的所有active events finish),會依次將其他Region的events加入到active中(例如跳轉到下一時刻,將future events加入active并執行,自然是最后去做的,也就是Region 5)。下面我們對各個region的events進行描述。
- Region 1 Active Events:這個其實就是當前時刻要率先執行的任務,包括內置函數$display,RHS的計算,阻塞賦值,continuous assignment(也就是assign語句),primitive的輸入到輸出等,Region內部的events執行并不存在固定順序,但在同一個block中時,阻塞賦值存在順序,這個我認為也可以延伸到continuous assignment上。
- Region 2 Inactive Events:#0 的阻塞賦值會放在這里。
- Region 3 Nonblocking Events:阻塞賦值中更新LHS。
- Region 4 Monitor Events:$monitor $strobe。
- Region 5 Future Events:接下時刻的events。
事實上,我們比較在意initial和always模塊中的的先后順序,我一般將組合邏輯作為對應順序的非阻塞賦值,有單向依賴關系的情況是好排序的,但是遇到兩個block又雙向依賴的情況,race condition一般就不好判定了。而對于那種trigger events,它在Active的位次處于同一block blocking assignment的后列,當他去monitor trigger的時候內部block的events事實上已經執行完成了,因此阻塞賦值不能夠出現自己self-trigger的情況,但非阻塞可以,因為它update LHS是在Active后。
initial clk = 0;always@(clk) ```#5 clk = ~clk; //不成功!只有在clk完成blocking assignment后,always模塊才會開啟trigger。always@(clk)#5 clk <= ~clk; //成功!trigger先在Active中開啟,在后才會把Non blocking中的賦值放入Active,此時trigger events可以檢測到非阻塞賦值的變化2.6 Fork methods【Verification】
我們使用fork方法來實現TB中的parallel thread。除了方法本身,這里還會介紹一些配合named blocks的usecases
- fork join:該block下的子線程需要全部完成后,fork join才會結束并返回主線程。
- fork join_any:任何一個子線程完成后,主線程繼續往下跑,但這并不會結束其他的子進程的運行,它們依舊會在后臺繼續運行。
- fork join_none:相較于join_any,join_none會直接讓主線程繼續跑無論是否有子進程結束,同樣的子進程會在后臺繼續運行。
- wait fork:針對join_any和join_none兩種情況,我們可以在主進程中添加wait fork語句,方便在后面等待子進程的完成加以控制。
 下面的代碼案例就使用了wait fork 組合 fork join_any。當完成Thread1時它會繼續執行join下的語句,并在wait fork時等待其他thread完成,通常我們會給一個timeout的限制,一般報timeout錯就$stop。
2.7 Assertion【Verification】
在testbench中我們經常會進行self-check,而Assertion則是SV支持的一種簡化的self-check寫法。具體來講它就是Assert一個condition,這是申明Assertion的系統下所需要遵循的一個條件狀態,可以是一個即時或者長期的固有屬性。因此有Immediate Assertion和Concurrent Assertion的區分,當判定的條件是永久性觸發(如posedge clk)時,我們就用Concurrent Assertion。當Assertion只需判定一次(形同if語句)時,我們就用Immediate Assertion。從可讀性和規范上Assertion是有增色的,它統一了self-check的格式。值得詳述的還是Concurrent Assertion,我們可以用Keyword “property”來聲明concurrent的condition。如果我們沒有去指定觸發check property的tick,則默認會用simulation的sys tick進行周期性check,這過于頻繁。因此我們通常會使用clk來作為property的checking tick。此外若是比較復雜的property,我們可以用sequence組合property blocks來進行層次化, sequence->property->directive。下面就放一些例子,其中也涉及到一些不太常用的operator。
operator |-> 是一個implication operator,代指了信號assert的先后關系,這個是LHS先RHS后。
 operator ## 表示前后時間間隔的operator,可以是constant或者range,無|->直接使用的話就是前后的范圍了。
這里property調用了一個變量和兩個sequence。其中set需要拉高3個clk而后第二時間觸發rdy_ack_seq,第三時間出發reg_gnt_seq,ended是將他們同步為結束后執行下一步。相對復雜的時序組合通過不同seq制作property是很好的self check編寫方法。我們也會通過disable iff語句來對self check進行關停與否。
self check中我們有時想要手動控制步驟的執行,一種方法是直接定義一個變量如logic flag,通過其他thread對他賦值來控制check。這里介紹event變量,作用類似,我們可以通過監視他的triggered成員,這個成員是一個狀態量,也就是說不會因為race condition而不被觸發。而倘若我們用類似@()方法,我們在Event Queue中已知trigger方法是在后觸發的,因此race condition下不能檢測到pulse。wait_order 顧名思義,它會等待event的順序觸發。
2.8 import package & `include【Both DV】
`include可以理解為直接將文件的文本copy到對應位置,它的好處是合并編譯,include的內容可以依賴目標模塊的成員,比如說要refer內部信號,include是可以做到的,壞處就在于冗余不方便多文件共享了,他例化的都是各自獨立的存在,public variable不好實現。而package是單獨編譯的,當模塊import package的時候,實際上它是會look up這個文件,所有import的都依賴一個package,我們也能指定import的內容,者方便了多文件共享和通信,缺點就是不能反過來依賴模塊文件,總體來講就是1對1和1對多的區別。package是SV特有的extension,搭配面對對象特性,可以做到方便快捷的多文件泛用。
2.9 Random Testing【Verification】
這里主要講CRV (Constrained Random Verification)。它會調用一些SV的功能對生成的隨機變量加以約束以生成我們想要的數據分布,從而實施更有針對性的測試。
- rand/randc bit[7:0] rand_byte; 這個type有一個built-in method randomize(),可以自己生成隨機數。randc的特點是他生成的隨機數會耗盡后再出現重復,也就是說相鄰的同樣隨機值之間一定包含該變化域的所有可能值,像這里就有255個。
- 利用constraint{} directive,我們可以限制rand bits的隨機生成,constraint塊的分層是{}不同于通常的begin end。
- control the distribution,用dist directive來控制隨機數的分布。通過class的構造我們也能生成隨機數,成員也可以通過randomize()變成對應的隨機數。
2.10 Fuction & Task【Verification】
這里標注了function和task的一些區別,有時候function還是會用在design里的(作為comb logic)。
 
這里再額外說一下task/func automatic,它的主要作用有兩個,一個是迭代函數,另一個是引入ref輸入(類似指針,但只可讀),ref輸入的作用就是可以輸入一些含時的信號,以作monitor。
//Define the factorial function function automatic integer factorial; input[31:0] oper; beginif (oper>=2)factorial = factorial(oper-1)*oper; elsefactorial = 1; end //這里可以看到func的返回可以直接用它的函數名來賦值task automatic uart_tx_case(input[7:0] tx_in, ref clk);@(negedge clk);vif.send_cmd = 1;vif.cmd = tx_in;@(negedge clk);vif.send_cmd = 0; // 1clk trmt, to capture and set txdata;wait(vif.cmd_sent == 1'b1); // serial data done, otherwise uart_tx is not sent$display("tx data, %h, is sent",tx_in);wait_bauds(12); endtask2.11 Coding for Synthesis【Design】
雖然說根據script,EDA工具會自動去優化生成對應的Netlist和Layout,但還是需要了解一些與代碼相關的部分,和設計的trade off息息相關。
3. Extension
眾所周知,Digital Design & Verification的工作流程比較長,不同EDA工具不同的Programming再到Layout等。因此這里再額外塞一些比較有意義的思路或方法,提高設計流程的質量和速度。
3.1 Automatic buildup/Test Script Cases
工業化設計下,使用腳本將作業自動化使我們所希望的,因此這里就列舉一些工具下自動化腳本的案例。Digital部分我用的比較多的還是Shell或者Tcl,這兩者比較方便與Software和OS進行交互。而若是數據處理等更high level的需求,Python C#等會更加好用。不同腳本語言也是可以混合運行的。通常GUI會把使用的CMD interface打印在terminal里,是我們腳本仿照使用的一個比較好的學習窗口。
// ModelSim sim.tcl proc compile_files {args} {#for .do script 's filelistvlog /filespace/demo/Segway/testbench/define.svh... }set fp [open "/filespace/demo/Segway/testbench/define.svh" w] puts $fp "`define TP1" close $fpvlib work vmap work work compile_filesvsim -t 1ns work.Segway_tb_seq -voptargs=+accadd wave -position insertpoint sim:/Segway_tb_seq/Seg_intf/* add wave -position insertpoint sim:/Segway_tb_seq/iPHYS/theta_* add wave -position insertpoint sim:/Segway_tb_seq/iDUT/ptch ...run -all dataset save sim wave1.wlf write format wave wave1.do還有vivado cadence和synopsis工具的case。等之后找到了再更新。
3.2 Code Coverage
根據變量值的變化情況(如SM覆蓋率),仿真工具可以生成Code Coverage的報告來評估仿真是否全面,我們再根據報告反推測試代碼沒有cover的模塊,優化測試質量和覆蓋率,這是Code Coverage的作用??梢酝ㄟ^GUI或者define對應的directive來使能這個功能。
 不同工具雖然界面不同,但基本都遵從Compile Configuration – Enable Code Coverage 和Sim Config 同理,兩者都需要去設置。
 得到的結果粗糙來看如下所示:
具體的話還能在代碼界面中查看各個變量,branch等是否cover到。
3.3 TBD
感覺具體的案例還是單獨開blog寫好點,太臃腫了可讀性還是差了點,吃了經驗的虧呀<_<
總結
以上是生活随笔為你收集整理的【数字设计验证】System Verilog(sv)稍微进阶的笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 清华姚班教授: 「读博,你真的想好了吗?
- 下一篇: 小记--解决方案: rsyslogd c
