《SystemVerilog驗證-測試平臺編寫指南》學習 - 第2章 數據類型



《SystemVerilog驗證-測試平臺編寫指南》學習 - 第2章 數據類型


  SystemVerilog引進了一些新的數據類型,它們具有如下優點:

(1)雙狀態數據類型:更好的性能,更低的內存消耗;
(2)隊列、動態和關聯數組:減少內存消耗,自帶搜索和分類功能;
(3)類和結構:支持抽象數據結構;
(4)聯合和合並結構:允許對同一數據有多種視圖(view);
(5)字符串:支持內建的字符序列;
(6)枚舉類型:方便代碼編寫,增加可讀性;


2.1 內建數據類型

  logic類型不能有多個結構性的驅動,在雙向總線建模的時候要使用線網類型。
  logic類型只能有一個驅動,否則編譯報錯,所以logic可以用來查找頂層多驅動的錯誤。

雙狀態數據類型
  最簡單的雙狀態數據類型是bit,它是無符號的。另外4種帶有符號的雙狀態數據類型是byte、shortint、int和longint,如下所示:

bit           b      ;    // 雙狀態,單比特無符號
bit   [31:0]  b32    ;    // 雙狀態,32比特無符號整數
int unsigned  ui     ;    // 雙狀態,32比特無符號整數

int           i      ;    // 雙狀態,32比特有符號整數
byte          b8     ;    // 雙狀態,8 比特有符號整數
shortint      s      ;    // 雙狀態,16比特有符號整數
longint       l      ;    // 雙狀態,64比特有符號整數

integer       i4     ;    // 四狀態,32比特有符號整數
time          t      ;    // 四狀態,64比特無符號整數

real          r      ;    // 雙狀態,雙精度浮點數

記:integer和time是四狀態數據類型,integer是32位有符號,time是64位無符號。

注:
  你可能會樂意用byte數據類型代替logic[7:0]的聲明,以使得程序更加簡潔。但是需要注意的是這些新的數據類型是帶符號的,所以byte變量的最大值只有127(取值範圍-128 ~ 127)。可以使用byte unsigned,但這其實比使用bit[7:0]還要麻煩。在進行隨機化時,帶符號變量可能會造成意想不到的結果。
  若把雙狀態變量連接到待測設計,務必小心,如果待測設計產生了X或者Z,這些值會被轉換爲雙狀態值,而測試代碼可能永遠也察覺不了。這些值被轉換爲了0還是1並不重要,重要的是要隨時檢查未知值的傳播。使用 $isunknown 操作符,可以在表達式的任意位出現X或者Z時返回1,如下例所示:

if ($isunknown(iport) == 1)
    $display("@%0t: 4-state value detected on iport %b", $time, iport);

2.2 定寬數組

2.2.1 聲明

  SystemVerilog允許只給出數組寬度的便捷聲明方式,和C語言類似。
  可以通過在變量名後面指定維度的方式來創建多維數組。緊湊型聲明方式是SystemVerilog特有的。

int       lo_hi      [0:15]       ; // 16個整數[0]...[15]
int       c_style    [16]         ; // 便捷聲明,16個整數[0]...[15]

int       array2     [0:7][0:3]   ; // 完整的聲明
int       array3     [8][4]       ; // 緊湊的聲明
array2[7][3]  = 1 ;                 // 設置最後一個元素爲1

  若代碼中試圖從一個越界的地址中讀取數據,那麼SystemVerilog將返回數組元素的缺省值。比如,四狀態logic返回X,雙狀態int或bit則返回0。這適用於所有數組類型,包括定寬數組、動態數組、關聯數組和隊列,也同時適用於地址中包含有X和Z的情況。線網在沒有驅動時輸出是Z。

  對於非壓縮數組(非合併數組),很多SystemVerilog仿真器存放數組元素時使用32bit的字符邊界,所以byte、shortint和int都是存放在相同長度的一個字中,而longint則存放到兩個字中。例如:

