icicle/rv32_alu.sv
2017-12-07 22:37:58 +00:00

72 lines
2.2 KiB
Systemverilog

`ifndef RV32_ALU
`define RV32_ALU
localparam RV32_ALU_OP_ADD_SUB = 4'b0000;
localparam RV32_ALU_OP_XOR = 4'b0001;
localparam RV32_ALU_OP_OR = 4'b0010;
localparam RV32_ALU_OP_AND = 4'b0011;
localparam RV32_ALU_OP_SLL = 4'b0100;
localparam RV32_ALU_OP_SRL_SRA = 4'b0101;
localparam RV32_ALU_OP_SLT = 4'b0110;
localparam RV32_ALU_OP_SLTU = 4'b0111;
localparam RV32_ALU_OP_SRC1P4 = 4'b1000;
localparam RV32_ALU_OP_SRC2 = 4'b1001;
localparam RV32_ALU_SRC1_REG = 1'b0;
localparam RV32_ALU_SRC1_PC = 1'b1;
localparam RV32_ALU_SRC2_REG = 1'b0;
localparam RV32_ALU_SRC2_IMM = 1'b1;
module rv32_alu (
/* control in */
input [3:0] op_in,
input sub_sra_in,
input src1_in,
input src2_in,
/* data in */
input [31:0] pc_in,
input [31:0] rs1_value_in,
input [31:0] rs2_value_in,
input [31:0] imm_in,
/* data out */
output [31:0] result_out
);
logic [31:0] src1 = src1_in ? pc_in : rs1_value_in;
logic [31:0] src2 = src2_in ? imm_in : rs2_value_in;
logic src1_sign = src1[31];
logic src2_sign = src2[31];
logic [4:0] shamt = src2[4:0];
logic [32:0] add_sub = sub_sra_in ? src1 - src2 : src1 + src2;
logic [31:0] srl_sra = $signed({sub_sra_in ? src1_sign : 1'b0, src1}) >>> shamt;
logic carry = add_sub[32];
logic sign = add_sub[31];
logic ovf = (!src1_sign && src2_sign && sign) || (src1_sign && !src2_sign && !sign);
logic lt = sign != ovf;
logic ltu = carry;
always_comb begin
case (op_in)
RV32_ALU_OP_ADD_SUB: result_out = add_sub[31:0];
RV32_ALU_OP_XOR: result_out = src1 ^ src2;
RV32_ALU_OP_OR: result_out = src1 | src2;
RV32_ALU_OP_AND: result_out = src1 & src2;
RV32_ALU_OP_SLL: result_out = src1 << shamt;
RV32_ALU_OP_SRL_SRA: result_out = srl_sra;
RV32_ALU_OP_SLT: result_out = {31'b0, lt};
RV32_ALU_OP_SLTU: result_out = {31'b0, ltu};
RV32_ALU_OP_SRC1P4: result_out = src1 + 4;
RV32_ALU_OP_SRC2: result_out = src2;
default: result_out = 32'bx;
endcase
end
endmodule
`endif