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
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);