MDU comment cleanup

This commit is contained in:
David Harris 2023-01-12 07:15:14 -08:00
parent e67f125201
commit b3e1badd31
4 changed files with 121 additions and 111 deletions

View File

@ -6,6 +6,8 @@
// //
// Purpose: Restoring integer division using a shift register and subtractor // Purpose: Restoring integer division using a shift register and subtractor
// //
// Documentation: RISC-V System on Chip Design Chapter 12 (Figure 12.19)
//
// A component of the CORE-V-WALLY configurable RISC-V project. // A component of the CORE-V-WALLY configurable RISC-V project.
// //
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
@ -26,32 +28,39 @@
`include "wally-config.vh" `include "wally-config.vh"
/* verilator lint_off UNOPTFLAT */ module intdivrestoring(
module intdivrestoring (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallM, input logic StallM,
input logic FlushE, input logic FlushE,
input logic DivSignedE, W64E, input logic IntDivE, // integer division/remainder instruction of any type
input logic IntDivE, input logic DivSignedE, // signed division
//input logic [`XLEN-1:0] SrcAE, SrcBE, input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Forwarding mux outputs for Source A and B
output logic DivBusyE, output logic DivBusyE, // Divide is busy - stall pipeline
output logic [`XLEN-1:0] QuotM, RemM output logic [`XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
); );
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; localparam STEPBITS = $clog2(`XLEN/`IDIV_BITSPERCYCLE); // Number of steps
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; // division FSM state
statetype state; statetype state;
logic [`XLEN-1:0] W[`IDIV_BITSPERCYCLE:0]; logic [`XLEN-1:0] W[`IDIV_BITSPERCYCLE:0]; // Residual for each of k steps
logic [`XLEN-1:0] XQ[`IDIV_BITSPERCYCLE:0]; logic [`XLEN-1:0] XQ[`IDIV_BITSPERCYCLE:0]; // dividend/quotient for each of k steps
logic [`XLEN-1:0] DinE, XinE, DnE, DAbsBE, DAbsB, XnE, XInitE, WnM, XQnM; logic [`XLEN-1:0] WNext, XQNext; // initialized W and XQ going into registers
localparam STEPBITS = $clog2(`XLEN/`IDIV_BITSPERCYCLE); logic [`XLEN-1:0] DinE, XinE; // divisor & dividend, possibly truncated to 32 bits
logic [STEPBITS:0] step; logic [`XLEN-1:0] DnE; // DnE = ~DinE
logic Div0E, Div0M; logic [`XLEN-1:0] DAbsBE; // absolute value of D
logic DivStartE, SignXE, SignDE, NegQE, NegWM, NegQM; logic [`XLEN-1:0] DAbsB; // registered absolute value of D, constant during division
logic [`XLEN-1:0] WNext, XQNext; logic [`XLEN-1:0] XnE; // DXnE = ~XinE
logic [`XLEN-1:0] XInitE; // |X|, or original X for divide by 0
logic [`XLEN-1:0] WnM, XQnM; // negated residual W and quotient XQ for postprocessing sign correction
logic [STEPBITS:0] step; // division step
logic Div0E, Div0M; // divide by 0
logic DivStartE; // start integer division
logic SignXE, SignDE; // sign of dividend and divisor
logic NegQE, NegWM, NegQM; // negate quotient or residual during postprocessing
////////////////////////////// //////////////////////////////
// Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ // Execute Stage: prepare for division calculation with control logic, W logic and absolute values, initialize W and XQ
@ -134,5 +143,3 @@ module intdivrestoring (
else state <= IDLE; else state <= IDLE;
end end
endmodule endmodule
/* verilator lint_on UNOPTFLAT */

View File

@ -4,7 +4,9 @@
// Written: David_Harris@hmc.edu 2 October 2021 // Written: David_Harris@hmc.edu 2 October 2021
// Modified: // Modified:
// //
// Purpose: Restoring integer division using a shift register and subtractor // Purpose: Restoring integer division step. k steps are used in intdivrestoring
//
// Documentation: RISC-V System on Chip Design Chapter 12 (Figure 12.19)
// //
// A component of the CORE-V-WALLY configurable RISC-V project. // A component of the CORE-V-WALLY configurable RISC-V project.
// //
@ -29,11 +31,16 @@
/* verilator lint_off UNOPTFLAT */ /* verilator lint_off UNOPTFLAT */
module intdivrestoringstep( module intdivrestoringstep(
input logic [`XLEN-1:0] W, XQ, DAbsB, input logic [`XLEN-1:0] W, // Residual in
output logic [`XLEN-1:0] WOut, XQOut); input logic [`XLEN-1:0] XQ, // bits of dividend X and quotient Q in
input logic [`XLEN-1:0] DAbsB, // complement of absolute value of divisor D (for subtraction)
output logic [`XLEN-1:0] WOut, // Residual out
output logic [`XLEN-1:0] XQOut // bits of dividend and quotient out: discard one bit of X, append one bit of Q
);
logic [`XLEN-1:0] WShift, WPrime; logic [`XLEN-1:0] WShift; // Shift W left by one bit, bringing in most significant bit of X
logic qi, qib; logic [`XLEN-1:0] WPrime; // WShift - D, for comparison and possible result
logic qi, qib; // Quotient digit and its complement
assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi}; // shift W and X/Q left, insert quotient bit at bottom assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi}; // shift W and X/Q left, insert quotient bit at bottom
adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime}); // effective subtractor, carry out determines quotient bit adder #(`XLEN+1) wdsub({1'b0, WShift}, {1'b1, DAbsB}, {qib, WPrime}); // effective subtractor, carry out determines quotient bit

View File

@ -6,6 +6,8 @@
// //
// Purpose: M extension multiply and divide // Purpose: M extension multiply and divide
// //
// Documentation: RISC-V System on Chip Design Chapter 12 (Figure 12.21)
//
// A component of the CORE-V-WALLY configurable RISC-V project. // A component of the CORE-V-WALLY configurable RISC-V project.
// //
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
@ -26,56 +28,49 @@
`include "wally-config.vh" `include "wally-config.vh"
module mdu ( module mdu(
input logic clk, reset, input logic clk, reset,
// Execute Stage interface input logic StallM, StallW,
// input logic [`XLEN-1:0] SrcAE, SrcBE, input logic FlushE, FlushM, FlushW,
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
input logic [2:0] Funct3E, Funct3M, input logic [2:0] Funct3E, Funct3M, // type of MDU operation
input logic IntDivE, W64E, input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
// Writeback stage output logic [`XLEN-1:0] MDUResultW, // multiply/divide result
output logic [`XLEN-1:0] MDUResultW, output logic DivBusyE // busy signal to stall pipeline in Execute stage
// Divide Done );
output logic DivBusyE,
// hazards
input logic StallM, StallW, FlushE, FlushM, FlushW
);
logic [`XLEN-1:0] MDUResultM; logic [`XLEN*2-1:0] ProdM; // double-width product from mul
logic [`XLEN-1:0] PrelimResultM; logic [`XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
logic [`XLEN-1:0] QuotM, RemM; logic [`XLEN-1:0] PrelimResultM; // selected result before W truncation
logic [`XLEN*2-1:0] ProdM; logic [`XLEN-1:0] MDUResultM; // result after W truncation
logic W64M; // W-type instruction
logic DivSignedE;
logic W64M;
// Multiplier // Multiplier
mul mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM); mul mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
// Divide // Divider
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing // Start a divide when a new division instruction is received and the divider isn't already busy or finishing
// When F extensions are supported, use the FPU divider instead // When IDIV_ON_FPU is set, use the FPU divider instead
if (`IDIV_ON_FPU) begin if (`IDIV_ON_FPU) begin
assign QuotM = 0; assign QuotM = 0;
assign RemM = 0; assign RemM = 0;
assign DivBusyE = 0; assign DivBusyE = 0;
end else begin end else begin
assign DivSignedE = ~Funct3E[0]; intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,
intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE, .W64E, .IntDivE,
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM); .ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
end end
// Result multiplexer // Result multiplexer
always_comb always_comb
case (Funct3M) case (Funct3M)
3'b000: PrelimResultM = ProdM[`XLEN-1:0]; 3'b000: PrelimResultM = ProdM[`XLEN-1:0]; // mul
3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; 3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulh
3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; 3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhsu
3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; 3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhu
3'b100: PrelimResultM = QuotM; 3'b100: PrelimResultM = QuotM; // div
3'b101: PrelimResultM = QuotM; 3'b101: PrelimResultM = QuotM; // divu
3'b110: PrelimResultM = RemM; 3'b110: PrelimResultM = RemM; // rem
3'b111: PrelimResultM = RemM; 3'b111: PrelimResultM = RemM; // remu
endcase endcase
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions

View File

@ -4,7 +4,9 @@
// Written: David_Harris@hmc.edu 16 February 2021 // Written: David_Harris@hmc.edu 16 February 2021
// Modified: // Modified:
// //
// Purpose: Multiply instructions // Purpose: Integer multiplication
//
// Documentation: RISC-V System on Chip Design Chapter 12 (Figure 12.18)
// //
// A component of the CORE-V-WALLY configurable RISC-V project. // A component of the CORE-V-WALLY configurable RISC-V project.
// //
@ -26,14 +28,12 @@
`include "wally-config.vh" `include "wally-config.vh"
module mul ( module mul(
// Execute Stage interface
input logic clk, reset, input logic clk, reset,
input logic StallM, FlushM, input logic StallM, FlushM,
// input logic [`XLEN-1:0] SrcAE, SrcBE, input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // source A and B from after Forwarding mux
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B input logic [2:0] Funct3E, // type of multiply
input logic [2:0] Funct3E, output logic [`XLEN*2-1:0] ProdM // double-widthproduct
output logic [`XLEN*2-1:0] ProdM
); );
// Number systems // Number systems
@ -50,12 +50,12 @@ module mul (
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2) // Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2) // Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; logic [`XLEN-1:0] Aprime, Bprime; // lower bits of source A and B
logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; logic MULH, MULHSU; // type of multiply
logic [`XLEN-2:0] PA, PB; logic [`XLEN-2:0] PA, PB; // product of msb and lsbs
logic PP; logic PP; // product of msbs
logic MULH, MULHSU; logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E; // partial products
logic [`XLEN-1:0] Aprime, Bprime; logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M; // registered partial proudcts
////////////////////////////// //////////////////////////////
// Execute Stage: Compute partial products // Execute Stage: Compute partial products
@ -72,7 +72,7 @@ module mul (
assign MULH = (Funct3E == 3'b001); assign MULH = (Funct3E == 3'b001);
assign MULHSU = (Funct3E == 3'b010); assign MULHSU = (Funct3E == 3'b010);
// Handle signs // Select partial products, handling signed multiplication
assign PP2E = {2'b00, (MULH | MULHSU) ? ~PA : PA, {(`XLEN-1){1'b0}}}; assign PP2E = {2'b00, (MULH | MULHSU) ? ~PA : PA, {(`XLEN-1){1'b0}}};
assign PP3E = {2'b00, (MULH) ? ~PB : PB, {(`XLEN-1){1'b0}}}; assign PP3E = {2'b00, (MULH) ? ~PB : PB, {(`XLEN-1){1'b0}}};
always_comb always_comb
@ -89,6 +89,7 @@ module mul (
flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M); flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M);
flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M); flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M);
// add up partial products; this multi-input add implies CSAs and a final CPA
assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE; assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
endmodule endmodule