What happened to this simple verilog ~^ operator?

让人想犯罪 __ 提交于 2021-02-17 03:36:06

问题


I wrote a simple block like this, but the cnt value is changed arbitrarily. The result is not supposed to change with size of cnt, but actually it is.

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

The console result is:

 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

I attach the whole code as below:

`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

回答1:


I just explained this same problem for a slightly different example to another user— you must be in the same class.

The problem is the operands in your expression get extended to the width of cnt (CMP_WIDTH) before the operators are applied. You want the result of x[i] ~^ w[i] to remain at 1 bit. So use the == operator instead. In SystemVerilog, you could do 1'(x[i] ~^ w[i]), but the == operator is much more intuitive.



来源:https://stackoverflow.com/questions/61966920/what-happened-to-this-simple-verilog-operator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!