天天看點

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                     圖5.1采樣值函數$rose,$fell-基礎

 這些采樣值函數允許先行和/或随後被邊緣觸發。 $rose表示在前一個clk邊緣(之前表示目前clk的前一個clk)的表達式(以$ rose(expr))被采樣為'0'(或'x'或'z'),并且它在這個時鐘邊沿被采樣為'1'。$fell,隻是相反情況發生。前一個值應該取樣為'1'(或'x'或'z')而且目前值為'0'。正如下面的例子所解釋的,人們需要了解電平敏感采樣與邊緣敏感采樣之間的差異(圖5.1)。

但是,為什麼我們稱這些函數為“采樣值”呢?這是因為它們僅在如上所述在推定區域中的表達式的采樣值在兩個連續時鐘邊緣處不同時才被觸發。換句話說,$ rose(abc)并不意味着像Verilog中的“posedge abc”。 $ rose(abc)隻要abc從0變為1,就不會評估為真。$ rose(abc)僅表示abc在目前時鐘邊緣(在預定區域)采樣為'1',并且在緊接的前一個時鐘邊緣處(在預定區域中)未采樣為'1'。

 還要注意,$rose和$ fall都隻能在表達式的最低有效位上才工作。如果在這兩個采樣值函數中使用總線(矢量),您将很快會看到會發生什麼情況。

 5.1 $rose:屬性/序列中的邊緣檢測

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                     圖5.2$rose-基礎

在頂部邏輯/時序圖中的屬性'checkiack'将會(圖5.2)PASS,因為'inter'和'iack'信号都滿足$rose的要求行為(兩個連續clks的值是不同的并且先是'0',然後是'1')。然而,底圖中的邏輯失敗,因為當$rose(intr)符合$rose的要求時,'iack'不符合。 'iack'在兩個時鐘沿之間不會從'0'變為'1'。

重要說明:重申以上幾點。$rose并不意味着posedge,$fell并不意味着negedge。換句話說,一旦檢測到'intr'上的posedge,斷言就不會認為$rose(intr)是真的。 $rose()/ $ fell()行為是通過在兩個連續的時鐘邊緣“采樣”表達式得出的,并且看看這些值是否相反并符合$ rose()或$ fell()。

換而言之,并發斷言​​的基本規定必須在采樣邊緣對所有内容進行采樣。行為基于采樣值。

5.1.1邊緣檢測很有用,因為...

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                    圖5.3“邊緣”檢測和性能暗示的有用性

 這是一個非常重要的例子。它解釋了使用電平敏感采樣值與邊沿敏感值之間的差異。兩者都是正确的使用,除非你知道什麼時候使用。如圖5.3所示,電平敏感評估是邊緣敏感評估的超集。但是,如果實際上您想要進行邊緣敏感性評估,但是您使用對電平敏感的采樣,則會降低仿真性能。

在上述屬性中,如果您隻想檢查一旦邊緣敏感信号intr被觸發, iack就從非活動狀态('0')進入活動狀态'1'。之後,intr的狀态并不重要。如果您的目的是在intr的上升沿一個時鐘之後檢查的iack邊緣,以下是編寫該斷言的更好方法。

property checkiack;
    @ (posedge clk) $rose(intr) |=[$rose(iack);
endproperty
           

 但是如果你決定做以下事情(如圖5.4所示)?現在你遇到了真正的麻煩。如圖5.4所示,由于'intr'是電平敏感的采樣,是以當它被采樣為高電平時,它将查找邊沿敏感的'iack'。但由于'intr'對電平敏感,并且在下一個時鐘高時,它将啟動一個新線程并檢查每個時鐘的$rose(iack)。由于iack在第二個線程中沒有從'0'到'1',是以屬性失敗。很有可能你不希望看到這種失敗。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                             圖5.4$rose-精細點

 簡而言之,就像這些功能看起來那麼簡單,你必須小心使用它們,并且要記住性能影響(圖5.5)。

 5.1.2 $fell:屬性/序列中的邊緣檢測

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                        圖5.5$fell-基礎

 5.1.3在程式塊中的$rose,$fell

 $ rose和$ fell不僅在并發斷言中非常有用,而且在順序性程式塊中也非常有用。它們的工作方式與并發斷言完全相同。

因為每個斷言都需要一個時鐘事件(即采樣邊沿),是以當您在程式代碼中使用并發斷言,但是沒有與它們關聯顯式的時鐘事件時,那麼仿真器将在并發斷言之前的代碼中查找時鐘事件。

在圖5.6中,$(posedge clk)是前面的時鐘事件,作為$ rose(iStreamDone)的采樣邊緣(例子在圖的頂部)。

注意在連續指派語句中使用$ rose和$ fell。由于連續指派不能具有邊緣行為,是以必須明确為$rose()和/或$fell()指定時鐘事件。這是适用于其他采樣值函數的相同規則。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                         圖5.6$rose和$fell在程式塊和連續指派

 5.2$stable

 顧名思義,$stable()會尋找它的表達式在兩個時鐘邊(即兩個采樣邊)之間是穩定的。它評估目前時鐘邊沿的表達式并将其與前一個時鐘邊沿處的采樣值進行比較。如果兩個值相同,則檢查通過(圖5.7)。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                                 圖5.7$ stable-基礎

 請注意在連續指派語句中使用$ stable。由于連續指派不能具有邊緣行為,是以必須使用$ stable明确嵌入時鐘事件。這與适用于其他采樣值函數的規則相同。

但是,如果您想檢查信号是否穩定超過1個時鐘,該怎麼辦?閱讀...... $ past()将解決這個問題。

 5.2.1程式塊中的$stable

 正如在$rose()和$fell()中一樣,$stable也可以嵌入到過程代碼中,并且與屬性或序列中的工作方式相同。如上例所示,$ stable在目前和前一個邊沿(本例中為posedge clk)中對表達式(本例中為'a'和'b')的值進行采樣,以檢視表達式的值是否不變。在時間15,'b'已經穩定,在25'a'時間已經穩定,等等(圖5.8)。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                     圖5.8程式塊中的$stable

 5.3$past

 $ past()是一個有趣的函數。它可以讓你追溯過去任意時鐘,然後您可以檢查'表達式1'是否具有特定的值,在以前的時鐘數(嚴格地說是在時間點之前)。請注意,時鐘的數量是可選的。如果你沒有指定它,預設情況下是在過去的一個時鐘查找'表達式1'。

需要注意的另一個警告是當你在仿真的初始時間刻度中調用$past時,沒有足夠的時鐘去'過去'。例如,您可以指定'a |  - > $ past(b)',并且在時間'0'前提'a'為真。過去并沒有時鐘。在這種情況下,斷言将使用'b'的'初始'值。 'b'的初始值是多少?它不是'初始'塊中的那個,它是變量'b'被聲明的值(如'logic b = 1'b1;')。在我們的例子中,如果'b'在其聲明中未被初始化,斷言将失敗。如果聲明初始值為1'b1,則斷言将通過。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                    圖5.9$ past-basics

你也可以通過表達式2'gate'這個檢查。圖5.9中的例子顯示$past如何工作。在這個例子中我們使用了一個門控表達式。它不是圖5.10中提到的要求,但它很可能在您的應用程式中需要。如果沒有指定表達式2,則不會假定時鐘門控。

如果您了解使用門控表達式的$past,那麼無需使用它就可以直接了解。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                         圖5.10$past門控表達式

 圖5.10斷言以下屬性

assert property (@ posedge clk) done |-[ lV(mySig,2,enb,lastVal)
$display(….);
           

 屬性LV模拟以下内容

property lV(Sig, numClocks, enb, lastV);
(lastV == $past(Sig, numClocks, enb));
endproperty
           

 該屬性表示在numClocks個過去檢視Sig,并檢視它是否具有值'lastV',并且僅當‘enb’為高時在開始檢查。讓我再次強調,當'先行詞'為真時,檢查門控表達式。當你開始檢查時,選通表達式必須為真。許多人似乎錯過了這一點。讓我們看看将解釋這個概念的仿真日志。當我們斷言/覆寫屬性'lV'(代表最後一個值)以便于參考仿真日志(圖5.11)時,前一頁的例子在這裡重複,設定lastV ='ha。

讓我們檢查仿真日志仔細看看$past是如何工作的。在時間30,第一次完成= 1,這意味着該屬性的先行詞是真實的,這意味着該屬性被執行。 lV的形式參數被assert語句的實際參數取代。

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                     圖5.11$ past-gating表達式仿真日志

 是以,在時間30,屬性首先檢查門控信号('enb')是否為真實。由于确實如此,該屬性現在評估過去mySig 在2個時鐘的值。看似它确實是h'a(在仿真日志中的時間10)。該屬性通過。

在時間50,done= 1和enb = 1,但在過去2個時鐘(在時間30)mySig不等于h'a,屬性失敗。

在時間80,done = 1,但門控信号'enb'是'0'。這裡需要注意的一點是,即使mySig的值在過去兩個時鐘的确是h'a(時刻60),屬性也會失敗。這是因為目前時鐘的門控表達式enb = 0(當先前'完成'是真的),這時$past()不會自我評估。換句話說,$ past()在以前沒有查找mySig 2時鐘,而是傳回了先前評估的值h'5。該屬性将h'5的值與h'a的期望值進行比較并且失敗。

在沒有門控信号的情況下,隻要前提是真實的,該屬性将始終進行評估,并在過去查找所需的表達式值N個時鐘。

還要注意在$display語句中使用$ past,這是一個過程語句。這是一個出色的調試功能。您可以随時顯示過去發生了什麼以調試目前的設計狀态。

 5.3.1應用程式:$ past()

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                                圖5.12$past的應用

 圖5.12是自我解釋。請注意,$ past在圖形頂部的應用程式中作為結果使用,并在底部應用程式中用作前項。

 5.3.2$past拯救$fell!

第5章 采樣值函數$rose,$fell,$past 5.1 $rose:屬性/序列中的邊緣檢測  5.2$stable  5.3$past

                                             圖5.13 $past拯救$fell

 圖5.13顯示$rose/$fell與$past之間的差異。回想一下,$fell(或者$rose)隻會對我們正在評估的表達/信号的LSB進行采樣。相反,$past評估整個表達式。是以,如果你想檢查(例如)整個'總線'的值,你必須使用$past。如圖所示,如果實際上您想要檢查整個總線在過去幾個時鐘的評估值,那麼$fell将給出對32位總線“dBus”的錯誤結果。該圖解釋了如何使用$ past來解決$fell無法解決的問題。

繼續閱讀