这个简单的 verilog ~^ 运算符发生了什么?
What happened to this simple verilog ~^ operator?
我写了这么一个简单的block,但是cnt的值是乱改的。结果不应该随着 cnt 的大小而改变,但实际上它是。
always @* begin
cnt = 0;
$display(" Now cnt is reset as %d", cnt);
for (i = 0; i < IN_NUM; i = i+1)begin
$display ("x[i] ~^ w[i] value: %d ", (x[i] ~^ w[i]));
$display ("Count value before: %d ", cnt);
cnt = cnt + (x[i] ~^ w[i]);
$display ("Count value after: %d ", cnt);
end
end
控制台结果是:
Now cnt is reset as 0
x[i] ~^ w[i] value: 1
Count value before: 0
Count value after: 1048575
x[i] ~^ w[i] value: 1
Count value before: 1048575
Count value after: 1048574
x[i] ~^ w[i] value: 1
Count value before: 1048574
Count value after: 1048573
我附上整个代码如下:
`timescale 1ns / 1ps
module tb_xnor_net();
localparam IN_WIDTH = 31;
localparam CMP_WIDTH = 20;
reg [IN_WIDTH-1:0] w;
reg [IN_WIDTH-1:0] x;
reg [CMP_WIDTH-1:0] th;
wire [CMP_WIDTH-1:0] cnt;
wire y;
initial begin
$display(" time, th, y, cnt, x ");
// monitors checks and print the transitions
// $monitor("%d, %d, %b, %b, %h", $time, th, y, cnt, x);
w <= 0; x <= 0; th <= 0;
#20 x <= 'h0; w <= 'h0; th <= 'd10;
#20 x <= 'hff; w <= 'h0; th <= 'd10;
#20 $finish;
end
xnor_kernel
#(
.CMP_WIDTH(CMP_WIDTH),
.IN_NUM(IN_WIDTH)
)
test
(
.x(x),
.w(w),
.th(th),
.y(y),
.cnt(cnt)
);
endmodule
module xnor_kernel
#(
parameter CMP_WIDTH = 9,
parameter IN_NUM = (1<<CMP_WIDTH)
)
(
input wire [IN_NUM-1:0] x,
input wire [IN_NUM-1:0] w,
input wire [CMP_WIDTH-1:0] th,
output wire y,
output reg [CMP_WIDTH-1:0] cnt
);
wire v;
integer i;
always @* begin
cnt = 0;
$display(" Now cnt is reset as %d", cnt);
for (i = 0; i < IN_NUM; i = i+1)begin
$display ("x[i] ~^ w[i] value: %d ", (x[i] ~^ w[i]));
$display ("Count value before: %d ", cnt);
cnt = cnt + (x[i] ~^ w[i]);
$display ("Count value after: %d ", cnt);
end
end
assign y = (cnt >= th);
endmodule
我只是 explained this same problem for a slightly different example 给另一个用户——你必须在同一个 class 中。
问题是表达式中的操作数在应用运算符 之前扩展到 cnt
(CMP_WIDTH) 的宽度。您希望 x[i] ~^ w[i]
的结果保持在 1 位。因此,请改用 ==
运算符。在 SystemVerilog 中,您可以执行 1'(x[i] ~^ w[i])
,但 ==
运算符更直观。
我写了这么一个简单的block,但是cnt的值是乱改的。结果不应该随着 cnt 的大小而改变,但实际上它是。
always @* begin
cnt = 0;
$display(" Now cnt is reset as %d", cnt);
for (i = 0; i < IN_NUM; i = i+1)begin
$display ("x[i] ~^ w[i] value: %d ", (x[i] ~^ w[i]));
$display ("Count value before: %d ", cnt);
cnt = cnt + (x[i] ~^ w[i]);
$display ("Count value after: %d ", cnt);
end
end
控制台结果是:
Now cnt is reset as 0
x[i] ~^ w[i] value: 1
Count value before: 0
Count value after: 1048575
x[i] ~^ w[i] value: 1
Count value before: 1048575
Count value after: 1048574
x[i] ~^ w[i] value: 1
Count value before: 1048574
Count value after: 1048573
我附上整个代码如下:
`timescale 1ns / 1ps
module tb_xnor_net();
localparam IN_WIDTH = 31;
localparam CMP_WIDTH = 20;
reg [IN_WIDTH-1:0] w;
reg [IN_WIDTH-1:0] x;
reg [CMP_WIDTH-1:0] th;
wire [CMP_WIDTH-1:0] cnt;
wire y;
initial begin
$display(" time, th, y, cnt, x ");
// monitors checks and print the transitions
// $monitor("%d, %d, %b, %b, %h", $time, th, y, cnt, x);
w <= 0; x <= 0; th <= 0;
#20 x <= 'h0; w <= 'h0; th <= 'd10;
#20 x <= 'hff; w <= 'h0; th <= 'd10;
#20 $finish;
end
xnor_kernel
#(
.CMP_WIDTH(CMP_WIDTH),
.IN_NUM(IN_WIDTH)
)
test
(
.x(x),
.w(w),
.th(th),
.y(y),
.cnt(cnt)
);
endmodule
module xnor_kernel
#(
parameter CMP_WIDTH = 9,
parameter IN_NUM = (1<<CMP_WIDTH)
)
(
input wire [IN_NUM-1:0] x,
input wire [IN_NUM-1:0] w,
input wire [CMP_WIDTH-1:0] th,
output wire y,
output reg [CMP_WIDTH-1:0] cnt
);
wire v;
integer i;
always @* begin
cnt = 0;
$display(" Now cnt is reset as %d", cnt);
for (i = 0; i < IN_NUM; i = i+1)begin
$display ("x[i] ~^ w[i] value: %d ", (x[i] ~^ w[i]));
$display ("Count value before: %d ", cnt);
cnt = cnt + (x[i] ~^ w[i]);
$display ("Count value after: %d ", cnt);
end
end
assign y = (cnt >= th);
endmodule
我只是 explained this same problem for a slightly different example 给另一个用户——你必须在同一个 class 中。
问题是表达式中的操作数在应用运算符 之前扩展到 cnt
(CMP_WIDTH) 的宽度。您希望 x[i] ~^ w[i]
的结果保持在 1 位。因此,请改用 ==
运算符。在 SystemVerilog 中,您可以执行 1'(x[i] ~^ w[i])
,但 ==
运算符更直观。