data/full_repos/permissive/130513936/src/hdl/alu.v
data/verilator_xmls/343f331b-3085-414a-a0e9-2199e0ab7327.xml
module alu
#(
	parameter WIDTH = 16
)(
	input signed [WIDTH-1:0] in1,
	input signed [WIDTH-1:0] in2,
	input [2:0] op,

	output signed [WIDTH-1:0] out,
	output [4:0] flags
);

	localparam ALU_OP_ADD = 'b001;
	localparam ALU_OP_SUB = 'b010;
	localparam ALU_OP_MUL = 'b011;
	localparam ALU_OP_AND = 'b100;
	localparam ALU_OP_OR  = 'b101;


	reg signed [WIDTH:0] out_ext;
	wire [WIDTH:0] in1_ext, in2_ext;
	assign in1_ext = {in1[WIDTH-1], in1};
	assign in2_ext = {in2[WIDTH-1], in2};


	reg error;
	reg negative;
	reg zero;
	reg carry;
	reg overflow;

	always @(*) begin
		error = 1'b0;

		case (op)
		ALU_OP_ADD:
			out_ext = in1_ext + in2_ext;
		ALU_OP_SUB:
			out_ext = in1_ext - in2_ext;
		ALU_OP_MUL:
			out_ext = in1_ext * in2_ext;
		ALU_OP_AND:
			out_ext = in1_ext & in2_ext;
		ALU_OP_OR:
			out_ext = in1_ext | in2_ext;
		default: begin
			error = 1'b1;
			out_ext = 'd0;
		end
		endcase
	end


	always @(*) begin
		case (out_ext[WIDTH:WIDTH-1])
		'b00: begin
			carry = 1'b0;
			overflow = 1'b0;
			negative = 1'b0;
		end
		'b01: begin
			carry = 1'b0;
			overflow = 1'b1;
			negative = 1'b1;
		end
		'b10: begin
			carry = 1'b1;

			overflow = 1'b1;
			negative = 1'b0;
		end
		'b11: begin
			carry = 1'b1;
			overflow = 1'b0;
			negative = 1'b1;
		end
		endcase
	end


	always @(*) begin
		if (~error && out_ext == 'd0)
			zero = 1'b1;
		else
			zero = 1'b0;
	end


	assign out = out_ext[WIDTH-1:0];
	assign flags = {error, negative, zero, carry, overflow};

endmodule
module alu
#(
	parameter WIDTH = 16
)(
	input signed [WIDTH-1:0] in1,
	input signed [WIDTH-1:0] in2,
	input [2:0] op,

	output signed [WIDTH-1:0] out,
	output [4:0] flags
);


	localparam ALU_OP_ADD = 'b001;
	localparam ALU_OP_SUB = 'b010;
	localparam ALU_OP_MUL = 'b011;
	localparam ALU_OP_AND = 'b100;
	localparam ALU_OP_OR  = 'b101;


	reg signed [WIDTH:0] out_ext;
	wire [WIDTH:0] in1_ext, in2_ext;
	assign in1_ext = {in1[WIDTH-1], in1};
	assign in2_ext = {in2[WIDTH-1], in2};


	reg error;
	reg negative;
	reg zero;
	reg carry;
	reg overflow;

	always @(*) begin
		error = 1'b0;

		case (op)
		ALU_OP_ADD:
			out_ext = in1_ext + in2_ext;
		ALU_OP_SUB:
			out_ext = in1_ext - in2_ext;
		ALU_OP_MUL:
			out_ext = in1_ext * in2_ext;
		ALU_OP_AND:
			out_ext = in1_ext & in2_ext;
		ALU_OP_OR:
			out_ext = in1_ext | in2_ext;
		default: begin
			error = 1'b1;
			out_ext = 'd0;
		end
		endcase
	end


	always @(*) begin
		case (out_ext[WIDTH:WIDTH-1])
		'b00: begin
			carry = 1'b0;
			overflow = 1'b0;
			negative = 1'b0;
		end
		'b01: begin
			carry = 1'b0;
			overflow = 1'b1;
			negative = 1'b1;
		end
		'b10: begin
			carry = 1'b1;

			overflow = 1'b1;
			negative = 1'b0;
		end
		'b11: begin
			carry = 1'b1;
			overflow = 1'b0;
			negative = 1'b1;
		end
		endcase
	end


	always @(*) begin
		if (~error && out_ext == 'd0)
			zero = 1'b1;
		else
			zero = 1'b0;
	end


	assign out = out_ext[WIDTH-1:0];
	assign flags = {error, negative, zero, carry, overflow};

endmodule