OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mips32r1/trunk/Hardware
    from Rev 9 to Rev 10
    Reverse comparison

Rev 9 → Rev 10

/XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Processor.v
96,7 → 96,7
wire ID_IsFlushed;
 
/*** EX (Execute) Signals ***/
wire EX_Stall;
wire EX_ALU_Stall, EX_Stall;
wire [1:0] EX_RsFwdSel, EX_RtFwdSel;
wire EX_Link;
wire [1:0] EX_LinkRegDst;
245,6 → 245,7
.IF_Exception_Stall (IF_Exception_Stall),
.ID_Exception_Stall (ID_Exception_Stall),
.EX_Exception_Stall (EX_Exception_Stall),
.EX_ALU_Stall (EX_ALU_Stall),
.M_Stall_Controller (M_Stall_Controller),
.IF_Stall (IF_Stall),
.ID_Stall (ID_Stall),
533,17 → 534,18
 
/*** Arithmetic Logic Unit ***/
ALU ALU (
.clock (clock),
.reset (reset),
.EX_Stall (EX_Stall),
.EX_Flush (EX_Exception_Flush),
.A (EX_ReadData1_Fwd),
.B (EX_ReadData2_Imm),
.Operation (EX_ALUOp),
.Shamt (EX_Shamt),
.Result (EX_ALUResult),
.BZero (EX_BZero),
.EXC_Ov (EX_EXC_Ov)
.clock (clock),
.reset (reset),
.EX_Stall (EX_Stall),
.EX_Flush (EX_Exception_Flush),
.A (EX_ReadData1_Fwd),
.B (EX_ReadData2_Imm),
.Operation (EX_ALUOp),
.Shamt (EX_Shamt),
.Result (EX_ALUResult),
.BZero (EX_BZero),
.EXC_Ov (EX_EXC_Ov),
.ALU_Stall (EX_ALU_Stall)
);
 
/*** Execute -> Memory Pipeline Stage ***/
/XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/ALU.v
27,8 → 27,9
input [4:0] Operation,
input signed [4:0] Shamt,
output reg signed [31:0] Result,
output BZero, // Used for Movc
output reg EXC_Ov
output BZero, // Used for Movc
output reg EXC_Ov,
output ALU_Stall // Stalls due to long ALU operations
);
 
