SystemVerilog 中可变宽度的位分片
Bit slicing with variable width in SystemVerilog
我正在尝试使用 +:
运算符访问数组的某些部分,但是遇到了臭名昭著的 [variable] is not a constant
错误。唯一的问题是,我希望从数组中获取的宽度也在发生变化。
这是我的循环:
logic [N-1:0] a;
logic [2**N-2:0] b;
for (i = 0; i < N; i++)
a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
换句话说,如果N = 4
,我希望这个循环这样做:
a[0] = b[0:0] == 1'b1;
a[1] = b[2:1] == 2'b11;
a[2] = b[6:3] == 4'b1111;
a[3] = b[14:7] == 8'b11111111;
从逻辑上讲,我很确定我提供的循环有效,但是 SystemVerilog 不允许使用非常数来设置宽度(在 a:
之后)。
当我的起始索引和宽度都依赖于非常量变量时,如何使用 +:
运算符?或者考虑到 N
可以是一个很大的数字,还有另一种方法可以做到这一点。
谢谢!
编辑:
这可以通过轮班来完成,这是一个工作代码:
for (i = 0; i < N; i++)
a[i] <= ((b >> (2**i)-1) << ((2**N) - (2**i) - 1)) ==
{(2**N-1){1'b1}} << ((2**N) - (2**i) - 1);
您不能使用可变宽度的 +:
。它实际上只是 shifts 和 masks 的简写。例如,下面的内容应该适用于您的情况:
logic [N-1:0] a;
logic [2**N-2:0] b;
always_comb begin
for (int i = 0; i < N; i++) begin
logic [2**N-2:0] tmpb, tmp1;
tmpb = b >> ((2**i)+1);
tmp1 = ((2**N)'(1) << (2**i)) - 1;
a[i] = (tmpb & tmp1) == 0;
end
end
您只需要计算出确切的偏移数和宽度即可。
您可以结合使用“+:”运算符和掩码
parameter N = 8; localparam N2 = 2**(N-1);
logic [N-1:0] a;
logic [2**N-1:0] b;
initial begin
b ={8'b000001,4'b1111,2'b01,1'b1};
for (int i = 0; i < N; i++)
a[i] = (b[(2**i)-1 +: N2] | ~N2'((1 << 2**i)- 1)) == '1;
$displayb(a,,b);
end
你可以使用+:
,前提是右边是常数或genvar
。
logic [N-1:0] a;
logic [2**N-2:0] b;
for (genvar i = 0; i < N; i++) begin : gen_a
assign a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
end
请注意,此 for 循环是一个不在程序块内的生成 for 循环(即 begin
-end
)
我正在尝试使用 +:
运算符访问数组的某些部分,但是遇到了臭名昭著的 [variable] is not a constant
错误。唯一的问题是,我希望从数组中获取的宽度也在发生变化。
这是我的循环:
logic [N-1:0] a;
logic [2**N-2:0] b;
for (i = 0; i < N; i++)
a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
换句话说,如果N = 4
,我希望这个循环这样做:
a[0] = b[0:0] == 1'b1;
a[1] = b[2:1] == 2'b11;
a[2] = b[6:3] == 4'b1111;
a[3] = b[14:7] == 8'b11111111;
从逻辑上讲,我很确定我提供的循环有效,但是 SystemVerilog 不允许使用非常数来设置宽度(在 a:
之后)。
当我的起始索引和宽度都依赖于非常量变量时,如何使用 +:
运算符?或者考虑到 N
可以是一个很大的数字,还有另一种方法可以做到这一点。
谢谢!
编辑:
这可以通过轮班来完成,这是一个工作代码:
for (i = 0; i < N; i++)
a[i] <= ((b >> (2**i)-1) << ((2**N) - (2**i) - 1)) ==
{(2**N-1){1'b1}} << ((2**N) - (2**i) - 1);
您不能使用可变宽度的 +:
。它实际上只是 shifts 和 masks 的简写。例如,下面的内容应该适用于您的情况:
logic [N-1:0] a;
logic [2**N-2:0] b;
always_comb begin
for (int i = 0; i < N; i++) begin
logic [2**N-2:0] tmpb, tmp1;
tmpb = b >> ((2**i)+1);
tmp1 = ((2**N)'(1) << (2**i)) - 1;
a[i] = (tmpb & tmp1) == 0;
end
end
您只需要计算出确切的偏移数和宽度即可。
您可以结合使用“+:”运算符和掩码
parameter N = 8; localparam N2 = 2**(N-1);
logic [N-1:0] a;
logic [2**N-1:0] b;
initial begin
b ={8'b000001,4'b1111,2'b01,1'b1};
for (int i = 0; i < N; i++)
a[i] = (b[(2**i)-1 +: N2] | ~N2'((1 << 2**i)- 1)) == '1;
$displayb(a,,b);
end
你可以使用+:
,前提是右边是常数或genvar
。
logic [N-1:0] a;
logic [2**N-2:0] b;
for (genvar i = 0; i < N; i++) begin : gen_a
assign a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
end
请注意,此 for 循环是一个不在程序块内的生成 for 循环(即 begin
-end
)