Verilog 時序邏輯UDP

2022-05-20 14:33 更新

時序邏輯 UDP 與組合邏輯 UDP 在定義形式和行為功能上均有不同,主要區(qū)別如下:

  • 時序邏輯 UDP 的輸出端必須聲明為 reg 型。
  • 時序邏輯 UDP 可以用 initial 語句初始化。
  • 狀態(tài)表格式也稍有不同:
  • ...    :  <current_state>  :  <next_state>  ;
  • 時序邏輯 UDP 狀態(tài)表每行由 3 部分組成:輸入部分、當前狀態(tài)和輸出狀態(tài),用冒號":"隔開。
  • current_state 就是輸出寄存器的當前值, next_state 就是輸出寄存器的新值。next_state 由輸入和 current_state 共同決定。
  • 狀態(tài)表的輸入項可以是電平,也可以是跳邊沿的形式。

表示時序邏輯的 UDP 主要分為 2 種:電平觸發(fā) UDP 與 邊沿觸發(fā) UDP。

電平觸發(fā) UDP

電平觸發(fā) UDP 的輸出是根據(jù)輸入電平狀態(tài)的改變而改變。

帶有清零端的 D 鎖存器的功能描述為:

  • 清零端為 1 時,輸出端恒為 0 ;
  • 清零端為 0 、使能控制端為 1 時,鎖存器透明,輸出端等于輸入端;
  • 清零端為 0 、使能控制端為 0 時,鎖存器呈保持狀態(tài),輸出端保持不變。

其真值表為(q 表示當前狀態(tài),q+ 表示下一個狀態(tài)):


其實編寫 UDP 的過程,可以理解為換一種格式編寫真值表的過程。

帶有清零端的 D 鎖存器的 UDP 可以描述如下:

primitive d_latch(q, clear, en, d);
   output       q ;
   reg          q ;
   input        d, en, clear ;

   initial
     q = 0 ;

   table
    //clear     en      d       :q      :q+ ;
      1         ?       ?       :?      :0 ;    //clear
      0         0       ?       :?      :- ;    //"-" means stable

      0         1       0       :?      :0 ;    //q = d
      0         1       1       :?      :1 ;
   endtable
endprimitive

當然,也可以在羅列端口信號時就聲明其類型,并且賦初值。

primitive d_latch2(
   output reg   q = 0,
   input        clear, en, d);
   ......
endprimitive

邊沿觸發(fā) UDP

邊沿觸發(fā) UDP 的輸出是根據(jù)輸入跳邊沿和(或)輸入電平狀態(tài)的改變而改變。

直接給出帶有異步復位端(RST)且在時鐘下降沿采集信號的 D 觸發(fā)器的"真值表":


可見此"真值表"中還加入了上下沿的概念,是為了方便編寫 UDP 代碼。

此 D 觸發(fā)器的時序邏輯 UDP 描述如下:

primitive D_TRI(
            output reg  Q = 0,
            input       RST, CP, D);
   table
    //RST       CP      D       :Q      :Q+ ;
      //(1) 清零
      1         ?       ?       :?      :0 ;  //RST=1 時清零
      (??)      ?       ?       :?      :- ;  //忽略 RST 邊沿變化
      //(2) 時鐘下降沿采集
      0         (10)    0       :?      :0 ;  //時鐘下降沿采集信號
      0         (10)    1       :?      :1 ;
      //possible negedge
      0         (1x)    ?       :?      :- ;  //可能是時鐘下降沿時保持
      0         (x0)    ?       :?      :- ;
      //(3) 時鐘上升沿保持
      0         (0?)    ?       :?      :- ;  //時鐘上升沿時保持
      //possible posedge
      0         (x1)    ?       :?      :- ;  //可能是時鐘上升沿時保持
      //(4) 非時鐘沿變化時,即便數(shù)據(jù)有跳變,輸出仍然保持
      0         ?       (??)    :?      :- ;  
   endtable
endprimitive // D_TRI

對此觸發(fā)器進行簡單的仿真,testbench 描述如下。

