diff --git a/pipelined/src/ieu/comparator.sv b/pipelined/src/ieu/comparator.sv index bc5a9a288..cc2eb1723 100644 --- a/pipelined/src/ieu/comparator.sv +++ b/pipelined/src/ieu/comparator.sv @@ -71,7 +71,7 @@ module comparator #(parameter WIDTH=64) ( assign flags = {eq, lt, ltu}; endmodule -// This comaprator +// This comaprator is best module comparator_dc_flip #(parameter WIDTH=64) ( input logic [WIDTH-1:0] a, b, input logic sgnd, diff --git a/pipelined/src/ppa/ppa.sv b/pipelined/src/ppa/ppa.sv index de0bac321..f1712d291 100644 --- a/pipelined/src/ppa/ppa.sv +++ b/pipelined/src/ppa/ppa.sv @@ -31,36 +31,318 @@ module ppa_inv(input a, output y); endmodule */ -module ppa_add #(parameter WIDTH=8) ( - input logic [7:0] a, b, - output logic [7:0] y +module ppa_comparator_16 #(parameter WIDTH=16) ( + input logic [WIDTH-1:0] a, b, + input logic sgnd, + output logic [1:0] flags); + + ppa_comparator #(WIDTH) comp (.*); +endmodule + +module ppa_comparator_32 #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] a, b, + input logic sgnd, + output logic [1:0] flags); + + ppa_comparator #(WIDTH) comp (.*); +endmodule + +module ppa_comparator_64 #(parameter WIDTH=64) ( + input logic [WIDTH-1:0] a, b, + input logic sgnd, + output logic [1:0] flags); + + ppa_comparator #(WIDTH) comp (.*); +endmodule + + + module ppa_comparator #(parameter WIDTH=16) ( + input logic [WIDTH-1:0] a, b, + input logic sgnd, + output logic [1:0] flags); + + logic eq, lt, ltu; + logic [WIDTH-1:0] af, bf; + + // For signed numbers, flip most significant bit + assign af = {a[WIDTH-1] ^ sgnd, a[WIDTH-2:0]}; + assign bf = {b[WIDTH-1] ^ sgnd, b[WIDTH-2:0]}; + + // behavioral description gives best results + assign eq = (af == bf); + assign lt = (af < bf); + assign flags = {eq, lt}; +endmodule + + +module ppa_add_32 #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] a, b, + output logic [WIDTH-1:0] y ); - assign out = a + b; + assign y = a + b; +endmodule + +module ppa_add_64 #(parameter WIDTH=64) ( + input logic [WIDTH-1:0] a, b, + output logic [WIDTH-1:0] y +); + + assign y = a + b; endmodule -/*module inv4(input logic a, output logic y); - logic [3:0] b - INVX2 i0(a, b[0]); - INVX2 i1(a, b[1]); - INVX2 i2(a, b[2]); - INVX2 i3(a, b[3]); - INVX2 i00(b[0], y; - INVX2 i01(b[0], y); - INVX2 i02(b[0], y); - INVX2 i03(b[0], y); - INVX2 i10(b[1], y; - INVX2 i11(b[1], y); - INVX2 i12(b[1], y); - INVX2 i13(b[1], y); - INVX2 i20(b[2], y; - INVX2 i21(b[2], y); - INVX2 i22(b[2], y); - INVX2 i23(b[2], y); - INVX2 i30(b[3], y; - INVX2 i31(b[3], y); - INVX2 i32(b[3], y); - INVX2 i33(b[3], y); +module ppa_add_16 #(parameter WIDTH=16) ( + input logic [WIDTH-1:0] a, b, + output logic [WIDTH-1:0] y +); + + assign y = a + b; endmodule -*/ + +module ppa_shiftleft( + assign y = a << amt; +) + +module ppa_mult( + assign y = a * b; +) + +module ppa_alu #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, B, + input logic [2:0] ALUControl, + input logic [2:0] Funct3, + output logic [WIDTH-1:0] Result, + output logic [WIDTH-1:0] Sum); + + logic [WIDTH-1:0] CondInvB, Shift, SLT, SLTU, FullResult; + logic Carry, Neg; + logic LT, LTU; + logic W64, SubArith, ALUOp; + logic [2:0] ALUFunct; + logic Asign, Bsign; + + // Extract control signals + // W64 indicates RV64 W-suffix instructions acting on lower 32-bit word + // SubArith indicates subtraction + // ALUOp = 0 for address generation addition or 1 for regular ALU + assign {W64, SubArith, ALUOp} = ALUControl; + + // addition + assign CondInvB = SubArith ? ~B : B; + assign {Carry, Sum} = A + CondInvB + {{(WIDTH-1){1'b0}}, SubArith}; + + // Shifts + shifter sh(.A, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .Arith(SubArith), .W64, .Y(Shift)); + + // condition code flags based on subtract output Sum = A-B + // Overflow occurs when the numbers being subtracted have the opposite sign + // and the result has the opposite sign of A + assign Neg = Sum[WIDTH-1]; + assign Asign = A[WIDTH-1]; + assign Bsign = B[WIDTH-1]; + assign LT = Asign & ~Bsign | Asign & Neg | ~Bsign & Neg; // simplified from Overflow = Asign & Bsign & Asign & Neg; LT = Neg ^ Overflow + assign LTU = ~Carry; + + // SLT + assign SLT = {{(WIDTH-1){1'b0}}, LT}; + assign SLTU = {{(WIDTH-1){1'b0}}, LTU}; + + // Select appropriate ALU Result + assign ALUFunct = Funct3 & {3{ALUOp}}; // Force ALUFunct to 0 to Add when ALUOp = 0 + always_comb + casez (ALUFunct) + 3'b000: FullResult = Sum; // add or sub + 3'b?01: FullResult = Shift; // sll, sra, or srl + 3'b010: FullResult = SLT; // slt + 3'b011: FullResult = SLTU; // sltu + 3'b100: FullResult = A ^ B; // xor + 3'b110: FullResult = A | B; // or + 3'b111: FullResult = A & B; // and + endcase + + // support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits + if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; + else assign Result = FullResult; +endmodule + + + +module ppa_shifter ( + input logic [`XLEN-1:0] A, + input logic [`LOG_XLEN-1:0] Amt, + input logic Right, Arith, W64, + output logic [`XLEN-1:0] Y); + + logic [2*`XLEN-2:0] z, zshift; + logic [`LOG_XLEN-1:0] amttrunc, offset; + + // Handle left and right shifts with a funnel shifter. + // For RV32, only 32-bit shifts are needed. + // For RV64, 32 and 64-bit shifts are needed, with sign extension. + + // funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong) + if (`XLEN==32) begin:shifter // RV32 + always_comb // funnel mux + if (Right) + if (Arith) z = {{31{A[31]}}, A}; + else z = {31'b0, A}; + else z = {A, 31'b0}; + assign amttrunc = Amt; // shift amount + end else begin:shifter // RV64 + always_comb // funnel mux + if (W64) begin // 32-bit shifts + if (Right) + if (Arith) z = {64'b0, {31{A[31]}}, A[31:0]}; + else z = {95'b0, A[31:0]}; + else z = {32'b0, A[31:0], 63'b0}; + end else begin + if (Right) + if (Arith) z = {{63{A[63]}}, A}; + else z = {63'b0, A}; + else z = {A, 63'b0}; + end + assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift + end + + // opposite offset for right shfits + assign offset = Right ? amttrunc : ~amttrunc; + + // funnel operation + assign zshift = z >> offset; + assign Y = zshift[`XLEN-1:0]; +endmodule + +module ppa_prioritythermometer #(parameter N = 8) ( + input logic [N-1:0] a, + output logic [N-1:0] y +); + +// Carefully crafted so design compiler will synthesize into a fast tree structure +// Rather than linear. + + // create thermometer code mask + genvar i; + assign y[0] = ~a[0]; + for (i=1; i