verilogvivado

`$display` output wrong result when caculate `-3*3`?


module te(
input a
);
reg clk;
reg [1:0]d1=2'd3;
reg signed [2:0]d2=-3'd3;
reg signed [4:0]d3;

always @(posedge clk) begin
   d3<=d1*d2;
   $display("%b",d3);//01111,how to know the exact value?the expect value is 1001
end

initial begin
    clk = 1'b1;
end

always  begin
#1 clk = ~clk;//for clock IP,100MHZ
end

endmodule

As -3*3=-9,the d3 expect value is 1001.
What make $display("%b",d3); output 01111?


Solution

  • d3 must contain 5 bits to store the number -9. But d2 = -3 is represented as a 3-bit value. The multiplication operation is performed on a 3-bit number. In this case, the highest bit of a 3-bit number responsible for the sign will not be interpreted as the highest bit of a 5-bit number responsible for the sign.

    If you set d2 as a 5-bit number, then everything will work:

    reg signed [4:0]d2=-5'd3;
    

    Note that 1001b is a positive 9. But you should have a negative 9, i.e. 10111b.

    d3 = -9;
    repeat(19) begin
        $display("%d = %bb", d3, d3);
        d3++;
    end
    

    Result:

     -9 = 10111b
     -8 = 11000b
     -7 = 11001b
     -6 = 11010b
     -5 = 11011b
     -4 = 11100b
     -3 = 11101b
     -2 = 11110b
     -1 = 11111b
      0 = 00000b
      1 = 00001b
      2 = 00010b
      3 = 00011b
      4 = 00100b
      5 = 00101b
      6 = 00110b
      7 = 00111b
      8 = 01000b
      9 = 01001b