bit   [7:0] b_unpack [3] ;  // 定義3個8位的非壓縮數組

非合併數組的存放

注:非壓縮數組(非合併數組) 佔用更多的內存空間。

2.2.2 常量數組

  使用:一個單引號加大括號來初始化數組。
  可以部分賦值;可以重複次數賦值;可以爲那些沒有顯式賦值的元素指定一個缺省值。如下所示:

int     ascend  [4] = '{0, 1, 2, 3} ;    // 對4個元素進行初始化
int     descend [5] ;

descend = '{4, 3, 2, 1, 0} ;             // 爲5個元素賦值
descend [0:2] = '{5, 6, 7} ;             // 爲前3個元素賦值
ascend  = '{4{8}} ;                      // 4個值全部爲8
descend = '{9, 8, default:1} ;           // {9, 8, 1, 1, 1}

2.2.3 基本的數組操作 -- for和foreach

  操作數組最常見的方式是使用 for 或者 foreach 循環。
  $size函數返回數組的寬度。
  在 foreach 循環中,只需要指定數組名並在後面的方括號中給出索引變量,SystemVerilog便會自動遍歷數組中的元素,索引變量將自動聲明,並只在循環內有效。

// 在數組操作中使用 for 和 foreach 循環

initial begin
    bit  [31:0] src  [5] ;  // 聲明5個32位整數
    bit  [31:0] dst  [5] ;  // 聲明5個32位整數
  //bit  [31:0] src[5], dst[5] ;

    for (int i = 0; i < $size(src); i++)
        src[i] = i ;
    foreach (dst[j])
        dst[j] = src[j] * 2 ; // dst的值是srcd的2倍
end
// 初始化並遍歷多維數組
int   md[2][3]  = '{'{0, 1, 2}, '{3, 4, 5}} ; // 定義常量數組
initial begin
    $display ("Initial Value:") ;
    foreach (md[i, j])             // 正確語法格式
        $display ("md[%0d][%0d]=%0d", i, j, md[i][j]) ;

    $display ("New Value:") ;
    // 對最後3個元素重複賦值5
    md = '{'{9, 8, 7}, '{3{32'd5}}} ;
    foreach (md[i, j])           // 正確語法格式
        $display ("md[%0d][%0d]=%0d", i, j, md[i][j]) ;
end

  打印結果:

Initial Value:
md[0][0]=0
md[0][1]=1
md[0][2]=2
md[1][0]=3
md[1][1]=4
md[1][2]=5

New Value:
md[0][0]=9
md[0][1]=8
md[0][2]=7
md[1][0]=5
md[1][1]=5
md[1][2]=5

注意:foreach 的使用

  如果不需要遍歷數組中的所有維度,可以在 foreach 循環裏忽略掉它們。看下面的例子,把一個二維數組打印成一個方形的陣列。它在外層循環遍歷一個維度,然後再內層循環遍歷第二個維度。

// 打印一個多維數組
initial begin
    byte  twoD [4][6] ;    //
    foreach (twoD[i, j])
        twoD [i][j] = i * 10 + j ;  //賦初值

    foreach (twoD[i]) begin
        $write ("%2d: ", i) ;
        foreach (twoD[, j])
            $write ("%3d", twoD[i][j]) ;
        $display ;
    end
end

  打印結果如下:

0: 0 1 2 3 4 5
1: 10 11 12 13 14 15
2: 20 21 22 23 24 25
3: 30 31 32 33 34 35 

  補充:foreach 循環會遍歷原始聲明中的數組範圍。如,
數組 f[5]等同於f[0:4],而 foreach (f[i]) 等同於 for (int i = 0; i <= 4; i++)。
數組 rev[6:2]來說,foreach (rev[i]) 等同於 for (int i=6; i >= 2; i--)。

2.2.4 基本的數組操作 -- 複製和比較

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章