`include "MIPS_Parameters.v"
42,24 → 43,55
the speed of arithmetic operations. The ALU could also be placed in a separate
pipeline stage after the Execute forwarding has completed.
***/
/***
Divider Logic:
The hardware divider requires 32 cycles to complete. Because it writes its
results to HILO and not to the pipeline, the pipeline can proceed without
stalling. When a later instruction tries to access HILO, the pipeline will
stall if the divide operation has not yet completed.
***/
// Internal state registers
reg [63:0] HILO;
reg HILO_Access; // Behavioral; not DFFs
reg [5:0] CLO_Result, CLZ_Result; // Behavioral; not DFFs
reg div_fsm;
// Internal signals
wire [31:0] HI, LO;
wire HILO_Commit;
wire signed [31:0] As, Bs;
wire AddSub_Add;
wire signed [31:0] AddSub_Result;
wire signed [63:0] Mult_Result;
wire [63:0] Multu_Result;
wire [31:0] Quotient;
wire [31:0] Remainder;
wire Div_Stall;
wire Div_Start, Divu_Start;
wire DivOp;
wire Div_Commit;
wire signed [31:0] As = A;
wire signed [31:0] Bs = B;
reg [63:0] HILO;
wire [31:0] HI = HILO[63:32];
wire [31:0] LO = HILO[31:0];
wire HILO_Commit = ~(EX_Stall | EX_Flush);
wire AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
wire signed [31:0] AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
wire signed [63:0] Mult_Result = As * Bs;
wire [63:0] Multu_Result = A * B;
reg [5:0] CLO_Result, CLZ_Result;
// Assignments
assign HI = HILO[63:32];
assign LO = HILO[31:0];
assign HILO_Commit = ~(EX_Stall | EX_Flush);
assign As = A;
assign Bs = B;
assign AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
assign AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
assign Mult_Result = As * Bs;
assign Multu_Result = A * B;
assign BZero = (B == 32'h00000000);
assign DivOp = (Operation == AluOp_Div) || (Operation == AluOp_Divu);
assign Div_Commit = (div_fsm == 1'b1) && (Div_Stall == 1'b0);
assign Div_Start = (div_fsm == 1'b0) && (Operation == AluOp_Div) && (HILO_Commit == 1'b1);
assign Divu_Start = (div_fsm == 1'b0) && (Operation == AluOp_Divu) && (HILO_Commit == 1'b1);
assign ALU_Stall = (div_fsm == 1'b1) && (HILO_Access == 1'b1);
always @(*) begin
case (Operation)
68,8 → 100,6
AluOp_And : Result <= A & B;
AluOp_Clo : Result <= {26'b0, CLO_Result};
AluOp_Clz : Result <= {26'b0, CLZ_Result};
AluOp_Div : Result <= 32'hdeafbeef; // XXX implement division
AluOp_Divu : Result <= 32'hdeadbeef; // XXX implement division
AluOp_Mfhi : Result <= HI;
AluOp_Mflo : Result <= LO;
AluOp_Mul : Result <= Mult_Result[31:0];
95,6 → 125,9
always @(posedge clock) begin
if (reset) begin
HILO <= 64'h00000000_00000000;
end
else if (Div_Commit) begin
HILO <= {Remainder, Quotient};
end
else if (HILO_Commit) begin
case (Operation)
112,6 → 145,42
else begin
HILO <= HILO;
end
end
// Detect accesses to HILO. RAW and WAW hazards are possible while a
// divide operation is computing, so reads and writes to HILO must stall
// while the divider is busy.
// (This logic could be put into an earlier pipeline stage or into the
// datapath bits to improve timing.)
always @(Operation) begin
case (Operation)
AluOp_Div : HILO_Access <= 1;
AluOp_Divu : HILO_Access <= 1;
AluOp_Mfhi : HILO_Access <= 1;
AluOp_Mflo : HILO_Access <= 1;
AluOp_Mult : HILO_Access <= 1;
AluOp_Multu : HILO_Access <= 1;
AluOp_Madd : HILO_Access <= 1;
AluOp_Maddu : HILO_Access <= 1;
AluOp_Msub : HILO_Access <= 1;
AluOp_Msubu : HILO_Access <= 1;
AluOp_Mthi : HILO_Access <= 1;
AluOp_Mtlo : HILO_Access <= 1;
default : HILO_Access <= 0;
endcase
end
// Divider FSM: The divide unit is either available or busy.
always @(posedge clock) begin
if (reset) begin
div_fsm <= 2'd0;
end
else begin
case (div_fsm)
1'd0 : div_fsm <= (DivOp & HILO_Commit) ? 1'd1 : 1'd0;
1'd1 : div_fsm <= (~Div_Stall) ? 1'd0 : 1'd1;
endcase
end
end
// Detect overflow for signed operations. Note that MIPS32 has no overflow
124,7 → 193,6
endcase
end
// Count Leading Ones
always @(A) begin
casex (A)
203,7 → 271,20
32'b0000_0000_0000_0000_0000_0000_0000_0000 : CLZ_Result <= 6'd32;
default : CLZ_Result <= 6'd0;
endcase
end
end
 
// Multicycle divide unit
Divide Divider (
.clock (clock),
.reset (reset),
.OP_div (Div_Start),
.OP_divu (Divu_Start),
.Dividend (A),
.Divisor (B),
.Quotient (Quotient),
.Remainder (Remainder),
.Stall (Div_Stall)
);
 
endmodule
 
/XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/CPZero.v
524,6 → 524,6
else if (EXC_Int) Cause_ExcCode_bits <= 4'h0; // 00000 // OK that NMI writes this.
else Cause_ExcCode_bits <= 4'bxxxx;
end
endmodule
 
/XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Divide.v
0,0 → 1,100
`timescale 1ns / 1ns
/*
* File : Divide.v
* Project : University of Utah, XUM Project MIPS32 core
* Creator(s) : Neil Russell
*
* Modification History:
* Rev Date Initials Description of Change
* 1.0 6-Nov-2012 NJR Initial design.
*
* Description:
* A multi-cycle 32-bit divider.
*
* On any cycle that one of OP_div or OP_divu are true, the Dividend and
* Divisor will be captured and a multi-cycle divide operation initiated.
* Stall will go true on the next cycle and the first cycle of the divide
* operation completed. After some time (about 32 cycles), Stall will go
* false on the same cycle that the result becomes valid. OP_div or OP_divu
* will abort any currently running divide operation and initiate a new one.
*/
module Divide(
input clock,
input reset,
input OP_div, // True to initiate a signed divide
input OP_divu, // True to initiate an unsigned divide
input [31:0] Dividend,
input [31:0] Divisor,
output [31:0] Quotient,
output [31:0] Remainder,
output Stall // True while calculating
);
 
 
reg active; // True if the divider is running
reg neg; // True if the result will be negative
reg [4:0] cycle; // Number of cycles to go
 
