data/full_repos/permissive/428334706/verilog/rtl/BB/ibex_alu.v
data/verilator_xmls/0e969db1-f851-4522-ae09-341e6e298b3a.xml
module ibex_alu (
	operator_i,
	operand_a_i,
	operand_b_i,
	multdiv_operand_a_i,
	multdiv_operand_b_i,
	multdiv_en_i,
	adder_result_o,
	adder_result_ext_o,
	result_o,
	comparison_result_o,
	is_equal_result_o
);
	input wire [4:0] operator_i;
	input wire [31:0] operand_a_i;
	input wire [31:0] operand_b_i;
	input wire [32:0] multdiv_operand_a_i;
	input wire [32:0] multdiv_operand_b_i;
	input wire multdiv_en_i;
	output wire [31:0] adder_result_o;
	output wire [33:0] adder_result_ext_o;
	output reg [31:0] result_o;
	output wire comparison_result_o;
	output wire is_equal_result_o;
	wire [31:0] operand_a_rev;
	wire [32:0] operand_b_neg;
	generate
		genvar k;
		for (k = 0; k < 32; k = k + 1) begin : gen_revloop
			assign operand_a_rev[k] = operand_a_i[31 - k];
		end
	endgenerate
	reg adder_op_b_negate;
	wire [32:0] adder_in_a;
	wire [32:0] adder_in_b;
	wire [31:0] adder_result;
	localparam [4:0] ibex_defines_ALU_EQ = 16;
	localparam [4:0] ibex_defines_ALU_GE = 14;
	localparam [4:0] ibex_defines_ALU_GEU = 15;
	localparam [4:0] ibex_defines_ALU_GT = 12;
	localparam [4:0] ibex_defines_ALU_GTU = 13;
	localparam [4:0] ibex_defines_ALU_LE = 10;
	localparam [4:0] ibex_defines_ALU_LEU = 11;
	localparam [4:0] ibex_defines_ALU_LT = 8;
	localparam [4:0] ibex_defines_ALU_LTU = 9;
	localparam [4:0] ibex_defines_ALU_NE = 17;
	localparam [4:0] ibex_defines_ALU_SLET = 20;
	localparam [4:0] ibex_defines_ALU_SLETU = 21;
	localparam [4:0] ibex_defines_ALU_SLT = 18;
	localparam [4:0] ibex_defines_ALU_SLTU = 19;
	localparam [4:0] ibex_defines_ALU_SUB = 1;
	always @(*) begin
		adder_op_b_negate = 1'b0;
		case (operator_i)
			ibex_defines_ALU_SUB, ibex_defines_ALU_EQ, ibex_defines_ALU_NE, ibex_defines_ALU_GTU, ibex_defines_ALU_GEU, ibex_defines_ALU_LTU, ibex_defines_ALU_LEU, ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLTU, ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU: adder_op_b_negate = 1'b1;
			default:
				;
		endcase
	end
	assign adder_in_a = (multdiv_en_i ? multdiv_operand_a_i : {operand_a_i, 1'b1});
	assign operand_b_neg = {operand_b_i, 1'b0} ^ {33 {adder_op_b_negate}};
	assign adder_in_b = (multdiv_en_i ? multdiv_operand_b_i : operand_b_neg);
	assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
	assign adder_result = adder_result_ext_o[32:1];
	assign adder_result_o = adder_result;
	wire shift_left;
	wire shift_arithmetic;
	wire [4:0] shift_amt;
	wire [31:0] shift_op_a;
	wire [31:0] shift_result;
	wire [31:0] shift_right_result;
	wire [31:0] shift_left_result;
	assign shift_amt = operand_b_i[4:0];
	localparam [4:0] ibex_defines_ALU_SLL = 7;
	assign shift_left = operator_i == ibex_defines_ALU_SLL;
	localparam [4:0] ibex_defines_ALU_SRA = 5;
	assign shift_arithmetic = operator_i == ibex_defines_ALU_SRA;
	assign shift_op_a = (shift_left ? operand_a_rev : operand_a_i);
	wire [32:0] shift_op_a_32;
	assign shift_op_a_32 = {shift_arithmetic & shift_op_a[31], shift_op_a};
	wire signed [32:0] shift_right_result_signed;
	assign shift_right_result_signed = $signed(shift_op_a_32) >>> shift_amt[4:0];
	assign shift_right_result = shift_right_result_signed[31:0];
	generate
		genvar j;
		for (j = 0; j < 32; j = j + 1) begin : gen_resrevloop
			assign shift_left_result[j] = shift_right_result[31 - j];
		end
	endgenerate
	assign shift_result = (shift_left ? shift_left_result : shift_right_result);
	wire is_equal;
	reg is_greater_equal;
	reg cmp_signed;
	always @(*) begin
		cmp_signed = 1'b0;
		case (operator_i)
			ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLET: cmp_signed = 1'b1;
			default:
				;
		endcase
	end
	assign is_equal = adder_result == 32'b00000000000000000000000000000000;
	assign is_equal_result_o = is_equal;
	always @(*)
		if ((operand_a_i[31] ^ operand_b_i[31]) == 1'b0)
			is_greater_equal = adder_result[31] == 1'b0;
		else
			is_greater_equal = operand_a_i[31] ^ cmp_signed;
	reg cmp_result;
	always @(*) begin
		cmp_result = is_equal;
		case (operator_i)
			ibex_defines_ALU_EQ: cmp_result = is_equal;
			ibex_defines_ALU_NE: cmp_result = ~is_equal;
			ibex_defines_ALU_GT, ibex_defines_ALU_GTU: cmp_result = is_greater_equal & ~is_equal;
			ibex_defines_ALU_GE, ibex_defines_ALU_GEU: cmp_result = is_greater_equal;
			ibex_defines_ALU_LT, ibex_defines_ALU_SLT, ibex_defines_ALU_LTU, ibex_defines_ALU_SLTU: cmp_result = ~is_greater_equal;
			ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU, ibex_defines_ALU_LE, ibex_defines_ALU_LEU: cmp_result = ~is_greater_equal | is_equal;
			default:
				;
		endcase
	end
	assign comparison_result_o = cmp_result;
	localparam [4:0] ibex_defines_ALU_ADD = 0;
	localparam [4:0] ibex_defines_ALU_AND = 4;
	localparam [4:0] ibex_defines_ALU_OR = 3;
	localparam [4:0] ibex_defines_ALU_SRL = 6;
	localparam [4:0] ibex_defines_ALU_XOR = 2;
	always @(*) begin
		result_o = {32 {1'sb0}};
		case (operator_i)
			ibex_defines_ALU_AND: result_o = operand_a_i & operand_b_i;
			ibex_defines_ALU_OR: result_o = operand_a_i | operand_b_i;
			ibex_defines_ALU_XOR: result_o = operand_a_i ^ operand_b_i;
			ibex_defines_ALU_ADD, ibex_defines_ALU_SUB: result_o = adder_result;
			ibex_defines_ALU_SLL, ibex_defines_ALU_SRL, ibex_defines_ALU_SRA: result_o = shift_result;
			ibex_defines_ALU_EQ, ibex_defines_ALU_NE, ibex_defines_ALU_GTU, ibex_defines_ALU_GEU, ibex_defines_ALU_LTU, ibex_defines_ALU_LEU, ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLTU, ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU: result_o = {31'h00000000, cmp_result};
			default:
				;
		endcase
	end
endmodule
module ibex_alu (
	operator_i,
	operand_a_i,
	operand_b_i,
	multdiv_operand_a_i,
	multdiv_operand_b_i,
	multdiv_en_i,
	adder_result_o,
	adder_result_ext_o,
	result_o,
	comparison_result_o,
	is_equal_result_o
);

	input wire [4:0] operator_i;
	input wire [31:0] operand_a_i;
	input wire [31:0] operand_b_i;
	input wire [32:0] multdiv_operand_a_i;
	input wire [32:0] multdiv_operand_b_i;
	input wire multdiv_en_i;
	output wire [31:0] adder_result_o;
	output wire [33:0] adder_result_ext_o;
	output reg [31:0] result_o;
	output wire comparison_result_o;
	output wire is_equal_result_o;
	wire [31:0] operand_a_rev;
	wire [32:0] operand_b_neg;
	generate
		genvar k;
		for (k = 0; k < 32; k = k + 1) begin : gen_revloop
			assign operand_a_rev[k] = operand_a_i[31 - k];
		end
	endgenerate
	reg adder_op_b_negate;
	wire [32:0] adder_in_a;
	wire [32:0] adder_in_b;
	wire [31:0] adder_result;
	localparam [4:0] ibex_defines_ALU_EQ = 16;
	localparam [4:0] ibex_defines_ALU_GE = 14;
	localparam [4:0] ibex_defines_ALU_GEU = 15;
	localparam [4:0] ibex_defines_ALU_GT = 12;
	localparam [4:0] ibex_defines_ALU_GTU = 13;
	localparam [4:0] ibex_defines_ALU_LE = 10;
	localparam [4:0] ibex_defines_ALU_LEU = 11;
	localparam [4:0] ibex_defines_ALU_LT = 8;
	localparam [4:0] ibex_defines_ALU_LTU = 9;
	localparam [4:0] ibex_defines_ALU_NE = 17;
	localparam [4:0] ibex_defines_ALU_SLET = 20;
	localparam [4:0] ibex_defines_ALU_SLETU = 21;
	localparam [4:0] ibex_defines_ALU_SLT = 18;
	localparam [4:0] ibex_defines_ALU_SLTU = 19;
	localparam [4:0] ibex_defines_ALU_SUB = 1;
	always @(*) begin
		adder_op_b_negate = 1'b0;
		case (operator_i)
			ibex_defines_ALU_SUB, ibex_defines_ALU_EQ, ibex_defines_ALU_NE, ibex_defines_ALU_GTU, ibex_defines_ALU_GEU, ibex_defines_ALU_LTU, ibex_defines_ALU_LEU, ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLTU, ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU: adder_op_b_negate = 1'b1;
			default:
				;
		endcase
	end
	assign adder_in_a = (multdiv_en_i ? multdiv_operand_a_i : {operand_a_i, 1'b1});
	assign operand_b_neg = {operand_b_i, 1'b0} ^ {33 {adder_op_b_negate}};
	assign adder_in_b = (multdiv_en_i ? multdiv_operand_b_i : operand_b_neg);
	assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
	assign adder_result = adder_result_ext_o[32:1];
	assign adder_result_o = adder_result;
	wire shift_left;
	wire shift_arithmetic;
	wire [4:0] shift_amt;
	wire [31:0] shift_op_a;
	wire [31:0] shift_result;
	wire [31:0] shift_right_result;
	wire [31:0] shift_left_result;
	assign shift_amt = operand_b_i[4:0];
	localparam [4:0] ibex_defines_ALU_SLL = 7;
	assign shift_left = operator_i == ibex_defines_ALU_SLL;
	localparam [4:0] ibex_defines_ALU_SRA = 5;
	assign shift_arithmetic = operator_i == ibex_defines_ALU_SRA;
	assign shift_op_a = (shift_left ? operand_a_rev : operand_a_i);
	wire [32:0] shift_op_a_32;
	assign shift_op_a_32 = {shift_arithmetic & shift_op_a[31], shift_op_a};
	wire signed [32:0] shift_right_result_signed;
	assign shift_right_result_signed = $signed(shift_op_a_32) >>> shift_amt[4:0];
	assign shift_right_result = shift_right_result_signed[31:0];
	generate
		genvar j;
		for (j = 0; j < 32; j = j + 1) begin : gen_resrevloop
			assign shift_left_result[j] = shift_right_result[31 - j];
		end
	endgenerate
	assign shift_result = (shift_left ? shift_left_result : shift_right_result);
	wire is_equal;
	reg is_greater_equal;
	reg cmp_signed;
	always @(*) begin
		cmp_signed = 1'b0;
		case (operator_i)
			ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLET: cmp_signed = 1'b1;
			default:
				;
		endcase
	end
	assign is_equal = adder_result == 32'b00000000000000000000000000000000;
	assign is_equal_result_o = is_equal;
	always @(*)
		if ((operand_a_i[31] ^ operand_b_i[31]) == 1'b0)
			is_greater_equal = adder_result[31] == 1'b0;
		else
			is_greater_equal = operand_a_i[31] ^ cmp_signed;
	reg cmp_result;
	always @(*) begin
		cmp_result = is_equal;
		case (operator_i)
			ibex_defines_ALU_EQ: cmp_result = is_equal;
			ibex_defines_ALU_NE: cmp_result = ~is_equal;
			ibex_defines_ALU_GT, ibex_defines_ALU_GTU: cmp_result = is_greater_equal & ~is_equal;
			ibex_defines_ALU_GE, ibex_defines_ALU_GEU: cmp_result = is_greater_equal;
			ibex_defines_ALU_LT, ibex_defines_ALU_SLT, ibex_defines_ALU_LTU, ibex_defines_ALU_SLTU: cmp_result = ~is_greater_equal;
			ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU, ibex_defines_ALU_LE, ibex_defines_ALU_LEU: cmp_result = ~is_greater_equal | is_equal;
			default:
				;
		endcase
	end
	assign comparison_result_o = cmp_result;
	localparam [4:0] ibex_defines_ALU_ADD = 0;
	localparam [4:0] ibex_defines_ALU_AND = 4;
	localparam [4:0] ibex_defines_ALU_OR = 3;
	localparam [4:0] ibex_defines_ALU_SRL = 6;
	localparam [4:0] ibex_defines_ALU_XOR = 2;
	always @(*) begin
		result_o = {32 {1'sb0}};
		case (operator_i)
			ibex_defines_ALU_AND: result_o = operand_a_i & operand_b_i;
			ibex_defines_ALU_OR: result_o = operand_a_i | operand_b_i;
			ibex_defines_ALU_XOR: result_o = operand_a_i ^ operand_b_i;
			ibex_defines_ALU_ADD, ibex_defines_ALU_SUB: result_o = adder_result;
			ibex_defines_ALU_SLL, ibex_defines_ALU_SRL, ibex_defines_ALU_SRA: result_o = shift_result;
			ibex_defines_ALU_EQ, ibex_defines_ALU_NE, ibex_defines_ALU_GTU, ibex_defines_ALU_GEU, ibex_defines_ALU_LTU, ibex_defines_ALU_LEU, ibex_defines_ALU_GT, ibex_defines_ALU_GE, ibex_defines_ALU_LT, ibex_defines_ALU_LE, ibex_defines_ALU_SLT, ibex_defines_ALU_SLTU, ibex_defines_ALU_SLET, ibex_defines_ALU_SLETU: result_o = {31'h00000000, cmp_result};
			default:
				;
		endcase
	end
endmodule