相关阅读
Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
位选
位选(bit-select)用于选择一个向量(vector)的某位,可以是线网大类(net),也可以是变量大类(variable)中的reg、integer和time(注意:real和realtime不可以位选)。
位选的语法如下所示。
vector [expression]
如果位选expression的结果超出vector的范围或者位选expression的结果包含x或z,则位选作为右值计算的结果是x,仿真器会给出警告,如下例所示。
module test();
reg [2:0] a = 3'b101;
reg b = 1'b1;
initial #1 $display("a[0] is %d", a[0]); //a[0] is 1
initial #1 $display("a[b] is %d", a[b]); //a[b] is 0
initial #1 $display("a[1'bx] is %d", a[1'bx]); //a[1'bx] is x
initial #1 $display("a[3] is %d", a[3]); //a[3] is x
endmodule
如果位选expression的结果超出vector的范围或者位选expression的结果包含x或z,则位选作为左值不会有任何作用,仿真器会给出警告,如下例所示。
module test();
reg [2:0] a = 3'b000;
initial #1 begin a[3]=1'b1;a[1'bx]=1'b1;end
initial #2 $display(a is "%b",a); // a is 000
endmodule
域选
域选(part select)用于选择一个向量(vector)的连续某几位,该向量可以是线网大类(net),也可以是变量大类(variable)中的reg、integer和time(注意:real和realtime不可以域选)。
域选有两种形式,常量域选和索引域选(Verilog 2001标准引入),下面分别进行说明。
常量域选
常量域选的语法如下所示。
vector [msb_expr : lsb_expr]
其中msb_expr和lsb_expr都必须计算为常量。msb_expr和lsb_expr的相对大小,需要符合vector定义时msb_expr和lsb_expr的相对大小,如下例所示。
module test();
reg [4:0] b = 5'b01010; //msb(left hand) is greater than lsb(right hand)
reg [0:4] a = 5'b01010; //msb(left hand) is less than lsb(right hand)
initial #1 $display("b[1:0] is %b", b[1:0]); //right, select lsb 2 bits, 10
initial #1 $display("b[1:0] is %b", b[0:1]); //false, msb(left hand) should be greater than lsb(right hand)
initial #1 $display("a[1:0] is %b", a[3:4]); //right, select lsb 2 bits, 10
initial #1 $display("a[1:0] is %b", a[4:3]); //false, msb(left hand) should be less than lsb(right hand)
endmodule
msb_expr和lsb_expr可以相等,此时相当于位选,如下例所示。
module test();
reg [4:0] b = 5'b01010;;
initial #1 $display("b[1] is %b", b[1]); //right bit-select, 1
initial #1 $display("b[1:1] is %b", b[1:1]); //right part-select, 1
endmodule
如果域选作为右值超出界限,则超出界限的部分为x,这是多数仿真器的处理方式,但也有仿真器选择让所有结果为x,不管如何处理,仿真器会给出警告,如下例所示。
module test();
reg [4:0] b = 5'b01010;;
initial #1 $display("b[5:-1] is %b", b[5:-1]); //x01010x for most simulator
endmodule
// x01010x
Mentor Modelsim SE
Aldec Riviera Pro
Mentor Questa
Synopsys VCS
Icarus Verilog
// xxxxxx
Cadence Xcelium
如果域选作为左值超出界限,则超出界限的位不会写入,只有界限中的位会被写入,这是多数仿真器的处理方式,但也有仿真器选择不进行任何写入,不管如何处理,仿真器会给出警告,如下例所示。
module test();
reg [2:0] a = 3'b000;
initial #1 begin a[2:-1]=4'b1100;end
initial #2 $display("%b",a);
endmodule
// 110
Mentor Modelsim SE
Aldec Riviera Pro
Mentor Questa
Synopsys VCS
Icarus Verilog
// 000
Cadence Xcelium
如果msb_expr或lsb_expr出现了x或z,则仿真器会报错。
索引域选
索引域选的语法如下所示。
reg [15:0] big_vector;
reg [0:15] little_vector;
big_vector [lsb_base_expr +: width_expr]
little_vector [msb_base_expr +: width_expr]
big_vector [msb_base_expr -: width_expr]
little_vector [lsb_base_expr -: width_expr]
可以看出,根据向量msb_expr和lsb_expr的相对大小,索引域选的解释方式不同。但都由两部分组成,base表达式可以是一个非常量表达式,width表达式必须是一个常量表达式,即可以动态索引固定数量的位,下面给出了一些等价写法。
reg [15:0] big_vector;
reg [0:15] little_vector;
reg a=0;
reg b=5;
******************
big_vector [5:0]
big_vector [a+:6]
******************
big_vector [5:0]
big_vector [b-:6]
******************
little_vector [0:5]
little_vector [a+:6]
******************
little_vector [0:5]
little_vector [b-:6]
索引域选的越界问题和常量域选是一样处理的,因为它们本来就是可互相转换的。