reg [31:0] result; // Begin with dividend, end with quotient
reg [31:0] denom; // Divisor
reg [31:0] work; // Running remainder
 
// Calculate the current digit
wire [32:0] sub = { work[30:0], result[31] } - denom;
 
// Send the results to our master
assign Quotient = !neg ? result : -result;
assign Remainder = work;
assign Stall = active;
 
// The state machine
always @(posedge clock) begin
if (reset) begin
active <= 0;
neg <= 0;
cycle <= 0;
result <= 0;
denom <= 0;
work <= 0;
end
else begin
if (OP_div) begin
// Set up for a signed divide. Remember the resulting sign,
// and make the operands positive.
cycle <= 5'd31;
result <= (Dividend[31] == 0) ? Dividend : -Dividend;
denom <= (Divisor[31] == 0) ? Divisor : -Divisor;
work <= 32'b0;
neg <= Dividend[31] ^ Divisor[31];
active <= 1;
end
else if (OP_divu) begin
// Set up for an unsigned divide.
cycle <= 5'd31;
result <= Dividend;
denom <= Divisor;
work <= 32'b0;
neg <= 0;
active <= 1;
end
else if (active) begin
// Run an iteration of the divide.
if (sub[32] == 0) begin
work <= sub[31:0];
result <= {result[30:0], 1'b1};
end
else begin
work <= {work[30:0], result[31]};
result <= {result[30:0], 1'b0};
end
 
if (cycle == 0) begin
active <= 0;
end
 
cycle <= cycle - 5'd1;
end
end
end
 
endmodule
XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Divide.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Hazard_Detection.v =================================================================== --- XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Hazard_Detection.v (revision 9) +++ XUPV5-LX110T_SoC/MIPS32-Pipelined-Hw/src/MIPS32/Hazard_Detection.v (revision 10) @@ -43,6 +43,7 @@ input IF_Exception_Stall, input ID_Exception_Stall, input EX_Exception_Stall, + input EX_ALU_Stall, input M_Stall_Controller, // Determined by data memory controller output IF_Stall, output ID_Stall, @@ -159,7 +160,7 @@ // Stalls and Control Flow Final Assignments assign WB_Stall = M_Stall; assign M_Stall = IF_Stall | M_Stall_Controller; - assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | M_Stall; + assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | EX_ALU_Stall | M_Stall; assign ID_Stall = (ID_Stall_1 | ID_Stall_2 | ID_Stall_3 | ID_Stall_4 | ID_Exception_Stall) | EX_Stall; assign IF_Stall = InstMem_Read | InstMem_Ready | IF_Exception_Stall;
/MIPS32_Standalone/Processor.v
96,7 → 96,7
wire ID_IsFlushed;
 
/*** EX (Execute) Signals ***/
wire EX_Stall;
wire EX_ALU_Stall, EX_Stall;
wire [1:0] EX_RsFwdSel, EX_RtFwdSel;
wire EX_Link;
wire [1:0] EX_LinkRegDst;
245,6 → 245,7
.IF_Exception_Stall (IF_Exception_Stall),
.ID_Exception_Stall (ID_Exception_Stall),
.EX_Exception_Stall (EX_Exception_Stall),
.EX_ALU_Stall (EX_ALU_Stall),
.M_Stall_Controller (M_Stall_Controller),
.IF_Stall (IF_Stall),
.ID_Stall (ID_Stall),
533,17 → 534,18
 
/*** Arithmetic Logic Unit ***/
ALU ALU (
.clock (clock),
.reset (reset),
.EX_Stall (EX_Stall),
.EX_Flush (EX_Exception_Flush),
.A (EX_ReadData1_Fwd),
.B (EX_ReadData2_Imm),
.Operation (EX_ALUOp),
.Shamt (EX_Shamt),
.Result (EX_ALUResult),
.BZero (EX_BZero),
.EXC_Ov (EX_EXC_Ov)
.clock (clock),
.reset (reset),
.EX_Stall (EX_Stall),
.EX_Flush (EX_Exception_Flush),
.A (EX_ReadData1_Fwd),
.B (EX_ReadData2_Imm),
.Operation (EX_ALUOp),
.Shamt (EX_Shamt),
.Result (EX_ALUResult),
.BZero (EX_BZero),
.EXC_Ov (EX_EXC_Ov),
.ALU_Stall (EX_ALU_Stall)
);
 
/*** Execute -> Memory Pipeline Stage ***/
/MIPS32_Standalone/ALU.v
27,8 → 27,9
input [4:0] Operation,
input signed [4:0] Shamt,
output reg signed [31:0] Result,
output BZero, // Used for Movc
output reg EXC_Ov
output BZero, // Used for Movc
output reg EXC_Ov,
output ALU_Stall // Stalls due to long ALU operations
);
 
`include "MIPS_Parameters.v"
42,24 → 43,55
the speed of arithmetic operations. The ALU could also be placed in a separate
pipeline stage after the Execute forwarding has completed.
***/
/***
Divider Logic:
The hardware divider requires 32 cycles to complete. Because it writes its
results to HILO and not to the pipeline, the pipeline can proceed without
stalling. When a later instruction tries to access HILO, the pipeline will
stall if the divide operation has not yet completed.
***/
// Internal state registers
reg [63:0] HILO;
reg HILO_Access; // Behavioral; not DFFs
reg [5:0] CLO_Result, CLZ_Result; // Behavioral; not DFFs
reg div_fsm;
// Internal signals
wire [31:0] HI, LO;
wire HILO_Commit;
wire signed [31:0] As, Bs;
wire AddSub_Add;
wire signed [31:0] AddSub_Result;
wire signed [63:0] Mult_Result;
wire [63:0] Multu_Result;
wire [31:0] Quotient;
wire [31:0] Remainder;
wire Div_Stall;
wire Div_Start, Divu_Start;
wire DivOp;
wire Div_Commit;
wire signed [31:0] As = A;
wire signed [31:0] Bs = B;
reg [63:0] HILO;
wire [31:0] HI = HILO[63:32];
wire [31:0] LO = HILO[31:0];
wire HILO_Commit = ~(EX_Stall | EX_Flush);
wire AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
wire signed [31:0] AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
wire signed [63:0] Mult_Result = As * Bs;
wire [63:0] Multu_Result = A * B;
reg [5:0] CLO_Result, CLZ_Result;
// Assignments
assign HI = HILO[63:32];
assign LO = HILO[31:0];
assign HILO_Commit = ~(EX_Stall | EX_Flush);
assign As = A;
assign Bs = B;
assign AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
assign AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
assign Mult_Result = As * Bs;
assign Multu_Result = A * B;
assign BZero = (B == 32'h00000000);
assign DivOp = (Operation == AluOp_Div) || (Operation == AluOp_Divu);
assign Div_Commit = (div_fsm == 1'b1) && (Div_Stall == 1'b0);
assign Div_Start = (div_fsm == 1'b0) && (Operation == AluOp_Div) && (HILO_Commit == 1'b1);
assign Divu_Start = (div_fsm == 1'b0) && (Operation == AluOp_Divu) && (HILO_Commit == 1'b1);
assign ALU_Stall = (div_fsm == 1'b1) && (HILO_Access == 1'b1);
always @(*) begin
case (Operation)
68,8 → 100,6
AluOp_And : Result <= A & B;
AluOp_Clo : Result <= {26'b0, CLO_Result};
AluOp_Clz : Result <= {26'b0, CLZ_Result};
AluOp_Div : Result <= 32'hdeafbeef; // XXX implement division
AluOp_Divu : Result <= 32'hdeadbeef; // XXX implement division
AluOp_Mfhi : Result <= HI;
AluOp_Mflo : Result <= LO;
AluOp_Mul : Result <= Mult_Result[31:0];
95,6 → 125,9
always @(posedge clock) begin
if (reset) begin
HILO <= 64'h00000000_00000000;
end
else if (Div_Commit) begin
HILO <= {Remainder, Quotient};
end
else if (HILO_Commit) begin
case (Operation)
112,6 → 145,42
else begin
HILO <= HILO;
end
end
// Detect accesses to HILO. RAW and WAW hazards are possible while a
// divide operation is computing, so reads and writes to HILO must stall
// while the divider is busy.
// (This logic could be put into an earlier pipeline stage or into the
// datapath bits to improve timing.)
always @(Operation) begin
case (Operation)
AluOp_Div : HILO_Access <= 1;
AluOp_Divu : HILO_Access <= 1;
AluOp_Mfhi : HILO_Access <= 1;
AluOp_Mflo : HILO_Access <= 1;
AluOp_Mult : HILO_Access <= 1;
AluOp_Multu : HILO_Access <= 1;
AluOp_Madd : HILO_Access <= 1;
AluOp_Maddu : HILO_Access <= 1;
AluOp_Msub : HILO_Access <= 1;
AluOp_Msubu : HILO_Access <= 1;
AluOp_Mthi : HILO_Access <= 1;
AluOp_Mtlo : HILO_Access <= 1;
default : HILO_Access <= 0;
endcase
end
// Divider FSM: The divide unit is either available or busy.
always @(posedge clock) begin
if (reset) begin
div_fsm <= 2'd0;
end
else begin
case (div_fsm)
1'd0 : div_fsm <= (DivOp & HILO_Commit) ? 1'd1 : 1'd0;
1'd1 : div_fsm <= (~Div_Stall) ? 1'd0 : 1'd1;
endcase
end
end
// Detect overflow for signed operations. Note that MIPS32 has no overflow
124,7 → 193,6
endcase
end
// Count Leading Ones
always @(A) begin
casex (A)
203,6 → 271,20
32'b0000_0000_0000_0000_0000_0000_0000_0000 : CLZ_Result <= 6'd32;
default : CLZ_Result <= 6'd0;
endcase
end
end
 
// Multicycle divide unit
Divide Divider (
.clock (clock),
.reset (reset),
.OP_div (Div_Start),
.OP_divu (Divu_Start),
.Dividend (A),
.Divisor (B),
.Quotient (Quotient),
.Remainder (Remainder),
.Stall (Div_Stall)
);
 
endmodule
 
/MIPS32_Standalone/Divide.v
0,0 → 1,100
`timescale 1ns / 1ns
/*
* File : Divide.v
* Project : University of Utah, XUM Project MIPS32 core
* Creator(s) : Neil Russell
*
* Modification History:
* Rev Date Initials Description of Change
* 1.0 6-Nov-2012 NJR Initial design.
*
* Description:
* A multi-cycle 32-bit divider.
*
* On any cycle that one of OP_div or OP_divu are true, the Dividend and
* Divisor will be captured and a multi-cycle divide operation initiated.
* Stall will go true on the next cycle and the first cycle of the divide
* operation completed. After some time (about 32 cycles), Stall will go
* false on the same cycle that the result becomes valid. OP_div or OP_divu
* will abort any currently running divide operation and initiate a new one.
*/
module Divide(
input clock,
input reset,
input OP_div, // True to initiate a signed divide
input OP_divu, // True to initiate an unsigned divide
input [31:0] Dividend,
input [31:0] Divisor,
output [31:0] Quotient,
output [31:0] Remainder,
output Stall // True while calculating
);
 
 
reg active; // True if the divider is running
reg neg; // True if the result will be negative
reg [4:0] cycle; // Number of cycles to go
 
reg [31:0] result; // Begin with dividend, end with quotient
reg [31:0] denom; // Divisor
reg [31:0] work; // Running remainder
 
// Calculate the current digit
wire [32:0] sub = { work[30:0], result[31] } - denom;
 
// Send the results to our master
assign Quotient = !neg ? result : -result;
assign Remainder = work;
assign Stall = active;
 
// The state machine
always @(posedge clock) begin
if (reset) begin
active <= 0;
neg <= 0;
cycle <= 0;
result <= 0;
denom <= 0;
work <= 0;
end
else begin
if (OP_div) begin
// Set up for a signed divide. Remember the resulting sign,
// and make the operands positive.
cycle <= 5'd31;
result <= (Dividend[31] == 0) ? Dividend : -Dividend;
denom <= (Divisor[31] == 0) ? Divisor : -Divisor;
work <= 32'b0;
neg <= Dividend[31] ^ Divisor[31];
active <= 1;
end
else if (OP_divu) begin
// Set up for an unsigned divide.
cycle <= 5'd31;
result <= Dividend;
denom <= Divisor;
work <= 32'b0;
neg <= 0;
active <= 1;
end
else if (active) begin
// Run an iteration of the divide.
if (sub[32] == 0) begin
work <= sub[31:0];
result <= {result[30:0], 1'b1};
end
else begin
work <= {work[30:0], result[31]};
result <= {result[30:0], 1'b0};
end
 
if (cycle == 0) begin
active <= 0;
end
 
cycle <= cycle - 5'd1;
end
end
end
 
endmodule
MIPS32_Standalone/Divide.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: MIPS32_Standalone/Hazard_Detection.v =================================================================== --- MIPS32_Standalone/Hazard_Detection.v (revision 9) +++ MIPS32_Standalone/Hazard_Detection.v (revision 10) @@ -43,6 +43,7 @@ input IF_Exception_Stall, input ID_Exception_Stall, input EX_Exception_Stall, + input EX_ALU_Stall, input M_Stall_Controller, // Determined by data memory controller output IF_Stall, output ID_Stall, @@ -159,7 +160,7 @@ // Stalls and Control Flow Final Assignments assign WB_Stall = M_Stall; assign M_Stall = IF_Stall | M_Stall_Controller; - assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | M_Stall; + assign EX_Stall = (EX_Stall_1 | EX_Stall_2 | EX_Exception_Stall) | EX_ALU_Stall | M_Stall; assign ID_Stall = (ID_Stall_1 | ID_Stall_2 | ID_Stall_3 | ID_Stall_4 | ID_Exception_Stall) | EX_Stall; assign IF_Stall = InstMem_Read | InstMem_Ready | IF_Exception_Stall;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.