/* * ALU. * * AI and BI are 8 bit inputs. Result in OUT. * CI is Carry In. * CO is Carry Out. * * op[3:0] is defined as follows: * * 0011 AI + BI * 0111 AI - BI * 1011 AI + AI * 1100 AI | BI * 1101 AI & BI * 1110 AI ^ BI * 1111 AI * */ module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY ); input clk; input right; input [3:0] op; // operation input [7:0] AI; input [7:0] BI; input CI; input BCD; // BCD style carry output [7:0] OUT; output CO; output V; output Z; output N; output HC; input RDY; reg [7:0] OUT; reg CO; wire V; wire Z; reg N; reg HC; reg AI7; reg BI7; reg [8:0] temp_logic; reg [7:0] temp_BI; reg [4:0] temp_l; reg [4:0] temp_h; wire [8:0] temp = { temp_h, temp_l[3:0] }; wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI; // calculate the logic operations. The 'case' can be done in 1 LUT per // bit. The 'right' shift is a simple mux that can be implemented by // F5MUX. always @* begin case( op[1:0] ) 2'b00: temp_logic = AI | BI; 2'b01: temp_logic = AI & BI; 2'b10: temp_logic = AI ^ BI; 2'b11: temp_logic = AI; endcase if( right ) temp_logic = { AI[0], CI, AI[7:1] }; end // Add logic result to BI input. This only makes sense when logic = AI. // This stage can be done in 1 LUT per bit, using carry chain logic. always @* begin case( op[3:2] ) 2'b00: temp_BI = BI; // A+B 2'b01: temp_BI = ~BI; // A-B 2'b10: temp_BI = temp_logic; // A+A 2'b11: temp_BI = 0; // A+0 endcase end // HC9 is the half carry bit when doing BCD add wire HC9 = BCD & (temp_l[3:1] >= 3'd5); // CO9 is the carry-out bit when doing BCD add wire CO9 = BCD & (temp_h[3:1] >= 3'd5); // combined half carry bit wire temp_HC = temp_l[4] | HC9; // perform the addition as 2 separate nibble, so we get // access to the half carry flag always @* begin temp_l = temp_logic[3:0] + temp_BI[3:0] + adder_CI; temp_h = temp_logic[8:4] + temp_BI[7:4] + temp_HC; end // calculate the flags always @(posedge clk) if( RDY ) begin AI7 <= AI[7]; BI7 <= temp_BI[7]; OUT <= temp[7:0]; CO <= temp[8] | CO9; N <= temp[7]; HC <= temp_HC; end assign V = AI7 ^ BI7 ^ CO ^ N; assign Z = ~|OUT; endmodule