Search code examples
veriloglogical-operators

Why is logic right shift behaving like arithmetic right shift in this code?


I'm building a floating point adder module and part of it requires 2's complementing and shifting value. The main module code is

module backup (x, y, z, clk);
input [7:0] x,y;
output reg [7:0] z;
input clk;
integer i;
reg [1:0] a;
reg unsigned [7:0] temp;
reg unsigned [8:0] temp2;
always @ (posedge clk) begin
a = 2'b00;
temp = 8'b00111100; 
temp = ((~temp)+1) >> 2;
$display("temp = %b", temp);
end
endmodule

module backup_tb();
reg [7:0] x,y;
wire [7:0] z;
reg clk;

backup m1 (.x(x),.y(y),.z(z),.clk(clk));

always #10 clk = ~clk;
initial begin
clk = 0;
#50
$finish;
end
endmodule

The output for this code is temp = 11110001 while intended output is temp = 00110001. Please explain what am I missing here, or how can I fix it?


Solution

  • The problem is not with the shift right; it's with the expression ((~temp)+1). You are adding an 8-bit operand to a 32-bit operand, and operands get extended before performing any operations. Numeric literals are implicitly 32-bits. So the bitwise ~ operation inverts 32'b00000000_00000000_00000000_00111100 and then shifts it right. To fix it, yo can write:

    temp = ((~temp)+1'b1) >> 2;