IEEE 2001 重点
矢量位选择和部分选择寻址
Vector bit-select and part-select addressing
操作符 +:与 -:
//Examples:
reg [31:0] big_vect;
reg [0:31] little_vect;
reg [63:0] dword; integer sel;
//The first four if statements show the identity between the two part select constructs. The last one shows an indexable nature.
initial begin
if ( big_vect[0 +:8] == big_vect[7 : 0]) begin end
if (little_vect[0 +:8] == little_vect[0 : 7]) begin end
if ( big_vect[15 -:8] == big_vect[15 : 8]) begin end
if (little_vect[15 -:8] == little_vect[8 :15]) begin end
if (sel >0 && sel < 8)
dword[8*sel +:8] = big_vect[7:0]; // Replace the byte selected.
+: 为升序 -: 为降序
big_vect称为大端,little_vect称为小端; 经过 +: 和 -: 转换后,仍为大端和小端,形式不变
big_vect [0 +: 8] 从0 开始,升序,位宽为8 ======》》》》》big_vect [7 :0]
little_vect [0 +: 8] 从0 开始,升序,位宽为8 ======》》》》》little_vect [0 :7]
big_vect [15 -: 8] 从15开始,降序,位宽为8 ======》》》》》big_vect [15 :8]
little_vect [15 -: 8] 从15开始,降序,位宽为8 ======》》》》》little_vect [8:15]
Array and memory addressing数组与内存寻址
Array and memory addressing
//256x256字节的8bit存储器;256x256x8 bit线网
reg [7:0] twod_array[0:255][0:255];
wire threed_array[0:255][0:255][0:7];
The syntax for access to the array shall consist of the name of the memory or array and an expression for each addressed dimension:
访问数组的语法应包括内存或数组的名称以及每个寻址维度的表达式:
twod_array[addr_expr][addr_expr] threed_array[addr_expr][addr_expr][addr_expr]
As before, the addr_expr
can be any expression. The array twod_array
accesses a whole 8-bit vector, while the array threed_array
accesses a single bit of the three dimensional array.
如前所述,addr_expr
可以是任何表达式。数组twod_array
访问整个8位向量,而数组threed_array
访问三维数组的单个位
To express bit selects or part selects of array elements, the desired word shall first be selected by supplying an address for each dimension. Once selected, bit and part selects shall be addressed in the same manner as net and reg bit and part selects (see 4.2.1).
为了表示数组元素的位选择或部分选择,应首先通过为每个维度提供地址来选择所需的字。
一旦选定,位、数据段的寻址方式与线网、寄存器寻址方式相同
//Examples:
twod_array[14][1][3:0] // access lower 4 bits of word 访问字的低四位
twod_array[1][3][6] // access bit 6 of word 访问字的第六位
twod_array[1][3][sel] // use variable bit select 访问字的第sel位
threed_array[14][1][3:0] // Illegal 非法访问
String operands字符串的操作
String operands shall be treated as constant numbers consisting of a sequence of 8-bit ASCII codes, one per character.
字符串操作数应视为常数,由8位ASCII码序列组成,每个字符一个。
Any VerilogHDL operator can manipulate string operands. The operator shall behave as though the entire string were a single numeric value.
任何Verilog HDL运算符都可以操作字符串。运算符对待整个字符串和对待单个数值是一样的。
![](/qrcode.jpg)
When a variable is larger than required to hold the value being assigned, the contents after the assignment shall be padded on the left with zeros. This is consistent with the padding that occurs during assignment of nonstring values.
当一个变量大于保存赋值所需的值时,赋值后的内容应在左边用零填充。这与非字符串值赋值过程中出现的填充一致。
module string_test;
reg [8*14:1] stringvar;
initial begin stringvar = "Hello world";
$display("%s is stored as %h", stringvar, stringvar);
stringvar = {stringvar,"!!!"};
$display("%s is stored as %h", stringvar, stringvar);
end endmodule
Hello world is stored as 00000048656c6c6f20776f726c64
Hello world!!! is stored as 48656c6c6f20776f726c64212121
reg [8*10:1] s1, s2;
initial begin
s1 = "Hello";
s2 = " world!";
if ({s1,s2} == "Hello world!")
$display("strings are equal");
end
s1 = 000000000048656c6c6f
s2 = 00000020776f726c6421
The concatenation of s1 and s2 includes the zero padding, resulting in the following value:
000000000048656c6c6f00000020776f726c6421
generate 动态创建电路
generate
语句的最主要功能就是对module、reg、assign、always、task
等语句或者模块进行复制
generate
语句有generate_for、generate_if、generate_case
三种语句
generate_for
(1)必须使用genvar申明一个正整数变量,用作for循环的判断。(genvar是generate语句中的一种变量类型,用在generate_for中声明正整数变量。)
(2)需要复制的语句必须写到begin_end语句里面。就算只有一句
(3)begin_end需要有一个类似于模块名的名字。
//格雷码转二进制
module gray2bin1 (bin, gray);
parameter SIZE = 8; // this module is parameterizable 此模块可参数化
output [SIZE-1:0] bin;
input [SIZE-1:0] gray;
genvar i;
generate for (i=0; i<SIZE; i=i+1) begin:bit
assign bin[i] = ^gray[SIZE-1:i];
end
endgenerate
endmodule
//------------------------------------------------------------------------------------//
//格雷码转二进制
module gray2bin2 (bin, gray);
parameter SIZE = 8; // this module is parameterizable
output [SIZE-1:0] bin;
input [SIZE-1:0] gray;
reg [SIZE-1:0] bin;
genvar i;
generate for (i=0; i<SIZE; i=i+1) begin:bit
always @(gray[SIZE-1:i]) // fixed part select 固定部件选择
bin[i] = ^gray[SIZE-1:i];
end
endgenerate
endmodule
//可变参数的二维的普通多位加法器
module addergen1 (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;
wire [SIZE-1:0] t [1:3];
genvar i;
assign c[0] = ci;
// Generated instance names are: 生成的实例为:
// xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1
// bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
// and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
// bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4
// or gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5
// Generated instances are connected with
// multi-dimensional nets t[1][3:0] t[2][3:0] t[3][3:0] 多维线网
// (12 multi-dimensional nets total) 共12个多维线网
generate
for(i=0; i<SIZE; i=i+1) begin:bit
xor g1 ( t[1][i], a[i], b[i]);
xor g2 ( sum[i], t[1][i], c[i]);
and g3 ( t[2][i], a[i], b[i]);
and g4 ( t[3][i], t[1][i], c[i]);
or g5 ( c[i+1], t[2][i], t[3][i]);
end
endgenerate
assign co = c[SIZE];
endmodule
//可变参数的一维的普通多位加法器
module addergen1 (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;
// Generated instance names are:
// xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1
// bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
// and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
// bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4
// or gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5
// Generated instances are connected with
// generated nets: bit[0].t1 bit[1].t1 bit[2].t1 bit[3].t1
// bit[0].t2 bit[1].t2 bit[2].t2 bit[3].t2
// bit[0].t3 bit[1].t3 bit[2].t3 bit[3].t3
generate
for(i=0; i<SIZE; i=i+1) begin:bit
wire t1, t2, t3; // generated net declaration
xor g1 ( t1, a[i], b[i]);
xor g2 ( sum[i], t1, c[i]);
and g3 ( t2, a[i], b[i]);
and g4 ( t3, t1, c[i]);
or g5 ( c[i+1], t2, t3);
end
endgenerate
assign co = c[SIZE];
endmodule
//多层循环嵌套
parameter SIZE = 2;
genvar i, j, k, m;
generate
for (i=0; i<SIZE+1; i=i+1) begin:B1 // scope B1[i]
M1 N1(); // instantiates B1[i].N1[i]
for (j=0; j<SIZE; j=j+1) begin:B2 // scope B1[i].B2[j]
M2 N2(); // instantiates B1[i].B2[j].N2
for (k=0; k<SIZE; k=k+1) begin:B3 // scope B1[i].B2[j].B3[k]
M3 N3(); // instantiates实例化 B1[i].B2[j].B3[k].N3
end
end
if (i>0)
for (m=0; m<SIZE; m=m+1) begin:B4 // scope B1[i].B4[m]
M4 N4(); // instantiates B1[i].B4[m].N4
end
end
endgenerate
// some of the generated instance names are: 生成的一些实例名称包括:
// B1[0].N1 B1[1].N1
// B1[0].B2[0].N2 B1[0].B2[1].N2
// B1[0].B2[0].B3[0].N3 B1[0].B2[0].B3[1].N3
// B1[0].B2[1].B3[0].N3
// B1[1].B4[0].N4 B1[1].B4[1].N4
generate_if
generate_for用于复制模块,而generate_if则是根据模块的参数(必须是常量)作为条件判断,来产生满足条件的电路。相当于判断语句。
//一种参数化乘法器模块的实现
module multiplier(a,b,product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;// can not be modified 不能修改
// directly with the defparam statement 直接使用defparam语句
// or the module instance statement # 或使用模块实例中的#()语句修改
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);
// instance a CLA_multiplier 实例化
else
WALLACE_multiplier #(a_width,b_width) u1(a, b, product);
// instance a Wallace-tree multiplier 实例化
endgenerate
// The generated instance name is u1 生成实例名u1
endmodule
generate_case
generate_case其实跟generate_if一样,都是根据参数(都必须为常量)作为判断条件,来产生满足条件的电路,不同于使用了case语法而已。
generate
case (WIDTH)
1: adder_1bit x1(co, sum, a, b, ci); // 1-bit adder implementation
2: adder_2bit x1(co, sum, a, b, ci); // 2-bit adder implementation
default: adder_cla #(WIDTH) x1(co, sum, a, b, ci); // others - carry look-ahead adder
endcase // The generated instance name is x1
endgenerate
/*---------------------------------------------------------------------------------------------------*/
module generate_case(
input t0 ,
input t1 ,
input t2 ,
output d
);
localparam S = 8; //定义模块所需参数,用于判断产生电路
generate
case(S)
0:assign d = t0 | t1 | t2;
1:assign d = t0 & t1 & t2;
default:assign d = t0 & t1 | t2;
endcase
endgenerate
endmodule
defparam高层改低层参数
方法一:引用实例时对实例内的参数进行改变
在引用Decode实例时,D1,D2的Width将采用不同的值4和5,且D1的Polarity将为0。可用例
子中所用的方法来改变参数,即用 #(4,0)向D1中传递 Width=4,Polarity=0; 用#(5)向D2中传递
Width=5,Polarity仍为1。
传参按顺序传入
module Decode(A,F);
parameter Width=1, Polarity=1;
……………
endmodule
module Top();
wire[3:0] A4;
wire[4:0] A5;
wire[15:0] F16;
wire[31:0] F32;
Decode #(4,0) D1(A4,F16);
Decode #(5) D2(A5,F32);
Endmodule
不按顺序,直接使用defparam修改
module foo(a,b);
real r1,r2;
parameter [2:0] A = 3’h2;
parameter B = 3’h2;
initial
begin
r1 = A;
r2 = B;
$display("r1 is %f r2 is %f",r1,r2);
end
endmodule // foo
module bar;
wire a,b;
defparam f1.A = 3.1415;
defparam f1.B = 3.1415;
foo f1(a,b);
endmodule // bar
方法二:通过defparam直接在高层模块中修改
多层次模块构成的电路,在一个模块中改变另一个模块的参数时,需要使用defparam
命令
module Test;
wire W;
Top T ( );
endmodule
module Top;
wire W ;
Block B1 ( );
Block B2 ( );
endmodule
module Block;
Parameter P = 0;
endmodule
module Annotate;
defparam
Test.T.B1.P = 2,
Test.T.B2.P = 3;
endmodule
port 端口的定义
module test(a,b,c,d,e,f,g,h); input [7:0] a;
// no explicit declaration - net is unsigned 没有显式声明-net是无符号的
input [7:0] b;
input signed [7:0] c;
input signed [7:0] d; // no explicit net declaration - net is signed 没有显式的net声明-net被签名
output [7:0] e; // no explicit declaration - net is unsigned 没有显式声明-net是无符号的
output [7:0] f;
output signed [7:0] g;
output signed [7:0] h; // no explicit net declaration - net is signed 没有显式的net声明-net被签名
wire signed [7:0] b; // port b inherits signed attribute from net decl. 端口b从net decl继承signed属性。
wire [7:0] c; // net c inherits signed attribute from port net c从端口继承signed属性
reg signed [7:0] f;
// port f inherits signed attribute from reg decl. 端口f从reg decl继承signed属性。
reg [7:0] g; // reg g inherits signed attribute from port net g从端口继承signed属性
endmodule
//===============================================不懂,没百度到===================================================
module complex_ports ({c,d}, .e(f));
// Nets {c,d} receive the first port bits. net{c,d}接收第一个端口位。
//Name ’f’ is declared inside the module. 名称“f”在模块内声明。
// Name ’e’ is defined outside the module. 名称“e”在模块外部定义
// Can’t use named port connections of first port. 无法使用第一个端口的命名端口连接
module split_ports (a[7:4], a[3:0]);
// First port is upper 4 bits of ’a’. 第一个端口是“a”的高位4位。
// Second port is lower 4 bits of ’a’. 第二个端口是“a”的低4位。
// Can’t use named port connections because of part-select port ’a’. 无法使用命名端口连接,因为部分选择端口“a”
module same_port (.a(i), .b(i));
// Name ’i’ is declared inside the module as a inout port. 名称“i”在模块内声明为inout端口。为
// Names ’a’ and ’b’ are defined for port connections. 端口连接定义了名称“a”和“b”。
module renamed_concat (.a({b,c}), f, .g(h[1]));
// Names ’b’, ’c’, ’f’, ’h’ are defined inside the module. 名称“b”、“c”、“f”、“h”在模块内定义
// Names ’a’, ’f’, ’g’ are defined for port connections. 为端口连接定义了名称“a”、“f”、“g”。
// Can use named port connections. 可以使用命名端口连接。
//============================================================================================================
module same_input (a,a); input a;
// This is legal. The inputs are ored together. 这是合法的。输入是“或”在一起的。
verilog提供signed
(有符号数)和unsigned
(无符号数)两种运算
Unsigned:不含sign bit(符号位)
以4bit的数据来说,范围为0000 ~ 1111,即0 ~ 15
Signed:含sign bit(符号位)
以4bit的数据来说,范围为1000 ~ 0111,即-8 ~ +7 (有符号数用补码来表示)
unsigned运算时,如果发生高位溢出,会舍去溢出的数,如1111+1=(1)0000.
signed运算时,要考虑符号https://www.cnblogs.com/oomusou/archive/2009/10/31/verilog_signed_overflow.html
The real data
type shall not be directly connected to a port. It shall be connected indirectly, as shown in the following example. The system functions $realtobits and $bitstoreal shall be used for passing the bit patterns across module ports.
real类型不应直接连接到端口,应间接连接。如下例所示。系统功能 r e a l t o b i t s 和 realtobits和 realtobits和bitstoreal应用于在模块端口之间传递位模式
real 实数寄存器 realtime 实数时间寄存器
https://blog.csdn.net/u011731939/article/details/40807449
Hierarchical names分层名称
module mod (in);
input in;
reg hold;
always @(posedge in) begin : keep
hold = in;
end
endmodule
module cct (stim1, stim2);
input stim1, stim2;
// instantiate mod 实例化mod模块
mod amod(stim1), bmod(stim2);
endmodule
module wave;
reg stim1, stim2;
cct a(stim1, stim2); // instantiate cct 实例化cct模块
initial begin :wave1
#100 fork :innerwave
reg hold;
join
#150 begin
stim1 = 0;
end
end
endmodule
有如图结构
a list of the hierarchical forms of the names of all the objects defined in the code
代码中定义的所有对象名称的层次结构列表
Scope rules变量的搜索规则
错误操作:
在同一模块中声名两个相同的变量,
在同一模块中任务或函数声名名称相同,
为门实例指定与连接到其输出的网络的名称相同的名称
向上搜索原则(无层次路径)
如果在任务、函数或命名块中直接引用标识符(无层次路径),则向上搜索。
先在本范围(任务,函数或命名块等),没找到则继续向外部搜索标识符,搜索完模块或搜索到标识符为止。注意:不搜索同级范围
有层次路径
如果一个标识符引用了一个分层名称,那么路径可以以模块名、实例名、任务、函数或命名块开头。应首先在当前级别搜索名称,然后在更高级别的模块中搜索,直到找到为止。由于模块名和实例名都可以使用,所以如果有一个名为与实例名相同的模块,则实例名优先。