ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Verilog基础:操作数的位选(bit-select)和域选(part select)

Verilog基础:操作数的位选(bit-select)和域选(part select)

相关阅读

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]

索引域选的越界问题和常量域选是一样处理的,因为它们本来就是可互相转换的。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进