当我们定义了一个向量,在使用这个向量时,可能是整个向量全部都使用,也有可能只是使用向量的其中一部分。verilog 语言语法支持可变的向量域选择,方便用户的使用。
1.语法:(向量使用方法)
- 向量名 [ 起始位 +: 位宽 ]
在不改变原本向量声明的高低有效位顺序的情况下,从起始位开始(包括起始位), 宽度为位宽,从起始位递增到位宽的一段向量区域。
例:
wire [31 : 0] a; a [0 +: 8] 等效为 a[7 : 0]; // 起始位 在最右侧
wire [0 : 31] b; b [0 +: 8] 等效为 b[0 : 7]; // 起始位 在最左侧
- 向量名 [ 起始位 -: 位宽 ]
在不改变原本向量声明的高低有效位顺序的情况下,从起始位开始(包括起始位), 宽度为位宽,从起始位递减到位宽的一段向量区域。
wire [31 : 0] a; a [7 -: 8] 等效为 a[7 : 0]; // 起始位 在最左侧
wire [0 : 31] b; b [7 -: 8] 等效为 b[0 : 7]; // 起始位 在最右侧
- 起始位可以是变量,但位宽必须是常量
例:
for (i = 0; i < 4; i = i + 1)
a[(i*8) +: 8] = i;
例1:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
`timescale 1ns / 1ps module tb; wire [7:0] a = 8'h7f; reg [3:0] b; initial begin b = a[0 +: 4]; $display("time = %d, b = %h", $time, b); #10; b = a[3:0]; $display("time = %d, b = %h", $time, b); #10; b = a[7 -: 4]; $display("time = %d, b = %h", $time, b); #10; b = a[7:4]; $display("time = %d, b = %h", $time, b); #10; end endmodule |
仿真的结果:
|
1 2 3 4 |
<span style="color: #0000ff;"><strong>time = 0, b = f</strong></span> <span style="color: #0000ff;"><strong>time = 10, b = f</strong></span> <span style="color: #0000ff;"><strong>time = 20, b = 7</strong></span> <span style="color: #0000ff;"><strong>time = 30, b = 7</strong></span> |
2.向量定义
wire [63:0] a; // a[0] 是最低有效位, a[63] 是最高有效位
reg [0:63] b; // b[0] 是最高有效位,b[63] 是最低有效位
例2:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
`timescale 1ns / 1ps module tb; wire [63:0] a; // a[0] 是最低有效位, a[63] 是最高有效位 reg [0:63] b; // b[0] 是最高有效位, b[63] 是最低有效位 assign a = 64'h0123_4567_89ab_cdef; reg [23:0] c; initial begin b = 64'h0123_4567_89ab_cdef; c = a[31 -: 24]; // 从bit[31]位开始(包括bit[31]位), 宽度为24位。 相当于 c = a [31:08]; $display ("time = %d, c = %h", $time , c ); #10; c = a[ 8 +: 24]; // 从bit[8]位开始(包括bit[8]位), 宽度为24位。 相当于 c = a [31:08]; $display ("time = %d, c = %h", $time , c ); #10; c = b[31 -: 24]; // 从bit[31]位开始(包括bit[31]位), 宽度为24位。 相当于 c = b [08:31]; $display ("time = %d, c = %h", $time , c ); #10; c = b[ 8 +: 24]; // 从bit[8]位开始(包括bit[8]位), 宽度为24位。 相当于 c = b [08:31]; $display ("time = %d, c = %h", $time , c ); #10; end endmodule |
控制台输出的结果:
time = 0, c = 89abcd
time = 10, c = 89abcd
time = 20, c = 234567
time = 30, c = 234567
可变的向量域选择通常用于向量的初始化赋值, 当然在平时使用时,也是可以用于赋值语句的。 可变的向量域选择是可仿真的, 也是可综合的语法。
例3:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
`timescale 1ns / 1ps module tb; integer i; reg [31:0] a; reg [31:0] b; initial begin for (i = 0; i < 4; i = i + 1) begin a[(i*8) +: 8] = i; end #10; $display("a[31:24] = %h", a[31:24]); $display("a[23:16] = %h", a[23:16]); $display("a[15:08] = %h", a[15:08]); $display("a[07:00] = %h", a[07:00]); #10; b[31:24] = 3; b[23:16] = 2; b[15:08] = 1; b[07:00] = 0; #10; $display("b[31:24] = %h", b[31:24]); $display("b[23:16] = %h", b[23:16]); $display("b[15:08] = %h", b[15:08]); $display("b[07:00] = %h", b[07:00]); end endmodule |
控制台输出结果:
a[31:24] = 03
a[23:16] = 02
a[15:08] = 01
a[07:00] = 00
b[31:24] = 03
b[23:16] = 02
b[15:08] = 01
b[07:00] = 00
我们会看到, 上个例子中, 如果使用可变向量选择, 会使得代码变得更加简洁灵活。特别是在for 循环中经常会使用可变向量域选择这种方式。
对应视频: