Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
92595157eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright 2019- RSD contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
//
// --- Divider Unit
//
// - 32bit/32bit=32bitを行うモジュール
//
import BasicTypes::*;
import MicroOpTypes::*;
import OpFormatTypes::*;
// 除算ユニット
module DividerUnit (
input
logic clk, rst,
logic req,
DataPath fuOpA_In,
DataPath fuOpB_In,
IntDIV_Code divCode,
output
logic finished,
DataPath dataOut
);
logic regIsSigned, nextIsSigned;
DataPath regDividend, nextDividend;
DataPath regDivisor, nextDivisor;
IntDIV_Code regDivCode, nextDivCode;
DataPath quotient, remainder;
QuickDivider div (
.clk( clk ),
.rst( rst ),
.req ( req ),
.dividend ( nextDividend ),
.divisor ( nextDivisor ),
.isSigned ( nextIsSigned ),
.finished ( finished ),
.quotient ( quotient ),
.remainder ( remainder )
);
// IntDIV code
/*
typedef enum logic [1:0] // enum IntDIV_Code
{
AC_DIV = 2'b00, // DIV
AC_DIVU = 2'b01, // DIVU
AC_REM = 2'b10, // REM
AC_REMU = 2'b11 // REMU
} IntDIV_Code;
*/
always_ff @(posedge clk) begin
if (rst) begin
regIsSigned <= FALSE;
regDividend <= '0;
regDivisor <= '0;
regDivCode <= AC_DIV;
end
else begin
regIsSigned <= nextIsSigned;
regDividend <= nextDividend;
regDivisor <= nextDivisor;
regDivCode <= nextDivCode;
end
end
// Make src operands unsigned(plus) value.
always_comb begin
if (req) begin
if (divCode == AC_DIVU || divCode == AC_REMU) begin
// DIVU and REMU take srcs as unsigned.
nextIsSigned = FALSE;
end
else begin
// DIV and REM take srcs as signed.
nextIsSigned = TRUE;
end
nextDividend = fuOpA_In;
nextDivisor = fuOpB_In;
nextDivCode = divCode;
end
else begin
// Keep the value
nextIsSigned = regIsSigned;
nextDividend = regDividend;
nextDivisor = regDivisor;
nextDivCode = regDivCode;
end
// Choose output from div or rem.
if (regDivCode == AC_DIV || regDivCode == AC_DIVU) begin
dataOut = quotient;
end
else begin
dataOut = remainder;
end
end
endmodule : DividerUnit
// パイプライン化された除算ユニット
module PipelinedDividerUnit #(
parameter BIT_WIDTH = 32,
parameter PIPELINE_DEPTH = 3
)(
input
logic clk,
logic stall,
logic req,
DataPath fuOpA_In,
DataPath fuOpB_In,
IntDIV_Code divCode,
output
logic finished,
DataPath dataOut
);
typedef struct packed { // PipeReg
logic valid;
logic isSigned;
IntDIV_Code divCode;
} PipeReg;
PipeReg pipeReg[ PIPELINE_DEPTH-1 ], nextReg;
DataPath quotient, remainder;
logic isSigned;
DataPath dividend;
DataPath divisor;
PipelinedRefDivider #(
.BIT_WIDTH( $bits(DataPath) ),
.PIPELINE_DEPTH( PIPELINE_DEPTH )
) div (
.clk( clk ),
.stall( stall ),
.dividend(dividend),
.divisor(divisor),
.isSigned(isSigned),
.quotient(quotient),
.remainder(remainder)
);
always_ff @(posedge clk) begin
if (!stall) begin
pipeReg[0] <= nextReg;
for (int i = 1; i < PIPELINE_DEPTH-1; i++) begin
pipeReg[i] <= pipeReg[i-1];
end
end
end
// Make src operands unsigned(plus) value.
always_comb begin
if (divCode == AC_DIVU || divCode == AC_REMU) begin
// // MULHU takes srcA as unsigned.
// srcA_signed = fuOpA_signed;
isSigned = TRUE;
end
else begin
isSigned = FALSE;
end
dividend = fuOpA_In;
divisor = fuOpB_In;
nextReg.isSigned = isSigned;
nextReg.divCode = divCode;
nextReg.valid = req;
if (pipeReg[PIPELINE_DEPTH-2].valid) begin
if (pipeReg[PIPELINE_DEPTH-2].divCode == AC_DIV || pipeReg[PIPELINE_DEPTH-2].divCode == AC_DIVU) begin
dataOut = quotient;
end
else begin
dataOut = remainder;
end
finished = TRUE;
end
else begin
dataOut = '0;
finished = FALSE;
end
end
`ifndef RSD_SYNTHESIS
initial begin
for (int i = 0; i < PIPELINE_DEPTH-1; i++) begin
pipeReg[i] <= '0;
end
end
`endif
endmodule : PipelinedDividerUnit