轉載請標明出處
數組、結構體和聯合體
1. 結構體(struct)
1.1. 結構體聲明
結構體默認是變量,也能夠聲明爲線網express
var struct { // 經過var進行結構體變量聲明數組
logic [31:0] a, b;函數
logic [ 7:0] opcode;} Instruction_Word_var;ui
wire struct { //結構體線網聲明,定義爲線網類型時,結構體的全部成員必須都是四態類型的 logic [31:0] a, b;spa
logic [ 7:0] opcode;} Instruction_Word_net;code
Point:結構體內不能使用線網類型。多個線網能夠用SV接口打包成一個組。索引
Eg:自定義結構體接口
typedef struct { //結構體定義,不分配存儲器rem
logic [31:0] a, b;it
logic [ 7:0] opcode;
logic [23:0] address;
} instruction_word_t;
instruction_word_t IW; // 結構體實例化時分配存儲區
自定義結構體能夠在模塊,接口或者包中定義。
1.2. 結構體賦值
u 使用值列表 初始化
結構體在實例化的時候能夠對其成員初始化using ’{<value>}
instruction_word_t IW = ’{100, 3, 8’hFF, 0}; //賦值a=100 b=3 opcode=FF address=0
u 結構體成員賦值
IW.a = 100; //引用結構體成員的名稱對成員進行賦值
u 將結構體表達式賦給結構體
if (!resetN) IW = ’{100, 5, 8’hFF, 0}; //同初始化的時候相似,但這是在過程塊中進行的
u 結構體表達式的默認值
IW = ’{ real:1.0, default:0, r1:3.1415 };//r1=3.1415 其餘real成員=1.0 其餘成員=0 (precedence:顯性成員名賦值>指定數據類型賦值>default)
1.3. 壓縮(packed)和非壓縮(unpacked)結構體(都可綜合)
默認狀況下,結構體是非壓縮的。結構體成員是獨立的變量或常量。
使用packed顯示的聲明一個壓縮結構體。壓縮結構體按照指定的順序以相鄰的位來存儲結構體成員。壓縮結構體被當作一個向量存儲,結構體的第一個成員在向量的最左邊。向量的最低位是結構體最後一個成員最低位,其位編號爲bit 0。如圖所示(相似小端模式):
struct packed {
logic valid; logic [ 7:0] tag; logic [31:0] data;
} data_word;
packed structure的成員能夠經過成員名引用(<struct_name>.<mem_name>)也可使用結構體向量的相應位來引用(<struct_name>[M:N])。
壓縮結構體只能包含整數。
(題外話:real和shortreal分別對應C語言的雙精度和單精度,不可被綜合,可是在抽象硬件模型和tb中有用,所以不算作整數範疇)
壓縮結構體可被看做是向量來操做。(除了’{}賦值操做是當作unpacked之外)
1.4. 經過端口傳遞結構體
要想使用結構體類型的端口,要先使用typedef定義爲用戶自定義數據類型的結構體。
Unpacked struct經過模塊port傳遞時,端口兩邊鏈接必須是同一種類型的結構體。
在兩個不一樣模塊聲明的匿名結構體即使成員類型相同也不能看做同一類型結構體。
1.5. 將結構體做爲自變量傳遞至task和function
要想傳遞結構體類型的自變量,要先使用typedef定義爲用戶自定義數據類型的結構體。
同4.1.4,要相同類型結構體才能做爲自變量傳遞給task和function
2. 聯合體(union)
聯合體只存儲一個元素,但該元素能夠有多種表示方法,每種表示方法能夠是不一樣數據類型
Union聲明及成員引用方法同struct,關鍵詞爲union。
Union內的成員公用同一存儲空間。因此對其中一個成員賦值,其餘成員也會相應變化,只是數據類型不一樣而已
2.1. 非壓縮聯合體(unpacked unions) (不可綜合)
非壓縮聯合體能夠包含任意變量類型,包括real,非壓縮結構體和非壓縮數組。
2.2. 標籤聯合體(tagged unions)(沒懂啥應用價值P130)
至關於在使用時要注意讀值和上次存儲都是針對同一個union member(有啥用)
2.3. 壓縮聯合體(packed unions)(可綜合)
壓縮聯合體中每一個成員位數相同,只存儲整數值。
(通常用於存signed,unsigned兩種類型,好比,當須要存signed類型時,給ele0賦值,須要存unsigned類型時,給ele1賦值)
typedef struct packed {
logic [15:0] source_address;
logic [15:0] destination_address;
logic [23:0] data;
logic [ 7:0] opcode;
} data_packet_t;
union packed {
data_packet_t packet; //壓縮結構體
logic [7:0][7:0] bytes; // 壓縮數組
} dreg;
該例中,值可使用byte格式的數組寫入,而後以data_packet格式讀出相同的值(共享空間)
3. 數組(Arrays)(可綜合)
3.1. 非壓縮數組(unpacked arrays)
l Verilog數組
變量及線網都可以用於數組。
聲明:<data_type> <vector_size> <array_name> <array_dimensions>
verilog一次只能訪問數組的一個元素。
數組中各個元素存儲位置相互獨立
需指定起始地址及結束地址 eg.int array [64:83]; //地址從64-83的Verilog數組
l SV數組
增長event數據類型及全部SV數據類型
SV能夠引用整個非壓縮數組以及一段元素(複製非壓縮數組時」=」左右需一樣結構及類型)
無需指定起始位置及結束位置,只需指定維度大小
eg.logic [31:0] data [1024]; //is equivalent to logic [31:0] data [0:1023];
3.2. 壓縮數組(packed arrays)
l Verilog向量是一維壓縮數組
l SV容許多維壓縮數組,壓縮數組做爲鄰近元素存儲
Eg: logic [3:0][7:0] data; // 2-D packed array包含4個8位的子數組
l 引用壓縮數組
logic [3:0][7:0] data; // 2-D packed array 4個8位數組
wire [31:0] out = data; // whole array
wire sign = data[3][7]; // 一位
wire [3:0] nib = data [0][3:0]; // 一部分
byte high_byte;
assign high_byte = data[3]; // 8-bit 寬的一段
logic [15:0] word;
assign word = data[1:0]; // 2段
3.3. 使用壓縮或非壓縮數組
l 非壓縮數組用於模擬存儲器以及抽象數據類型如RAM,ROM,一般每次只訪問一個元素
l 壓縮數組建立有子域的變量,能夠訪問子段
3.4. 聲明時對數組進行初始化
l 壓縮數組初始化
logic [3:0][7:0] a = 32’h0; //向量賦值
logic [3:0][7:0] b = {16’hz,16’h0}; //常數的拼接
logic [3:0][7:0] c = {16{2’b01}}; //常數的複製(16個01)
l 非壓縮數組初始化
n Verilog:int d [0:1][0:3] = { {7,3,0,5}, {2,0,1,6} }; //d[0][0]=7 d[1][3]=6 不用’
n SV:int e [0:1][0:3] = ’{ 2{7,3,0,5} }; //’{’{},’{}} or ’{n{}}
l 非壓縮數組能夠被初始化有一個默認值(default)
int a1 [0:7][0:1023] = ’{default:8’h55};
3.5. 數組賦值
給非壓縮數組賦值的時候要以元素爲單位賦值,給壓縮數組賦值的時候當它是個向量就行
Eg:a[3] = '{'hF, 'hA, 'hC, 'hE};//非壓縮數組 a[0] = 16’hFACE; //壓縮數組
3.6. 數組複製
壓縮數組能夠直接賦值給壓縮數組,同理非壓縮數組能夠直接賦值給非壓縮數組。
壓縮數組和非壓縮數組的互相賦值要使用位流轉換的方式
3.7. 使用位流轉換複製數組和結構體(靜態轉換操做符 ’ )
位流轉換使用SV靜態轉換操做符,轉換須要至少目標數組是用typedef表示的自定義類型
typedef int data_t [3:0][7:0]; // unpacked type
data_t a; // unpacked array
int b [1:0][3:0][3:0]; // unpacked array
a = data_t’(b); // 將非壓縮數組賦給不一樣結構的非壓縮數組
轉換操做經過將源數組或結構體轉換成臨時向量表達式(位流),而後將位組賦給目標數組的各個元素來實現。
3.8. 由數組構成的數組
Eg: wire [3:0][7:0] data [0:1023];
//由32位元素組成的非壓縮數組,每一個元素是由4個字節組成的壓縮數組
非壓縮數組的索引先於壓縮數組的索引,順序如圖(unpacked→packed,left→right)
3.9. 數組中使用用戶自定義類型,結構體和聯合體
數組能夠包含用戶自定義類型,結構體和聯合體(聯合體必須是壓縮的)
3.10. 數組能夠經過端口及任務和函數傳送
4. foreach數組循環結構體
foreach循環用來對一維或多維數組中的元素進行迭代,而沒必要指定數組每一個維度的寬度
int sum [1:8] [1:3];
foreach ( sum[i,j] ) //自變量是數組名,[ ]中用,隔開循環變量列表。
sum[i][j] = i + j; //對數組初始化
外循環對應低基數索引。上例中,最外層循環對i進行索引,最內層循環對j進行迭代
循環變量可缺省,循環變量爲空時,循環不會對數組的該維度進行迭代
5. 用於數組查詢的系統函數(array定寬時可綜合)
$dimensions(array_name) //返回數組的維數
$left(array_name, dimension) //返回指定維度的最高有效位(MSB)
從最左端的非壓縮維度開始,從左到右遞增;而後遞增到壓縮維度,從左到右遞增
Eg. logic [1:2][7:0] word [0:3][4:1];
$left(word,1) will return 0
$left(word,2) will return 4
$left(word,3) will return 1
$left(word,4) will return 7
$right(array_name, dimension) //返回指定維度的最低有效位(LSB)
$low(array_name, dimension) //返回指定維度的最低位數(上例中dimension1-4分別 對應0,1,1,0)
$high(array_name, dimension) //返回指定維度的最高位數
$size(array_name, dimension) //返回指定維度元素的總個數(high-low+1)
$increment(array_name, dimension) //對於指定的維度,若是$left>=$right,返回1,不然-1
$bit(expression) //返回表達式的位數
Eg. bit [63:0] a; logic [63:0] b;
$bits(a) returns 64;$bits(b) returns 64;道理我都懂,but why $bits(a+b) returns 128?