Search code examples
verilogriscvunsignedsigned

How to make an unsigned to signed number, and reverse in verilog


I have an school assignment at my university in verilog where i need to create an ALU for a RISC-V processor. In the ALU, i need to perform the operations AND, OR, XOR, sub, add, bitwise left and right, less than and arithmetic shift right. For the operations sub, add and less than, the professor told us that we need to first make them signed and then do the operation, and especially for less i need to make them again unsigned.I have created this code for the ALU:

module alu
   (output reg zero,
    output reg [31:0] result,
    input wire [31:0] op1, op2,
    input wire [3:0] alu_op);

  // extra
  wire [31:0] signed_op1, signed_op2, unsigned_op1;
  wire [4:0] shiftamount;
  wire [31:0] shiftedresult;

  // creating the signed number of op1, op2.
  assign signed_op1 = {{32{op1[31]}},op1};
  assign signed_op2 = {{32{op2[31]}},op2};

  // making them unsigned again, only for >>>> operation.
  assign unsigned_op1 = signed_op1[31:0];

  always @ (alu_op or op1 or op2) // this block changes whenever alu_op, op1, or op2 changes

  begin
    case(alu_op)
      4'b0000: result <= op1 & op2; // AND
      4'b0001: result <= op1 | op2; // OR
      4'b0010: result <= signed_op1 + signed_op2; // +
      4'b0110: result = signed_op1 - signed_op2; // -
      4'b0111: result = (signed_op1 < signed_op2); // smaller than
      4'b1000: result = op1 >> shiftamount; // bitwise shift right
      4'b1001: result = op1 << shiftamount; // bitwise shift left
      4'b1010: shiftedresult = signed_op1 >>> shiftamount; // arithmetic shift right
      assign result = shiftedresult; //making in unsigned 
      4'b1101: result = op1 ^ op2; // XOR
      default : result = 0;
    endcase
  end

  always @(result) 
    begin
      if (result == 0) 
        begin
            Zero <= 1;
        end else 
        begin
            Zero <= 0;
        end
    end

endmodule

The line assign signed_op1 = {{32{op1[31]}},op1}; I saw it from chat gpt for making the unsigned input to signed, but i am not sure if it is right. Is what the chat gpt wrote right or wrong. I now that the sub is not complete yet because i need to do it in two's complement first, other than that do i need to change something in my code? than, we need to make the result back to unsigned


Solution

  • Just declare signed variables

    wire signed [31:0] signed_op1, signed_op2;

    Also, make sure you know the desired number range.
    Range for 4-bit unsigned number: 0 to 15
    Range for 4-bit signed number: -8 to 7

    Also, to convert between signed and unsigned numbers. Use $signed and $unsigned. Example:

    wire signed [3:0] a_sign;
    wire [3:0] b_unsign;
    assign a_sign = $signed(b_unsign);
    assign b_unsign = $unsigned(a_sign);