MP
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 2. Verilog 基礎語法 [參考網址:Verilog 中文詳細教程](https://www.runoob.com/w3cnote/verilog-tutorial.html) ###### tags: `verilog` `IC 設計` --- [toc] --- ### :pushpin: 格式 Verilog 是區分大小寫的。 格式自由,可以在一行內編寫,也可跨多行編寫。 每個語句必須以分號為結束符。空白符(換行、製表、空格)都沒有實際的意義,在編譯階段可忽略。例如下面兩中編程方式都是等效的。 Example: ```verilog= wire [1:0] results ; assign results = (a == 1'b0) ? 2'b01 : (b==1'b0) ? 2'b10 : 2'b11 ; ``` ### :pushpin: 註釋 Verilog 中有 2 種註釋方式: 用 // 進行單行註釋: ```verilog= reg [3:0] counter ; // A definition of counter register ``` 用 /* 與 */ 進行跨行註釋: ```verilog= wire [11:0] addr ; /* Next are notes with multiple lines. Codes here cannot be compiled. */ assign addr = 12'b0 ; ``` ### :pushpin: 標識符與關鍵字 - 標識符(identifier)可以是任意一組字母、數字、$ 符號和 _(下劃線)符號的合,但標識符的第一個字符必須是字母或者下劃線,**不能以數字或者美元符開始**。 另外,標識符是區分大小寫的。 - 關鍵字是 Verilog 中預留的用於定義語言結構的特殊標識符。 Verilog 中關鍵字全部為小寫。 # 2.2 數值種類 Verilog HDL 有下列四種基本的值來表示硬件電路中的電平邏輯: 0:邏輯 0 或 "假" 1:邏輯 1 或 "真" x 或 X:未知 z 或 Z:高阻 - x 意味著信號數值的不確定,即在實際電路里,信號可能為 1,也可能為 0。 - z 意味著信號處於高阻狀態,常見於信號(input, reg)沒有驅動時的邏輯結果。例如一個 pad 的 input 呈現高阻狀態時,其邏輯值和上下拉的狀態有關係。上拉則邏輯值為 1,下拉則為 0 。 ### :pushpin: 整數數值表示方法 數字宣告時,合法的基數格式有4種(數值可指明位寬,也可不指明位寬),包括: - 十進制('d 或 'D) - 十六進制('h 或 'H) - 二進制('b 或 'B) - 八進制('o 或 'O) **指明位寬:** ```verilog= 4'b1011 // 4bit 数值 32'h3022_c0de // 32bit 的数值 ``` 其中,下劃線 _ 是為了增強代碼的可讀性。 **不指明位寬:** 一般直接寫數字時,**默認為十進製表示**,例如下面的 3 種寫法是等效的: ```verilog= counter = 'd100 ; //一般会根据编译器自动分频位宽,常见的为32bit counter = 100 ; counter = 32'h64 ; ``` **負數表示** 通常在表示位寬的數字前面加一個減號來表示負數。例如: ```verilog= -6'd15 -15 ``` -15 在 5 位二進制中的形式為 5'b10001, 在 6 位二進制中的形式為 6'b11_0001。 **需要注意的是,減號放在基數和數字之間是非法的**,例如下面的表示方法是錯誤的: ```verilog= 4'd-2 //非法說明 ``` **實數表示方法** 實數表示方法主要有兩種方式: - 十進制: ```verilog 30.123 6.0 3.0 0.001 ``` - 科學計數法: ```verilog 1.2e4 //大小為12000 1_0001e4 //大小為100010000 1E-3 //大小為0.001 ``` **字符串表示方法** 字符串是由雙引號包起來的字符隊列。字符串不能多行書寫,即字符串中不能包含回車符。 Verilog 將字符串當做一系列的單字節 ASCII 字符隊列。例如,為存儲字符串 "www.runoob.com", 需要 14*8bit 的存儲單元。例如: ```verilog= reg [0: 14*8-1] str ; initial begin str = "www.runoob.com"; end ``` # 2.3 Verilog 數據類型 Verilog 最常用的 2 種數據類型就是**線網(wire)與寄存器(reg)**,其餘類型可以理解為這兩種數據類型的擴展或輔助。 ### :pushpin: 線網(wire) wire 類型表示硬件單元之間的物理連線,由其連接的器件輸出端連續驅動。如果沒有驅動元件連接到 wire 型變量,缺省值一般為 "Z"。舉例如下: ```verilog= wire interrupt ; wire flag1, flag2 ; wire gnd = 1'b0 ; ``` 線網型還有其他數據類型,包括 wand,wor,wri,triand,trior,trireg 等。這些數據類型用的頻率不是很高,這裡不做介紹。 ### :pushpin: 寄存器(reg) 寄存器(reg)用來表示存儲單元,它會保持數據原有的值,直到被改寫。宣告舉例如下: ```verilog= reg clk_temp; reg flag1, flag2 ; ``` 例如在 always 塊中,寄存器可能被綜合成邊沿觸發器,在組合邏輯中可能被綜合成 wire 型變量。寄存器不需要驅動源,也不一定需要時鐘信號。在仿真時,寄存器的值可在任意時刻通過賦值操作進行改寫。例如: ```verilog= reg rstn ; initial begin rstn = 1'b0 ; #100 ; rstn = 1'b1 ; end ``` ### :pushpin: 向量 當位寬大於 1 時,wire 或 reg 即可聲明為向量的形式。例如: ```verilog= reg [3:0] counter ; //聲明4bit位寬的寄存器counter wire [32-1:0] gpio_data; //聲明32bit位寬的線型變量gpio_data wire [8:2] addr ; //聲明7bit位寬的線型變量addr,位寬範圍為8:2 reg [0:31] data ; //聲明32bit位寬的寄存器變量data, 最高有效位為0 ``` 對於上面的向量,我們可以指定某一位或若干相鄰位,作為其他邏輯使用。例如: ```verilog= wire [9:0] data_low = data[0:9] ; addr_temp[3:2] = addr[8:7] + 1'b1 ; ``` Verilog 支持可變的向量域選擇,例如: ```verilog= reg [31:0] data1 ; reg [7:0] byte1 [3:0]; integer j ; always@* begin for (j=0; j<=3;j=j+1) begin byte1[j] = data1[(j+1)*8-1 : j*8]; //把data1[7:0]…data1[31:24]依次賦值給byte1[0][7:0]…byte[3][7:0] end end ``` **Verillog 還支持指定 bit 位後固定位寬的向量域選擇訪問。** - [bit+: width] : 從起始 bit 位開始遞增,位寬為 width。 - [bit-: width] : 從起始 bit 位開始遞減,位寬為 width。 ```verilog= //下面 2 種賦值是等效的 A = data1[31-: 8] ; A = data1[31:24] ; //下面 2 種賦值是等效的 B = data1[0+ : 8] ; B = data1[0:7] ; ``` **對信號重新進行組合成新的向量時,需要藉助大括號。例如:** ```verilog= wire [31:0] temp1, temp2 ; assign temp1 = {byte1[0][7:0], data1[31:8]}; //數據拼接 assign temp2 = {32{1'b0}}; //賦值32位的數值0 ``` ### :pushpin: **整數(integer)** - 整數類型用關鍵字 integer 來聲明。聲明時不用指明位寬,位寬和編譯器有關,一般為32 bit。 - reg 型變量為無符號數,而 integer 型變量為有符號數。例如: ```verilog= reg [31:0] data1 ; reg [3:0] byte1 [7:0]; //數組變量,後續介紹 integer j ; //整型變量,用來輔助生成數字電路 always@* begin for (j=0; j<=3;j=j+1) begin byte1[j] = data1[(j+1)*8-1 : j*8]; //把data1[7:0]…data1[31:24]依次賦值給byte1[0][7:0]…byte[3][7:0] end end ``` 此例中,integer 信號 j 作為輔助信號,將 data1 的數據依次賦值給數組 byte1。綜合後實際電路里並沒有 j 這個信號,j 只是輔助生成相應的硬件電路。 ### :pushpin: **實數(real)** 實數用關鍵字 real 來聲明,可用十進製或科學計數法來表示。實數聲明不能帶有範圍,默認值為 0。如果將一個實數賦值給一個整數,則只有實數的整數部分會賦值給整數。例如: ```verilog= real data1 ; integer temp ; initial begin data1 = 2e3 ; data1 = 3.75 ; end initial begin temp = data1 ; //temp 值的大小為3 end ``` ### :pushpin: **時間(time)** Verilog 使用特殊的時間寄存器 time 型變量,對仿真時間進行保存。其寬度一般為 64 bit,通過調用系統函數 $time 獲取當前仿真時間。例如: ```verilog= time current_time ; initial begin #100 ; current_time = $time ; //current_time 的大小為100 end ``` ### :pushpin: **數組** 在 Verilog 中允許聲明 reg, wire, integer, time, real 及其向量類型的數組。 數組維數沒有限制。線網數組也可以用於連接實例模塊的端口。數組中的每個元素都可以作為一個標量或者向量,以同樣的方式來使用,形如:**<數組名>[<下標>]**。對於多維數組來講,用戶需要說明其每一維的索引。例如: ```verilog integer flag [7:0] ; //8個整數組成的數組 reg [3:0] counter [3:0] ; //由4個4bit計數器組成的數組 wire [7:0] addr_bus [3:0] ; //由4個8bit wire型變量組成的數組 wire data_bit[7:0][5:0] ; //聲明1bit wire型變量的二維數組 reg [31:0] data_4d[11:0][3:0][3:0][255:0] ; //聲明4維的32bit數據變量數組 ``` 下面顯示了對數組元素的賦值操作: ```verilog= flag [1] = 32'd0 ; //將flag數組中第二個元素賦值為32bit的0值 counter[3] = 4'hF ; //將數組counter中第4個元素的值賦值為4bit 十六進制數F,等效於counter[3][3:0] = 4'hF,即可省略寬度; assign addr_bus[0] = 8'b0 ; //將數組addr_bus中第一個元素的值賦值為0 assign data_bit[0][1] = 1'b1; //將數組data_bit的第1行第2列的元素賦值為1,這裡不能省略第二個訪問標號,即 assign data_bit[0] = 1'b1; 是非法的。 data_4d[0][0][0][0][15:0] = 15'd3 ; //將數組data_4d中標號為[0][0][0][0]的寄存器單元的15~0bit賦值為3 ``` 雖然數組與向量的訪問方式在一定程度上類似,但不要將向量和數組混淆。向量是一個單獨的元件,位寬為 n;數組由多個元件組成,其中每個元件的位寬為 n 或 1。它們在結構的定義上就有所區別。 ### :pushpin: **存儲器** 存儲器變量就是一種寄存器數組,可用來描述 RAM 或 ROM 的行為。例如: ```verilog= reg membit[0:255] ; //256bit的1bit存儲器 reg [7:0] mem[0:1023] ; //1Kbyte存儲器,位寬8bit mem[511] = 8'b0 ; //令第512個8bit的存儲單元值為0 ``` ### :pushpin: **參數** 參數用來表示常量,用關鍵字 parameter 聲明,只能賦值一次。例如: ```verilog= parameter data_width = 10'd32 ; parameter i=1, j=2, k=3 ; parameter mem_size = data_width * 10 ; ``` 但是,通過實例化的方式,可以更改參數在模塊中的值。此部分以後會介紹。 局部參數用 localparam 來聲明,其作用和用法與 parameter 相同,區別在於它的值不能被改變。所以當參數只在本模塊中調用時,可用 localparam 來說明。 ### :pushpin: **字符串** 字符串保存在 reg 類型的變量中,每個字符佔用一個字節(8bit)。因此寄存器變量的寬度應該足夠大,以保證不會溢出。 字符串不能多行書寫,即字符串中不能包含回車符。如果寄存器變量的寬度大於字符串的大小,則使用 0 來填充左邊的空餘位;如果寄存器變量的寬度小於字符串大小,則會截去字符串左邊多餘的數據。例如,為存儲字符串 "run.runoob.com", 需要 14*8bit 的存儲單元: ```verilog= reg [0: 14*8-1] str ; initial begin str = "run.runoob.com"; end ``` 有一些特殊字符在顯示字符串中有特殊意義,例如換行符,製表符等。如果需要在字符串中顯示這些特殊的字符,則需要在前面加前綴轉義字符 \ 。例如下表所示: ![](https://i.imgur.com/IJEZRyd.png) 其實,在 SystemVerilog(主要用於 Verilog 仿真的編程語言)語言中,已經可以直接用關鍵字 string 來表示字符串變量類型,這為 Verilog 的仿真帶來了極大的便利。 # 2.4 Verilog 表達式 ### :pushpin: 表達式 表達式由操作符和操作數構成,其目的是根據操作符的意義得到一個計算結果。表達式可以在出現數值的任何地方使用。例如: ```verilog= a^b ; //a與b進行異或操作 address[9:0] + 10'b1 ; //地址累加 flag1 && flag2 ; //邏輯與操作 ``` ### :pushpin: 操作數 操作數可以是任意的數據類型,只是某些特定的語法結構要求使用特定類型的操作數。 操作數可以為常數,整數,實數,線網,寄存器,時間,位選,域選,存儲器及函數調用等。 ```verilog= module test; //實數 real a, b, c; c = a + b ; //寄存器 reg [3:0] cprmu_1, cprmu_2 ; always @(posedge clk) begin cprmu_2 = cprmu_1 ^ cprmu_2 ; end //函數 reg flag1 ; flag = calculate_result(A, B); //非法操作數 reg [3:0] res; wire [3:0] temp; always@ (*)begin res = cprmu_2 – cprmu_1 ; //temp = cprmu_2 – cprmu_1 ; //不合法,always塊裡賦值對像不能是wire型 end endmodule ``` ### :pushpin: 操作符 Verilog 中提供了大約 9 種操作符,分別是算術、關係、等價、邏輯、按位、歸約、移位、拼接、條件操作符。 大部分操作符與 C 語言中類似。同類型操作符之間,除條件操作符從右往左關聯,其餘操作符都是自左向右關聯。圓括號內表達式優先執行。例如下面每組的 2 種寫法都是等價的。 ```verilog= //自右向左關聯,兩種寫法等價 A+B-C ; (A+B)-C ; //自右向左關聯,兩種寫法等價,結果為 B、D 或 F A ? B : C ? D : F ; A ? B : (C ? D : F) ; //自右向左關聯,兩種寫法不等價 (A ? B : C) ? D : F ; //結果 D 或 F A ? B : C ? D : F ; //結果為 B、D 或 F ``` 不同操作符之間,優先級是不同的。下表列出了操作符優先級從高至低的排列順序。當沒有圓括號時,Verilog 會根據操作符優先級對錶達式進行計算。為了避免由操作符優先級導致的計算混亂,在不確定優先級時,建議用圓括號將表達式區分開來。 ![](https://i.imgur.com/nfVyi6M.png) ### :pushpin: 算術操作符 算術操作符包括單目操作符和雙目操作符。 雙目操作符對 2 個操作數進行算術運算,包括乘(*)、除(/)、加(+)、減(-)、求冪(**)、取模(%)。 ```verilog= reg [3:0] a, b; reg [4:0] c ; a = 4'b0010 ; b = 4'b1001 ; c = a+b; //結果為c=b'b1011 c = a/b; //結果為c=4,取整 ``` 如果操作數某一位為 X,則計算結果也會全部出現 X。例如: ```verilog= b = 4'b100x ; c = a+b ; //结果为c=4'bxxxx ``` 對變量進行聲明時,要根據變量的操作符對變量的位寬進行合理聲明,不要讓結果溢出。上述例子中,相加的 2 個變量位寬為 4bit,那麼結果寄存器變量位寬最少為 5bit。否則,高位將被截斷,導致結果高位丟失。無符號數乘法時,結果變量位寬應該為 2 個操作數位寬之和。 ```verilog= reg [3:0] mula ; reg [1:0] mulb; reg [5:0] res ; mula = 4'he ; mulb = 2'h3 ; res = mula * mulb ; //結果為res=6'h2a, 數據結果沒有丟失位數 ``` + 和 - 也可以作為單目操作符來使用,表示操作數的正負性。此類操作符優先級最高。 ```verilog= -4 //表示負4 +3 //表示正3 ``` 負數表示時,可以直接在十進制數字前面增加一個減號 -,也可以指定位寬。因為負數使用二進制補碼來表示,不指定位寬來表示負數,編譯器在轉換時,會自動分配位寬,從而導致意想不到的結果。例如: ```verilog= mula = -4'd4 ; mulb = 2 ; res = mula * mulb ; //計算結果為res=-6'd8, 即res=6'h38,正常 res = mula * (-'d4) ; //(4的32次冪-4) * 2, 結果異常 ``` ### :pushpin: 關係操作符 關係操作符有大於(>),小於(<),大於等於(>=),小於等於(<=)。 關係操作符的正常結果有 2 種,真(1)或假(0)。 如果操作數中有一位為 x 或 z,則關係表達式的結果為 x。 ```verilog= A = 4 ; B = 3 ; X = 3'b1xx ; A > B //为真 A <= B //为假 A >= Z //为X,不确定 ``` ### :pushpin: 等價操作符 等價操作符包括邏輯相等(==),邏輯不等(!=),全等(===),非全等(!==)。 等價操作符的正常結果有 2 種:為真(1)或假(0)。 邏輯相等/不等操作符不能比較 x 或 z,當操作數包含一個 x 或 z,則結果為不確定值。 全等比較時,如果按位比較有相同的 x 或 z,返回結果也可以為 1,即全等比較可比較 x 或 z。所以,全等比較的結果一定不包含 x。舉例如下: ```verilog= A = 4 ; B = 8'h04 ; C = 4'bxxxx ; D = 4'hx ; A == B //为真 A == (B + 1) //为假 A == C //为X,不确定 A === C //为假,返回值为0 C === D //为真,返回值为1 ``` ### :pushpin: 邏輯操作符 邏輯操作符主要有 3 個:&&(邏輯與), ||(邏輯或),!(邏輯非)。 邏輯操作符的計算結果是一個 1bit 的值,0 表示假,1 表示真,x 表示不確定。 如果一個操作數不為 0,它等價於邏輯 1;如果一個操作數等於 0,它等價於邏輯 0。如果它任意一位為 x 或 z,它等價於 x。 如果任意一個操作數包含 x,邏輯操作符運算結果不一定為 x。 邏輯操作符的操作數可以為變量,也可以為表達式。例如: ```verilog= A = 3; B = 0; C = 2'b1x ; A && B // 为假 A || B // 为真 ! A // 为假 ! B // 为真 A && C // 为X,不确定 A || C // 为真,因为A为真 (A==2) && (! B) //为真,此时第一个操作数为表达式 ``` ### :pushpin: 按位操作符 按位操作符包括:取反(~),與(&),或(|),異或(^),同或(~^)。 按位操作符對 2 個操作數的每 1bit 數據進行按位操作。 如果 2 個操作數位寬不相等,則用 0 向左擴展補充較短的操作數。 取反操作符只有一個操作數,它對操作數的每 1bit 數據進行取反操作。 下圖給出了按位操作符的邏輯規則。 ![](https://i.imgur.com/vgYZbxU.png) ```verilog= A = 4'b0101 ; B = 4'b1001 ; C = 4'bx010 ; ~A //4'b1010 A & B //4'b0001 A | B //4'b1101 A^B //4'b1100 A ~^ B //4'b0011 B | C //4'b1011 B&C //4'bx000 ``` ### :pushpin: 歸約操作符 歸約操作符包括:歸約與(&),歸約與非(~&),歸約或(|),歸約或非(~|),歸約異或(^),歸約同或(~^)。 歸約操作符只有一個操作數,它對這個向量操作數逐位進行操作,最終產生一個 1bit 結果。 邏輯操作符、按位操作符和歸約操作符都使用相同的符號表示,因此有時候容易混淆。區分這些操作符的關鍵是分清操作數的數目,和計算結果的規則。 ```verilog= A = 4'b1010 ; &A ; //結果為 1 & 0 & 1 & 0 = 1'b0,可用來判斷變量A是否全1 ~|A ; //結果為 ~(1 | 0 | 1 | 0) = 1'b0, 可用來判斷變量A是否為全0 ^A ; //结果为 1 ^ 0 ^ 1 ^ 0 = 1'b0 ``` ### :pushpin: 移位操作符 移位操作符包括左移(<<),右移(>>),算術左移(<<<),算術右移(>>>)。 移位操作符是雙目操作符,兩個操作數分別表示要進行移位的向量信號(操作符左側)與移動的位數(操作符右側)。 算術左移和邏輯左移時,右邊低位會補 0。 邏輯右移時,左邊高位會補 0;而算術右移時,左邊高位會補充符號位,以保證數據縮小後值的正確性。 ```verilog= A = 4'b1100 ; B = 4'b0010 ; A = A >> 2 ; //结果为 4'b0011 A = A << 1; //结果为 4'b1000 A = A <<< 1 ; //结果为 4'b1000 C = B + (A>>>2); //结果为 2 + (-4/4) = 1, 4'b0001 ``` ### :pushpin: 拼接操作符 拼接操作符用大括號 {,} 來表示,用於將多個操作數(向量)拼接成新的操作數(向量),信號間用逗號隔開。 拼接符操作數必須指定位寬,常數的話也需要指定位寬。例如: ```verilog= A = 4'b1010 ; B = 1'b1 ; Y1 = {B, A[3:2], A[0], 4'h3 }; //结果为Y1='b1100_0011 Y2 = {4{B}, 3'd4}; //结果为 Y2=7'b111_1100 Y3 = {32{1'b0}}; //结果为 Y3=32h0,常用作寄存器初始化时匹配位宽的赋初值 ``` ### :pushpin: 條件操作符 條件表達式有 3 個操作符,結構描述如下: ```verilog= condition_expression ? true_expression : false_expression ``` - 如果 condition_expression 為真(邏輯值為 1),則運算結果為 true_expression; - 如果 condition_expression 為假(邏輯值為 0),則計算結果為 false_expression。 ```verilog= assign hsel = (addr[9:8] == 2'b0) ? hsel_p1 : hsel_p2 ; //當信號 addr 高 2bit 為 0 時,hsel 賦值為 hsel_p1; 否則,將 hsel_p2 賦值給 hsel。 ``` 其實,條件表達式類似於 2 路(或多路)選擇器,其描述方式完全可以用 if-else 語句代替。 當然條件操作符也能進行嵌套,完成一個多次選擇的邏輯。例如: ```verilog= assign hsel = (addr[9:8] == 2'b00) ? hsel_p1 : (addr[9:8] == 2'b01) ? hsel_p2 : (addr[9:8] == 2'b10) ? hsel_p3 : (addr[9:8] == 2'b11) ? hsel_p4 ; ``` # 2.5 Verilog 編譯指令 以反引號 開始的某些標識符是 Verilog 系統編譯指令。 編譯指令為 Verilog 代碼的撰寫、編譯、調試等提供了極大的便利。 下面介紹下完整的 8 種編譯指令,其中前 4 種使用頻率較高。 `define, `undef 在編譯階段,`define 用於文本替換,類似於 C 語言中的 #define。 一旦 `define 指令被編譯,其在整個編譯過程中都會有效。例如,在一個文件中定義: ```verilog= `define DATA_DW 32 ``` 則在另一個文件中也可以直接使用 DATA_DW。 ```verilog= `define S $stop; //用`S來代替系統函數$stop; (包括分號) `define WORD_DEF reg [31:0] //可以用`WORD_DEF來聲明32bit寄存器變量 ``` `undef 用來取消之前的宏定義,例如: ```verilog= `define DATA_DW 32 …… reg [DATA_DW-1:0] data_in ; …… `undef DATA_DW `ifdef, `ifndef, `elsif, `else, `endif ``` 這些屬於條件編譯指令。例如下面的例子中,如果定義了 MCU51,則使用第一種參數說明;如果沒有定義 MCU、定義了 WINDOW,則使用第二種參數說明;如果 2 個都沒有定義,則使用第三種參數說明。 ```verilog= `ifdef MCU51 parameter DATA_DW = 8 ; `elsif WINDOW parameter DATA_DW = 64 ; `else parameter DATA_DW = 32 ; `endif ``` `elsif, `else 編譯指令對於 `ifdef 指令是可選的,即可以只有 `ifdef 和 `endif 組成一次條件編譯指令塊。 當然,也可用 `ifndef 來設置條件編譯,表示如果沒有相關的宏定義,則執行相關語句。 下面例子中,如果定義了 WINDOW,則使用第二種參數說明。如果沒有定義 WINDOW,則使用第一種參數說明。 ```verilog= `ifndef WINDOW parameter DATA_DW = 32 ; `else parameter DATA_DW = 64 ; `endif ``` ### :pushpin: `include 使用 `include 可以在編譯時將一個 Verilog 文件內嵌到另一個 Verilog 文件中,作用類似於 C 語言中的 #include 結構。該指令通常用於將全局或公用的頭文件包含在設計文件裡。 文件路徑既可以使用相對路徑,也可以使用絕對路徑。 ```verilog= `include "../../param.v" `include "header.v" ``` ### :pushpin: `timescale 在 Verilog 模型中,時延有具體的單位時間表述,並用 `timescale 編譯指令將時間單位與實際時間相關聯。 該指令用於定義時延、仿真的單位和精度,格式為: ```verilog= `timescale time_unit / time_precision ``` time_unit 表示時間單位,time_precision 表示時間精度,它們均是由數字以及單位 s(秒),ms(毫秒),us(微妙),ns(納秒),ps(皮秒)和 fs(飛秒)組成。時間精度可以和時間單位一樣,但是時間精度大小不能超過時間單位大小,例如下面例子中,輸出端 Z 會延遲 5.21ns 輸出 A&B 的結果。 ```verilog= `timescale 1ns/100ps //时间单位为1ns,精度为100ps,合法 //`timescale 100ps/1ns //不合法 module AndFunc(Z, A, B); output Z; input A, B ; assign #5.207 Z = A & B endmodule ``` - 在編譯過程中,`timescale 指令會影響後面所有模塊中的時延值,直至遇到另一個 `timescale 指令或 `resetall 指令。 由於在 Verilog 中沒有默認的 `timescale,如果沒有指定 `timescale,Verilog 模塊就有會繼承前面編譯模塊的 `timescale 參數。有可能導致設計出錯。 - 如果一個設計中的多個模塊都帶有 `timescale 時,模擬器總是定位在所有模塊的最小時延精度上,並且所有時延都相應地換算為最小時延精度,時延單位並不受影響。例如: ```verilog= `timescale 10ns/1ns module test; reg A, B ; wire OUTZ ; initial begin A = 1; B = 0; # 1.28 B = 1; # 3.1 A = 0; end AndFunc u_and(OUTZ, A, B) ; endmodule ``` - 在模塊 AndFunc 中,5.207 對應 5.21ns。 - 在模塊 test 中,1.28 對應 13ns,3.1 對應 31ns。 - 但是,當仿真 test 時,由於 AndFunc 中的最小精度為 100ps,因此 test 中的時延精度將進行重新調整。 13ns 將對應 130*100ps,31ns 將對應 310*100ps。 - 仿真時,時延精度也會使用 100ps。仿真時間單位大小沒有影響。 - 如果有並行子模塊,子模塊間的 `timescale 並不會相互影響。 例如在模塊 test 中再例化一個子模塊 OrFunc。 - 仿真 test 時,OrFunc 中的 #5.207 延時依然對應 52ns。 ```verilog= //子模块: `timescale 10ns/1ns //时间单位为1ns,精度为100ps,合法 module OrFunc(Z, A, B); output Z; input A, B ; assign #5.207 Z = A | B endmodule //顶层模块: `timescale 10ns/1ns module test; reg A, B ; wire OUTZ ; wire OUTX ; initial begin A = 1; B = 0; # 1.28 B = 1; # 3.1 A = 0; end AndFunc u_and(OUTZ, A, B) ; OrFunc u_and(OUTX, A, B) ; endmodule ``` 此例中,仿真 test 時,OrFunc 中的 #5.207 延時依然對應 52ns。 `timescale 的時間精度設置是會影響仿真時間的。時間精度越小,仿真時佔用內存越多,實際使用的仿真時間就越長。所以如果沒有必要,應盡量將時間精度設置的大一些。 ### :pushpin: `default_nettype 該指令用於為隱式的線網變量指定為線網類型,即將沒有被聲明的連線定義為線網類型。 ```verilog= `default_nettype wand ``` 該實例定義的缺省的線網為線與類型。因此,如果在此指令後面的任何模塊中的連線沒有說明,那麼該線網被假定為線與類型。 ```verilog= `default_nettype none ``` 該實例定義後,將不再自動產生 wire 型變量。 例如下面第一種寫法編譯時不會報 Error,第二種寫法編譯將不會通過。 ```verilog= //Z1 無定義就使用,系統默認Z1為wire型變量,有 Warning 無 Error module test_and( input A, input B, output Z); assign Z1 = A & B ; endmodule ``` ```verilog= //Z1 無定義就使用,由於編譯指令的存在,系統會報Error,從而檢查出書寫錯誤 `default_nettype none module test_and( input A, input B, output Z); assign Z1 = A & B ; endmodule ``` ### :pushpin: `resetall 該編譯器指令將所有的編譯指令重新設置為缺省值。 `resetall 可以使得缺省連線類型為線網類型。 當 `resetall 加到模塊最後時,可以將當前的 `timescale 取消防止進一步傳遞,只保證當前的 `timescale 在局部有效,避免 `timescale 的錯誤繼承。 ### :pushpin: `celldefine, `endcelldefine 這兩個程序指令用於將模塊標記為單元模塊,他們包含模塊的定義。例如一些與、或、非門,一些 PLL 單元,PAD 模型,以及一些 Analog IP 等。 ```verilog= `celldefine module ( input clk, input rst, output clk_pll, output flag); …… endmodule `endcelldefine ``` ### :pushpin: `unconnected_drive, `nounconnected_drive 在模塊實例化中,出現在這兩個編譯指令間的任何未連接的輸入端口,為正偏電路狀態或者為反偏電路狀態。 ```verilog= `unconnected_drive pull1 . . . / *在這兩個程序指令間的所有未連接的輸入端口為正偏電路狀態(連接到高電平) * / `nounconnected_drive ``` ```verilog= `unconnected_drive pull0 . . . / *在這兩個程序指令間的所有未連接的輸入端口為反偏電路狀態(連接到低電平) * / `nounconnected_drive ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully