这个简单的 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]),但 == 运算符更直观。