• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > Verilog HDL簡明教程(2)

    Verilog HDL簡明教程(2)

    作者: 時間:2017-10-11 來源:網絡 收藏

    第二章 指南

    模塊

    模塊是 的基本描述單位,用于描述某個設計的功能或結構及其與其他模塊通信的外部端口。一個設計的結構可使用開關級原語、門級原語和用戶定義的原語方式描述; 設計的數據流行為使用連續賦值語句進行描述; 時序行為使用過程結構描述。一個模塊可以在另一個模塊中使用。

    本文引用地址:http://www.czjhyjcfj.com/article/201710/365605.htm

    一個模塊的基本語法如下:
    module module_name (port_list);
    DeclaraTIons:
    reg, wire, parameter,
    input, output, inout,
    funcTIon, task, . . .
    Statements:
    IniTIal statement
    Always statement
    Module instanTIation
    Gate instantiation
    UDP instantiation
    Continuous assignment
    endmodule
    說明部分用于定義不同的項,例如模塊描述中使用的寄存器和參數。語句定義設計的功能和結構。說明部分和語句可以散布在模塊中的任何地方;但是變量、寄存器、線網和參數等的說明部分必須在使用前出現。為了使模塊描述清晰和具有良好的可讀性, 最好將所有的說明部分放在語句前。本書中的所有實例都遵守這一規范。
    以下為建模一個半加器電路的模塊的簡單實例。
    module HalfAdder (A, B, Sum, Carry);
    input A, B;
    output Sum, Carry;
    assign #2 Sum = A ^ B;
    assign #5 Carry = A B;
    endmodule
    模塊的名字是HalfAdder。 模塊有4個端口: 兩個輸入端口A和B,兩個輸出端口Sum和Carry。由于沒有定義端口的位數, 所有端口大小都為1位;同時, 由于沒有各端口的數據類型說明, 這四個端口都是線網數據類型。
    模塊包含兩條描述半加器數據流行為的連續賦值語句。從這種意義上講,這些語句在模塊中出現的順序無關緊要,這些語句是并發的。每條語句的執行順序依賴于發生在變量A和B上的事件。
    在模塊中,可用下述方式描述一個設計:
    1) 數據流方式;
    2) 行為方式;
    3) 結構方式;
    4) 上述描述方式的混合。
    下面幾節通過實例講述這些設計描述方式。不過有必要首先對 的時延作簡要介紹。

    時延

    模型中的所有時延都根據時間單位定義。 下面是帶時延的連續賦值語句實例。
    assign #2 Sum = A ^ B;
    #2指2個時間單位。
    使用編譯指令將時間單位與物理時間相關聯。這樣的編譯器指令需在模塊描述前定義,如下所示:
    ` timescale 1ns /100ps
    此語句說明時延時間單位為1ns并且時間精度為100ps (時間精度是指所有的時延必須被限定在0.1ns內)。 如果此編譯器指令所在的模塊包含上面的連續賦值語句, #2 代表2ns。
    如果沒有這樣的編譯器指令, Verilog HDL 模擬器會指定一個缺省時間單位。IEEE Verilog HDL 標準中沒有規定缺省時間單位。

    數據流描述方式
    用數據流描述方式對一個設計建模的最基本的機制就是使用連續賦值語句。在連續賦值語句中,某個值被指派給線網變量。 連續賦值語句的語法為:
    assign [delay] LHS_net = RHS_ expression;
    右邊表達式使用的操作數無論何時發生變化, 右邊表達式都重新計算, 并且在指定的時延后變化值被賦予左邊表達式的線網變量。時延定義了右邊表達式操作數變化與賦值給左邊表達式之間的持續時間。如果沒有定義時延值, 缺省時延為0。
    下面的例子顯示了使用數據流描述方式對2-4解碼器電路的建模的實例模型。
    `timescale 1ns/ 1ns
    module Decoder2x4 (A, B, EN, Z);
    input A, B, EN;
    output [ 0 :3] Z;
    wire Abar, Bbar;
    assign #1 Abar = ~ A; / / 語句 1。
    assign #1 Bbar = ~ B; / / 語句 2。
    assign #2 Z[0] = ~ (Abar Bbar EN) ; / / 語句 3。
    assign #2 Z[1] = ~ (Abar B EN) ; / / 語句 4。
    assign #2 Z[2] = ~ (A Bbar EN) ; / / 語句 5。
    assign #2 Z[3] = ~ (A B EN) ; / / 語句 6。
    endmodule
    以反引號“ ` ”開始的第一條語句是編譯器指令, 編譯器指令`timescale 將模塊中所有時延的單位設置為1 ns,時間精度為1 ns。例如,在連續賦值語句中時延值#1和#2分別對應時延1 ns和2 ns。
    模塊Decoder2x4有3個輸入端口和1個4位輸出端口。線網類型說明了兩個連線型變量Abar和Bbar (連線類型是線網類型的一種)。此外,模塊包含6個連續賦值語句。
    當EN在第5 ns變化時,語句3、4、5和6執行。這是因為EN是這些連續賦值語句中右邊表達式的操作數。Z[0]在第7 ns時被賦予新值0。當A在第15 ns變化時, 語句1、5和6執行。執行語句5和6不影響Z[0]和Z[1]的取值。執行語句5導致Z[2]值在第17 ns變為0。執行語句1導致Abar在第16 ns被重新賦值。由于Abar的改變,反過來又導致Z[0]值在第18 ns變為1。
    請注意連續賦值語句是如何對電路的數據流行為建模的;這種建模方式是隱式而非顯式的建模方式。此外,連續賦值語句是并發執行的,也就是說各語句的執行順序與其在描述中出現的順序無關。

    行為描述方式

    設計的行為功能使用下述過程語句結構描述:
    1) initial語句:此語句只執行一次。
    2) always語句:此語句總是循環執行, 或者說此語句重復執行。
    只有寄存器類型數據能夠在這兩種語句中被賦值。寄存器類型數據在被賦新值前保持原有值不變。所有的初始化語句和always語句在0時刻并發執行。
    下例為always語句對1位全加器電路建模的示例。
    module FA_Seq (A, B, Cin, Sum, Cout);
    input A, B, Cin;
    output Sum, Cout;
    reg Sum, Cout;
    reg T1, T2, T3;
    always
    @ ( A or B or Cin ) begin
    Sum = (A ^ B) ^ Cin;
    T1 = A Cin;
    T2 = B Cin;
    T3 = A B;
    Cout = (T1| T2) | T3;
    end
    endmodule
    模塊FA_Seq 有三個輸入和兩個輸出。由于Sum、Cout、T1、T2和T3在always 語句中被賦值,它們被說明為 reg 類型(reg 是寄存器數據類型的一種)。always 語句中有一個與事件控制(緊跟在字符@ 后面的表達式)。相關聯的順序過程(begin-end對)。這意味著只要A、B或Cin 上發生事件,即A、B或Cin之一的值發生變化,順序過程就執行。在順序過程中的語句順序執行,并且在順序過程執行結束后被掛起。順序過程執行完成后,always 語句再次等待A、B或Cin上發生的事件。
    在順序過程中出現的語句是過程賦值模塊化的實例。模塊化過程賦值在下一條語句執行前完成執行。過程賦值可以有一個可選的時延。
    時延可以細分為兩種類型:
    1) 語句間時延: 這是時延語句執行的時延。
    2) 語句內時延: 這是右邊表達式數值計算與左邊表達式賦值間的時延。
    下面是語句間時延的示例:
    Sum = (A ^ B) ^ Cin;
    #4 T1 = A Cin;
    在第二條語句中的時延規定賦值延遲4個時間單位執行。就是說,在第一條語句執行后等待4個時間單位,然后執行第二條語句。下面是語句內時延的示例。
    Sum = #3 (A^ B) ^ Cin;
    這個賦值中的時延意味著首先計算右邊表達式的值, 等待3個時間單位,然后賦值給Sum。
    如果在過程賦值中未定義時延,缺省值為0時延,也就是說,賦值立即發生。這種形式以及在always 語句中指定語句的其他形式將在第8章中詳細討論。
    下面是initial語句的示例:
    `timescale 1ns / 1ns
    module Test (Pop, Pid);
    output Pop, Pid;
    reg Pop, Pid;
    initial
    begin
    Pop = 0; // 語句 1。
    Pid = 0; // 語句 2。
    Pop = #5 1; // 語句 3。
    Pid = #3 1; // 語句 4。
    Pop = #6 0; // 語句 5。
    Pid = #2 0; // 語句 6。
    end
    endmodule
    initial語句包含一個順序過程。這一順序過程在0 ns時開始執行,并且在順序過程中所有語句全部執行完畢后, initial語句永遠掛起。這一順序過程包含帶有定義語句內時延的分組過程賦值的實例。語句1和2在0 ns時執行。第三條語句也在0時刻執行,導致Pop 在第5 ns時被賦值。語句4在第5 ns執行,并且Pid 在第8 ns被賦值。同樣,Pop在14 ns被賦值0,Pid在第16 ns被賦值0。第6條語句執行后,initial語句永遠被掛起。

    結構化描述形式

    在Verilog HDL中可使用如下方式描述結構:
    1) 內置門原語(在門級);
    2) 開關級原語(在晶體管級);
    3) 用戶定義的原語(在門級);
    4) 模塊實例 (創建層次結構)。
    通過使用線網來相互連接。下面的結構描述形式使用內置門原語描述的全加器電路實例。
    module FA_Str (A, B, Cin, Sum, Cout);
    input A, B, Cin;
    output Sum, Cout;
    wire S1, T1, T2, T3;
    xor
    X1 (S1, A, B),
    X2 (Sum, S1, Cin);
    and
    A1 (T3, A, B),
    A2 (T2, B, Cin),
    A3 (T1, A, Cin),
    or
    O1 (Cout, T1, T2, T3);
    endmodule
    在這一實例中,模塊包含門的實例語句,也就是說包含內置門xor、and和or 的實例語句。門實例由線網類型變量S1、T1、T2和T3互連。由于沒有指定的順序, 門實例語句可以以任何順序出現;圖中顯示了純結構;xor、and和or是內置門原語;X1、X2、A1等是實例名稱。緊跟在每個門后的信號列表是它的互連;列表中的第一個是門輸出,余下的是輸入。例如,S1與xor 門實例X1的輸出連接,而A和B與實例X1的輸入連接。
    4位全加器可以使用4個1位全加器模塊描述。下面是4位全加器的結構描述形式。
    module FourBitFA (FA, FB, FCin, FSum, FCout );
    parameter SIZE = 4;
    input [SIZE:1] FA, FB;
    output [SIZE:1] FSum
    input FCin;
    input FCout;
    wire [ 1: SIZE-1] FTemp;
    FA_Str
    FA1( .A (FA[1]), .B(FB[1]), .Cin(FCin),
    .Sum(FSum[1]), .Cout(FTemp[2])),
    FA2( .A (FA[2]), .B(FB[2]), .Cin(FTemp[1]),
    .Sum(FSum[2]), .Cout(FTemp[2])),
    FA3(FA[3], FB[3], FTemp[2], FSum[3], FTemp[3],
    FA4(FA[4], FB[4], FTemp[3], FSum[4], FCout);
    endmodule
    在這一實例中,模塊實例用于建模4位全加器。在模塊實例語句中,端口可以與名稱或位置關聯。前兩個實例FA1和FA2使用命名關聯方式,也就是說,端口的名稱和它連接的線網被顯式描述(每一個的形式都為“.port_name (net_name))。最后兩個實例語句,實例FA3和FA4使用位置關聯方式將端口與線網關聯。這里關聯的順序很重要,例如,在實例FA4中,第一個FA[4]與FA_Str 的端口A連接,第二個FB[4]與FA_Str 的端口B連接,余下的由此類推。

    混合設計描述方式

    在模塊中,結構的和行為的結構可以自由混合。也就是說,模塊描述中可以包含實例化的門、模塊實例化語句、連續賦值語句以及always語句和initial語句的混合。它們之間可以相互包含。來自always語句和initial語句(切記只有寄存器類型數據可以在這兩種語句中賦值)的值能夠驅動門或開關,而來自于門或連續賦值語句(只能驅動線網)的值能夠反過來用于觸發always語句和initial語句。
    下面是混合設計方式的1位全加器實例。
    module FA_Mix (A, B, Cin, Sum, Cout);
    input A,B, Cin;
    output Sum, Cout;
    reg Cout;
    reg T1, T2, T3;
    wire S1;
    xor X1(S1, A, B); // 門實例語句。
    always
    @ ( A or B or Cin ) begin // always 語句。
    T1 = A Cin;
    T2 = B Cin;
    T3 = A B;
    Cout = (T1| T2) | T3;
    end
    assign Sum = S1 ^ Cin; // 連續賦值語句。
    endmodule
    只要A或B上有事件發生,門實例語句即被執行。只要A、B或Cin上有事件發生,就執行always 語句,并且只要S1或Cin上有事件發生,就執行連續賦值語句。

    設計模擬

    Verilog HDL不僅提供描述設計的能力,而且提供對激勵、控制、存儲響應和設計驗證的建模能力。激勵和控制可用初始化語句產生。驗證運行過程中的響應可以作為“變化時保存”或作為選通的數據存儲。最后,設計驗證可以通過在初始化語句中寫入相應的語句自動與期望的響應值比較完成。
    下面是測試模塊Top的例子。該例子測試2.3節中講到的FA_Seq模塊。
    ‘timescale 1ns/1ns
    module Top; // 一個模塊可以有一個空的端口列表。
    reg PA, PB, PCi;
    wire PCo, PSum;
    // 正在測試的實例化模塊:
    FA_Seq F1(PA, PB, PCi, PSum, PCo); // 定位。
    initial
    begin: ONLY_ONCE
    reg [3:0] Pal;
    //需要4位, Pal才能取值8。
    for (Pal = 0; Pal 8; Pal = Pal + 1)
    begin
    {PA, PB, PCi} = Pal;
    #5 $display (“PA, PB, PCi = %b%b%b”, PA, PB, PCi,
    “ : : : PCo, PSum=%b%b”, PCo, PSum);
    end
    end
    endmodule
    在測試模塊描述中使用位置關聯方式將模塊實例語句中的信號與模塊中的端口相連接。也就是說,PA連接到模塊FA_Seq的端口A,PB連接到模塊FA_Seq的端口B,依此類推。注意初始化語句中使用了一個for循環語句,在PA、PB和PCi上產生波形。for 循環中的第一條賦值語句用于表示合并的目標。自右向左,右端各相應的位賦給左端的參數。初始化語句還包含有一個預先定義好的系統任務。系統任務$display將輸入以特定的格式打印輸出。
    系統任務$display調用中的時延控制規定$display任務在5個時間單位后執行。這5個時間單位基本上代表了邏輯處理時間。即是輸入向量的加載至觀察到模塊在測試條件下輸出之間的延遲時間。
    這一模型中還有另外一個細微差別。Pal在初始化語句內被局部定義。為完成這一功能,初始化語句中的順序過程(begin-end)必須標記。在這種情況下, ONLY_ONCE是順序過程標記。如果在順序過程內沒有局部聲明的變量,就不需要該標記。下面是測試模塊產生的輸出。
    PA, PB, PCi = 000 ::: PCo, PSum = 00
    PA, PB, PCi = 001 ::: PCo, PSum = 01
    PA, PB, PCi = 010 ::: PCo, PSum = 01
    PA, PB, PCi = 011 ::: PCo, PSum = 10
    PA, PB, PCi = 100 ::: PCo, PSum = 01
    PA, PB, PCi = 101 ::: PCo, PSum = 10
    PA, PB, PCi = 110 ::: PCo, PSum = 10
    PA, PB, PCi = 111 ::: PCo, PSum = 11
    驗證與非門交叉連接構成的RS_FF模塊的測試模塊如下例所示。
    `timescale 10ns/1ns
    module RS_FF (Q, Qbar, R, S);
    output Q, Qbar;
    input R, S;
    nand #1 (Q, R, Qbar);
    nand #1 (Qbar, S, Q,);
    //在門實例語句中,實例名稱是可選的。
    endmodule
    module Test;
    reg TS, TR;
    wire TQ, TQb;
    //測試模塊的實例語句:
    RS_FF NSTA (.Q(TQ), .S(TS), .R(TR), .Qbar(TQb));
    //采用端口名相關聯的連接方式。
    // 加載激勵:
    initial
    begin:
    TR = 0;
    TS = 0;
    #5 TS = 1;
    #5 TS = 0;
    TR = 1;
    #5 TS = 1;
    TR = 0;
    #5 TS = 0;
    #5 TR = 1;
    end
    //輸出顯示:
    initial
    $monitor (At time %t , , $time,
    TR = %b, TS=%b, TQ=%b, TQb= %b, TR, TS, TQ, TQb);
    endmodule
    RS_FF模塊描述了設計的結構。在門實例語句中使用門時延;例如,第一個實例語句中的門時延為1個時間單位。該門時延意味著如果R或Qbar假定在T時刻變化,Q將在T+1時刻獲得計算結果值。
    模塊Test是一個測試模塊。測試模塊中的RS_FF用實例語句說明其端口用端口名關聯方式連接。在這一模塊中有兩條初始化語句。第一個初始化語句只簡單地產生TS和TR上的波形。這一初始化語句包含帶有語句間時延的程序塊過程賦值語句。
    第二條初始化語句調用系統任務$monitor。這一系統任務調用的功能是只要參數表中指定的變量值發生變化就打印指定的字符串。下面是測試模塊產生的輸出。請注意`timescale指令在時延上的影響。
    At time 0, TR=0, TS=0, TQ=x, TQb= x
    At time 10, TR=0, TS=0, TQ=1, TQb= 1
    At time 50, TR=0, TS=1, TQ=1, TQb= 1
    At time 60, TR=0, TS=1, TQ=1, TQb= 0
    At time 100, TR=1, TS=0, TQ=1, TQb= 0
    At time 110, TR=1, TS=0, TQ=1, TQb= 1
    At time 120, TR=1, TS=0, TQ=0, TQb= 1
    At time 150, TR=0, TS=1, TQ=0, TQb= 1
    At time 160, TR=0, TS=1, TQ=1, TQb= 1
    At time 170, TR=0, TS=1, TQ=1, TQb= 0
    At time 200, TR=0, TS=0, TQ=1, TQb= 0
    At time 210, TR=0, TS=0, TQ=1, TQb= 1
    At time 250, TR=1, TS=0, TQ=1, TQb= 1
    At time 260, TR=1, TS=0, TQ=0, TQb= 1



    關鍵詞: Verilog HDL

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 沙洋县| 张北县| 肥乡县| 铜山县| 青铜峡市| 石家庄市| 兴和县| 芦溪县| 玛沁县| 寻乌县| 乐业县| 东乌珠穆沁旗| 黔江区| 穆棱市| 邹城市| 汾西县| 长子县| 会泽县| 外汇| 醴陵市| 平安县| 磐安县| 巴楚县| 太仆寺旗| 大同县| 安陆市| 浑源县| 保定市| 惠州市| 南丰县| 阳城县| 抚远县| 焉耆| 元阳县| 武乡县| 桦甸市| 招远市| 衡东县| 灵宝市| 义乌市| 三明市|