//	this verilog file dictates the behavior of our processor's ALU.
//based on the value of the ALUOperation, the ALU will either add, subtract, and, or, or invert.

module ALU(DataA, DataB, ALUOperation, DataOut, Overflow);

input [2:0] ALUOperation;
input [15:0] DataA, DataB;		//operands for the ALU operation
output [15:0] DataOut;			   //16-bit output of ALU
output Overflow;
wire [16:0] F0, F1;	//temporary valuyes later to be selected for DataOut
wire OV0, OV1;
wire[15:0] ralph0, ralph1, F2, F3, F4;
		  
//for ALUop = 000, add

//assign F0[15:0] = DataA[15:0] + DataB[15:0];
assign F0[16:0] = DataA[15:0] + DataB[15:0];
assign ralph0[15:0] = DataA[14:0] + DataB[14:0];
assign OV0 = (ralph0[15] ^ F0[16]);

//for ALUop = 001, subtract
//assign F1[15:0] = DataA[15:0] - DataB[15:0];
assign F1[16:0] = DataA[15:0] - DataB[15:0];
assign ralph1[15:0] = DataA[14:0] - DataB[14:0];
assign OV1 = (ralph1[15] ^ F1[16]);

//for ALUop = 010, and
assign F2[15:0] = DataA[15:0] & DataB[15:0];

//for ALUop = 011, or
assign F3[15:0] = DataA[15:0] | DataB[15:0];

//for ALUop = 100, invert
assign F4[15:0] = ~DataA[15:0];

assign DataOut[15:0] =  ((ALUOperation == 0)*(F0[15:0])|(ALUOperation == 1)*(F1[15:0])|(ALUOperation == 2)*(F2)|(ALUOperation == 3)*(F3)|(ALUOperation == 4)*(F4));
assign Overflow = (ALUOperation == 0)*(OV0)|(ALUOperation == 1)*(OV1);

endmodule