l generate語句
Verilog-2001添加了generate循環,允許產生module和primitive的多個實例化,同時也可以產生多個variable,net,task,function,continous assignment,initial和always。在generate語句中可以引入if-else和case語句,根據條件不同產生不同的實例化。
為此,Verilog-2001還增加了以下關鍵字:generate,endgenerate,genvar,localparam。genvar為新增數據類型,存儲正的integer。在generate語句中使用的index必須定義成genvar類型。localparam與parameter有些類似,不過其不能通過redefinition改變值。除了可以在generate語句中使用if-else,case外,還能使用for語句進行循環。
下面是一個使用generate的例子,根據a_width和b_width的不同,實例化不同的multiplier。
module multiplier (a, b, product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
input [a_width-1:0] a;
input [b_width-1:0] b;
output[product_width-1:0]product;
generate
if((a_width < 8) || (b_width < 8))
CLA_multiplier #(a_width, b_width)
u1 (a, b, product);
else
WALLACE_multiplier #(a_width, b_width)
u1 (a, b, product);
endgenerate
endmodule
在下面的例子中,在generate語句中使用了for語句。
module Nbit_adder (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE:0] c;
genvar i;
assign c[0] = ci;
assign co = c[SIZE];
generate
for(i=0; i<SIZE; i="i"+1)
begin:addbit
wire n1,n2,n3; //internal nets
xor g1 ( n1, a[i], b[i]);
xor g2 (sum[i],n1, c[i]);
and g3 ( n2, a[i], b[i]);
and g4 ( n3, n1, c[i]);
or g5 (c[i+1],n2, n3);
end
endgenerate
endmodule
generate執行過程中,每一個generated net在每次循環中有唯一的名字,比如n1在4次循環中會產生如下名字:
addbit[0].n1
addbit[1].n1
addbit[2].n1
addbit[3].n1
這也是為什么在begin-end塊語句需要名字的一個原因。同樣,實例化的module,gate等在每次循環中也有不同的名字。
addbit[0].g1
addbit[1].g1
addbit[2].g1
addbit[3].g1
l constant functions
Verilog的語法要求定義向量的寬度或數組大小時其值必須是一個確定的數字或一個常量表達式。比如:
parameter WIDTH = 8;
wire [WIDTH-1:0] data;
在Verilog-1995標准中,常量表達式只能是基於一些常量的算術操作。而在Verilog-2001中增加了constant function,其定義與普通的function一樣,不過constant function只允許操作常量。下面是一個使用constant function的例子,clogb2函數返回輸入值2次方的次數。
module ram (address_bus, write, select, data);
parameter SIZE = 1024;
input [clogb2(SIZE)-1:0] address_bus;
...
function integer clogb2 (input integer depth);
begin
for(clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
...
endmodule
l Indexed vector part selects
在Verilog-1995中,可以選擇向量的任一位輸出,也可以選擇向量的連續幾位輸出,不過此時連續幾位的始末數值的index需要是常量。而在Verilog-2001中,可以用變量作為index,進行part select。
[base_expr +: width_expr] //positive offset
[base_expr -: width_expr] //negative offset
其中base_expr可以是變量,而width_expr必須是常量。+:表示由base_expr向上增長width_expr位,-:表示由base_expr向上遞減width_expr位。例如:
reg [63:0] word;
reg [3:0] byte_num; //a value from 0 to 7
wire [7:0] byteN = word[byte_num*8 +: 8];
如果byte_num的值為4,則word[39:32]賦值給byteN。
l 多維數組
Verilog-1995只允許一維數組,而Verilog-2001允許多維數組。
//1-dimensional array of 8-bit reg variables
//(allowed in Verilog-1995 and Verilog-2001)
reg [7:0] array1 [0:255];
wire [7:0] out1 = array1[address];
//3-dimensional array of 8-bit wire nets
//(new for Verilog-2001)
wire [7:0] array3 [0:255][0:255][0:15];
wire [7:0] out3 = array3[addr1][addr2][addr3];
而且在Verilog-1995中不能對一維數組中取出其中的一位,比如要取出上面array1[7][5],需要將array1[7]賦給一個reg變量比如arrayreg <= array1[7],再從arrayreg中取出bit5,即arrayreg[5]。而在Verilog-2001中,可以任意取出多維數組中的一位或連續幾位,比如:
//select the high-order byte of one word in a
//2-dimensional array of 32-bit reg variables
reg [31:0] array2 [0:255][0:15];
wire [7:0] out2 = array2[100][7][31:24];
l 符號運算
在Verilog-1995中,integer數據類型為有符號類型,而reg和wire類型為無符號類型。而且integer大小固定,即為32位數據。在Verilog-2001中對符號運算進行了如下擴展。
Reg和wire變量可以定義為有符號類型:
reg signed [63:0] data;
wire signed [7:0] vector;
input signed [31:0] a;
function signed [128:0] alu;
函數返回類型可以定義為有符號類型。
帶有基數的整數也可以定義為有符號數,在基數符號前加入s符號。
16'hC501 //an unsigned 16-bit hex value
16'shC501 //a signed 16-bit hex value
操作數可以在無符號和有符號之間轉變。通過系統函數$signed和$unsigned實現。
reg [63:0] a; //unsigned data type
always @(a) begin
result1 = a / 2; //unsigned arithmetic
result2 = $signed(a) / 2;//signed arithmetic
end
增加了算術移位操作,在Verilog-1995中只有邏輯移位操作。比如D的初始值為8’b10100011,則:
D >> 3 //logical shift yields 8'b00010100
D >>> 3 //arithmetic shift yields 8'b11110100
l 指數運算
Verilog-2001中增加了指數運算操作,操作符為**。
always @(posedge clock)
result = base ** exponent;
l 遞歸函數和任務
在Verilog-2001中增加了一個新的關鍵字:automatic。該關鍵字可以讓任務或函數在運行中從新調用該任務和函數。
function automatic [63:0] factorial;
input [31:0] n;
if (n == 1)
factorial = 1;
else
factorial = n * factorial(n-1);
endfunction
l 組合邏輯敏感信號通配符
在組合邏輯設計中,需要在敏感信號列表中包含所有組合邏輯輸入信號,以免產生鎖存器。在大型的組合邏輯中比較容易遺忘一些敏感信號,因此在Verilog-2001中可以使用@*包含所有的輸入信號作為敏感信號。
always @* //combinational logic sensitivity
if (sel)
y = a;
else
y = b;
l 使用逗號隔開敏感信號
Verilog-2001中可以用逗號來代替or隔開敏感信號。
always @(a or b or c or d or sel)
always @(a, b, c, d, sel)
l Automatic width extension beyond 32 bits
在Verilog-1995中,在不指定基數的情況下為大於32位的變量賦高阻值,只能使其低32位為高阻值,其他高位會被設置為0,此時需要指定基數值才能將高位賦值為高阻。
Verilog-1995:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;
data = 'bz; //fills with 'h00000000zzzzzzzz
data = 64'bz; //fills with 'hzzzzzzzzzzzzzzzz
而在Verilog-2001中並沒有這一限制。
Verilog-2001:
parameter WIDTH = 64;
reg [WIDTH-1:0] data;
data = 'bz; //fills with 'hzzzzzzzzzzzzzzzz
轉載:http://blog.sina.com.cn/s/blog_625507140100ux11.html