`timescale 1ns/1ps
module test ;
   reg  D, CP = 0 ;
   reg  RST ;
   wire Q ;
   always #5 CP = ~CP ;
   //data driver
   initial begin
      D = 0 ;
      #12 D = 1 ;
      #10 D = 0 ;
      #14  D = 1 ;
      #3  D = 0 ;
      #18  D = 0 ;
   end
   //reset driver
   initial begin
      RST = 0 ;
      #3        RST = 1 ;
      #2        RST = 0 ;
      #22       RST = 1 ;
      #1        RST = 0 ;
   end
   D_TRI u_d_trigger(Q, RST, CP, D);
   initial begin
      forever begin
         #100;
         //$display("---gyc---%d", $time);
         if ($time >= 1000) begin
            $finish ;
         end
      end
   end
endmodule // test

仿真結果如下。

由圖可知,在 cap1 時刻,Q 端被復位清零;在 cap2 時刻,即時鐘下降沿時,輸出端采集到 D 端輸入 1;在 cap3 時刻,Q 端又被清零。符合設計。


需要注意的是:

狀態(tài)表每行多個輸入部分,最多只能有一個跳邊沿,例如下面狀態(tài)表的表述是錯誤的。

   table
      ......
      (10)     (10)    1       :?      :1 ;
   endtable

電平觸發(fā)的狀態(tài)表輸入項,其優(yōu)先級高于邊沿觸發(fā)的狀態(tài)表輸入項。若兩者在同一時刻出現(xiàn),則輸出端的狀態(tài)由電平觸發(fā)的狀態(tài)表決定。

例如上述 D 觸發(fā)器中,RST 可以看做是電平觸發(fā),CP 可以看做是邊沿觸發(fā)。當 RST 上升沿與 CP 端下降沿同時刻來臨時,輸出端會變?yōu)?nbsp;0 ,如下圖 cap 時刻。當然,實際的時序應該避免時鐘和復位邊沿同時到來。


邊沿觸發(fā) UDP 中,必須為每一個輸入信號都指定邊沿變化時輸出信號的變化情況,否則在該信號的跳變沿處可能會造成輸出端為 X 。

例如缺少 RST 邊沿變化的說明:

    //(??)    ?       ?       :?      :- ; //忽略 RST 邊沿變化

則在 RST 下降沿輸出會變?yōu)?nbsp;x。


再例如缺少時鐘穩(wěn)定、D 端數(shù)據(jù)變化時的說明:

    //(4) 非時鐘沿變化時,即便數(shù)據(jù)有跳變,輸出仍然保持
    //0         ?       (??)    :?      :- ;

則 D 端數(shù)據(jù)變化的邊沿處也會使輸出為 x。


UDP 狀態(tài)表符號縮寫

UDP 狀態(tài)表的電平和跳變沿縮寫符號及說明如下表所示。

縮寫符 含義 說明
? 0, 1, x 只能用于輸入
b 1, 1 只能用于輸入
- 保持原值不變 只能用于輸出
(ab) 信號由 a 變 b 用作輸入端邊沿的指示
r (01) 信號的上升沿
f (10) 信號的下降沿
p (01), (0x) 或 (x1) 可能是信號的上升沿
n (10), (1x) 或 (x0) 可能是信號的下降沿
* (??) 信號任意邊沿的變化

UDP 設計指導

針對數(shù)字設計時是選擇使用 module 還是 primitive,要從設計需求、復雜度等方面進行綜合考慮。下面給出一些指導性的建議。

  • UDP 只能進行功能性建模,不能對電路時序和制造工藝(例如 CMOS,TTL等)進行建模。使用 UDP 的主要目的是以類似于真值表的簡潔形式對數(shù)字設計進行建模,而 module 可以包含電路時序,并指定制造工藝。
  • UDP 只能完成有一個輸出端口的數(shù)字設計。當輸出端口大于一個時,只能用 module。
  • UDP 是使用內存中的查找表實現(xiàn)的,當輸入端口較多時,輸入端口的組合將會呈指數(shù)增長。UDP 輸入端口的數(shù)量也會受到仿真器的限制。因此輸入端口較多時不宜使用 UDP。
  • 選擇使用 UDP 以后,一定要盡可能的用縮寫符完整的描述 UDP 狀態(tài)表。漏掉輸入的組合情況,輸出端可能會出現(xiàn) X 的狀態(tài),造成設計錯誤。

點擊這里下載源碼


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號