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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [gpu_4_cores/] [rtl/] [Collaterals/] [Module_FixedPointDivision.v] - Diff between revs 118 and 127

Only display areas with differences | Details | Blame | View Log

Rev 118 Rev 127
/*
/*
        Fixed point Multiplication Module Qm.n
        Fixed point Multiplication Module Qm.n
        C = (A << n) / B
        C = (A << n) / B
 
 
*/
*/
 
 
 
 
//Division State Machine Constants
//Division State Machine Constants
`define INITIAL_DIVISION_STATE                                  6'd1
`define INITIAL_DIVISION_STATE                                  6'd1
`define DIVISION_REVERSE_LAST_ITERATION         6'd2
`define DIVISION_REVERSE_LAST_ITERATION         6'd2
`define PRE_CALCULATE_REMAINDER                                 6'd3
`define PRE_CALCULATE_REMAINDER                                 6'd3
`define CALCULATE_REMAINDER                                             6'd4
`define CALCULATE_REMAINDER                                             6'd4
`define WRITE_DIVISION_RESULT                                           6'd5
`define WRITE_DIVISION_RESULT                                           6'd5
 
 
 
 
`timescale 1ns / 1ps
`timescale 1ns / 1ps
`include "aDefinitions.v"
`include "aDefinitions.v"
`define FPS_AFTER_RESET_STATE 0
`define FPS_AFTER_RESET_STATE 0
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//This only works if you dividend is power of 2
//This only works if you dividend is power of 2
//x % 2^n == x & (2^n - 1).
//x % 2^n == x & (2^n - 1).
/*
/*
module Modulus2N
module Modulus2N
(
(
input wire                                              Clock,
input wire                                              Clock,
input wire                                              Reset,
input wire                                              Reset,
input wire [`WIDTH-1:0]         iDividend,iDivisor,
input wire [`WIDTH-1:0]         iDividend,iDivisor,
output reg  [`WIDTH-1:0]        oQuotient,
output reg  [`WIDTH-1:0]        oQuotient,
input  wire                                             iInputReady,            //Is the input data valid?
input  wire                                             iInputReady,            //Is the input data valid?
output reg                                              oOutputReady            //Our output data is ready!
output reg                                              oOutputReady            //Our output data is ready!
);
);
 
 
 
 
 
 
FF1_POSEDGE_SYNCRONOUS_RESET FFOutputReadyDelay2
FF1_POSEDGE_SYNCRONOUS_RESET FFOutputReadyDelay2
(
(
        .Clock( Clock ),
        .Clock( Clock ),
        .Clear( Reset ),
        .Clear( Reset ),
        .D( iInputReady ),
        .D( iInputReady ),
        .Q( oOutputReady )
        .Q( oOutputReady )
);
);
 
 
assign oQuotient = (iDividend & (iDivisor-1'b1));
assign oQuotient = (iDividend & (iDivisor-1'b1));
 
 
 
 
endmodule
endmodule
*/
*/
//-----------------------------------------------------------------
//-----------------------------------------------------------------
/*
/*
Be aware that the unsgined division algorith doesn't know or care
Be aware that the unsgined division algorith doesn't know or care
about the sign bit of the Result (bit 31). So if you divisor is very
about the sign bit of the Result (bit 31). So if you divisor is very
small there is a chance that the bit 31 from the usginned division is
small there is a chance that the bit 31 from the usginned division is
one even thogh the result should be positive
one even thogh the result should be positive
 
 
*/
*/
module SignedIntegerDivision
module SignedIntegerDivision
(
(
input    wire                   Clock,Reset,
input    wire                   Clock,Reset,
input  wire [`WIDTH-1:0] iDividend,iDivisor,
input  wire [`WIDTH-1:0] iDividend,iDivisor,
output reg  [`WIDTH-1:0] xQuotient,
output reg  [`WIDTH-1:0] xQuotient,
input  wire     iInputReady,            //Is the input data valid?
input  wire     iInputReady,            //Is the input data valid?
output reg      OutputReady             //Our output data is ready!
output reg      OutputReady             //Our output data is ready!
);
);
 
 
 
 
parameter SIGN = 31;
parameter SIGN = 31;
wire Sign;
wire Sign;
 
 
wire [`WIDTH-1:0] wDividend,wDivisor;
wire [`WIDTH-1:0] wDividend,wDivisor;
wire wInputReady;
wire wInputReady;
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD1
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD1
(
(
        .Clock( Clock ),
        .Clock( Clock ),
        .Reset( Reset),
        .Reset( Reset),
        .Enable( iInputReady ),
        .Enable( iInputReady ),
        .D( iDividend ),
        .D( iDividend ),
        .Q( wDividend)
        .Q( wDividend)
);
);
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD2
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD2
(
(
        .Clock( Clock ),
        .Clock( Clock ),
        .Reset( Reset),
        .Reset( Reset),
        .Enable( iInputReady ),
        .Enable( iInputReady ),
        .D( iDivisor ),
        .D( iDivisor ),
        .Q( wDivisor )
        .Q( wDivisor )
);
);
 
 
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
(
(
        .Clock( Clock ),
        .Clock( Clock ),
        .Reset( Reset),
        .Reset( Reset),
        .Enable( 1'b1 ),
        .Enable( 1'b1 ),
        .D( iInputReady ),
        .D( iInputReady ),
        .Q( wInputReady )
        .Q( wInputReady )
);
);
 
 
 
 
//wire [7:0] wExitStatus;
//wire [7:0] wExitStatus;
wire [`WIDTH-1:0] wAbsDividend,wAbsDivisor;
wire [`WIDTH-1:0] wAbsDividend,wAbsDivisor;
wire [`WIDTH-1:0] wQuottientTemp;
wire [`WIDTH-1:0] wQuottientTemp;
wire  [`WIDTH-1:0] wAbsQuotient;
wire  [`WIDTH-1:0] wAbsQuotient;
 
 
assign Sign = wDividend[SIGN] ^ wDivisor[SIGN];
assign Sign = wDividend[SIGN] ^ wDivisor[SIGN];
 
 
assign wAbsDividend = ( wDividend[SIGN] == 1 )?
assign wAbsDividend = ( wDividend[SIGN] == 1 )?
                        ~wDividend + 1'b1 : wDividend;
                        ~wDividend + 1'b1 : wDividend;
 
 
assign wAbsDivisor = ( wDivisor[SIGN] == 1 )?
assign wAbsDivisor = ( wDivisor[SIGN] == 1 )?
                ~wDivisor + 1'b1 : wDivisor;
                ~wDivisor + 1'b1 : wDivisor;
 
 
wire DivReady;
wire DivReady;
 
 
 
 
UnsignedIntegerDivision UDIV
UnsignedIntegerDivision UDIV
(
(
                .Clock(Clock),
                .Clock(Clock),
                .Reset( Reset ),
                .Reset( Reset ),
                .iDividend( wAbsDividend),
                .iDividend( wAbsDividend),
                .iDivisor( wAbsDivisor ),
                .iDivisor( wAbsDivisor ),
                .xQuotient(wQuottientTemp),
                .xQuotient(wQuottientTemp),
                .iInputReady( wInputReady ),
                .iInputReady( wInputReady ),
                .OutputReady( DivReady )
                .OutputReady( DivReady )
 
 
        );
        );
 
 
//Make sure the output from the 'unsigned' operation is really posity
//Make sure the output from the 'unsigned' operation is really posity
assign wAbsQuotient = wQuottientTemp & 32'h7FFFFFFF;
assign wAbsQuotient = wQuottientTemp & 32'h7FFFFFFF;
 
 
//assign Quotient = wAbsQuotient;
//assign Quotient = wAbsQuotient;
 
 
        //-----------------------------------------------
        //-----------------------------------------------
        always @ ( posedge Clock )
        always @ ( posedge Clock )
        begin
        begin
 
 
                if ( DivReady )
                if ( DivReady )
                begin
                begin
                        if ( Sign == 1 )
                        if ( Sign == 1 )
                                xQuotient = ~wAbsQuotient + 1'b1;
                                xQuotient = ~wAbsQuotient + 1'b1;
                        else
                        else
                                xQuotient = wAbsQuotient;
                                xQuotient = wAbsQuotient;
 
 
                end
                end
 
 
                OutputReady = DivReady;
                OutputReady = DivReady;
 
 
                if (Reset == 1)
                if (Reset == 1)
                        OutputReady = 0;
                        OutputReady = 0;
 
 
 
 
        end
        end
        //-----------------------------------------------
        //-----------------------------------------------
 
 
endmodule
endmodule
//-----------------------------------------------------------------
//-----------------------------------------------------------------
/*
/*
 
 
        Returns the integer part (Quotient) of a division.
        Returns the integer part (Quotient) of a division.
 
 
        Division is the process of repeated subtraction.
        Division is the process of repeated subtraction.
        Like the long division we learned in grade school,
        Like the long division we learned in grade school,
        a binary division algorithm works from the high
        a binary division algorithm works from the high
        order digits to the low order digits and generates
        order digits to the low order digits and generates
        a quotient (division result) with each step.
        a quotient (division result) with each step.
        The division algorithm is divided into two steps:
        The division algorithm is divided into two steps:
   * Shift the upper bits of the dividend (the number
   * Shift the upper bits of the dividend (the number
   we are dividing into) into the remainder.
   we are dividing into) into the remainder.
   * Subtract the divisor from the value in the remainder.
   * Subtract the divisor from the value in the remainder.
   The high order bit of the result become a bit of
   The high order bit of the result become a bit of
   the quotient (division result).
   the quotient (division result).
 
 
*/
*/
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
/*
/*
Try to implemet the division as a FSM,
Try to implemet the division as a FSM,
this basically because the behavioral Division has a for loop,
this basically because the behavioral Division has a for loop,
with a variable loop limit counter which I think is not friendly
with a variable loop limit counter which I think is not friendly
to the synthetiser (dumb dumb synthetizer :) )
to the synthetiser (dumb dumb synthetizer :) )
*/
*/
module UnsignedIntegerDivision(
module UnsignedIntegerDivision(
input   wire                            Clock,Reset,
input   wire                            Clock,Reset,
input   wire [`WIDTH-1:0]        iDividend,iDivisor,
input   wire [`WIDTH-1:0]        iDividend,iDivisor,
//output reg    [`WIDTH-1:0]    Quotient,Remainder,
//output reg    [`WIDTH-1:0]    Quotient,Remainder,
 
 
output reg      [`WIDTH-1:0]     xQuotient,
output reg      [`WIDTH-1:0]     xQuotient,
 
 
input  wire     iInputReady,            //Is the input data valid?
input  wire     iInputReady,            //Is the input data valid?
output reg      OutputReady     //Our output data is ready!
output reg      OutputReady     //Our output data is ready!
//output reg  [7:0]                     ExitStatus
//output reg  [7:0]                     ExitStatus
);
);
 
 
//reg           [`WIDTH-1:0] Dividend, Divisor;
//reg           [`WIDTH-1:0] Dividend, Divisor;
 
 
reg [63:0] Dividend,Divisor;
reg [63:0] Dividend,Divisor;
 
 
//reg   [`WIDTH-1:0] t, q, d, i,Bit,  num_bits; 
//reg   [`WIDTH-1:0] t, q, d, i,Bit,  num_bits; 
reg     [`WIDTH-1:0]  i,num_bits;
reg     [`WIDTH-1:0]  i,num_bits;
reg [63:0] t, q, d, Bit;
reg [63:0] t, q, d, Bit;
reg     [63:0]   Quotient,Remainder;
reg     [63:0]   Quotient,Remainder;
 
 
reg     [5:0]    CurrentState, NextState;
reg     [5:0]    CurrentState, NextState;
//----------------------------------------
//----------------------------------------
//Next states logic and Reset sequence
//Next states logic and Reset sequence
always @(negedge Clock)
always @(negedge Clock)
begin
begin
        if( Reset!=1 )
        if( Reset!=1 )
           CurrentState = NextState;
           CurrentState = NextState;
                  else
                  else
                          CurrentState = `FPS_AFTER_RESET_STATE;
                          CurrentState = `FPS_AFTER_RESET_STATE;
end
end
//----------------------------------------
//----------------------------------------
 
 
always @ (posedge Clock)
always @ (posedge Clock)
begin
begin
case (CurrentState)
case (CurrentState)
        //----------------------------------------
        //----------------------------------------
        `FPS_AFTER_RESET_STATE:
        `FPS_AFTER_RESET_STATE:
        begin
        begin
                OutputReady = 0;
                OutputReady = 0;
                NextState = ( iInputReady == 1 ) ?
                NextState = ( iInputReady == 1 ) ?
                        `INITIAL_DIVISION_STATE : `FPS_AFTER_RESET_STATE;
                        `INITIAL_DIVISION_STATE : `FPS_AFTER_RESET_STATE;
        end
        end
        //----------------------------------------
        //----------------------------------------
        `INITIAL_DIVISION_STATE:
        `INITIAL_DIVISION_STATE:
        begin
        begin
                Dividend = iDividend;
                Dividend = iDividend;
                Dividend =  Dividend << `SCALE;
                Dividend =  Dividend << `SCALE;
 
 
                Divisor  = iDivisor;
                Divisor  = iDivisor;
                Remainder = 0;
                Remainder = 0;
                Quotient = 0;
                Quotient = 0;
 
 
                if (Divisor == 0)
                if (Divisor == 0)
                begin
                begin
                                Quotient[31:0] = 32'h0FFF_FFFF;
                                Quotient[31:0] = 32'h0FFF_FFFF;
                //      ExitStatus = `DIVISION_BY_ZERO; 
                //      ExitStatus = `DIVISION_BY_ZERO; 
                                NextState = `WRITE_DIVISION_RESULT;
                                NextState = `WRITE_DIVISION_RESULT;
                end
                end
                else if (Divisor > Dividend)
                else if (Divisor > Dividend)
                begin
                begin
                Remainder       = Dividend;
                Remainder       = Dividend;
                        //ExitStatus    = `NORMAL_EXIT; 
                        //ExitStatus    = `NORMAL_EXIT; 
                        NextState = `WRITE_DIVISION_RESULT;
                        NextState = `WRITE_DIVISION_RESULT;
        end
        end
                else if (Divisor == Dividend)
                else if (Divisor == Dividend)
                begin
                begin
                Quotient = 1;
                Quotient = 1;
        //      ExitStatus      = `NORMAL_EXIT; 
        //      ExitStatus      = `NORMAL_EXIT; 
                        NextState = `WRITE_DIVISION_RESULT;
                        NextState = `WRITE_DIVISION_RESULT;
      end
      end
                else
                else
                begin
                begin
         NextState = `PRE_CALCULATE_REMAINDER;
         NextState = `PRE_CALCULATE_REMAINDER;
                end
                end
                  //num_bits = 32;
                  //num_bits = 32;
                  num_bits = 64;
                  num_bits = 64;
        end
        end
 
 
        //----------------------------------------
        //----------------------------------------
        `PRE_CALCULATE_REMAINDER:
        `PRE_CALCULATE_REMAINDER:
        begin
        begin
 
 
                //Bit = (Dividend & 32'h80000000) >> 31;
                //Bit = (Dividend & 32'h80000000) >> 31;
                Bit = (Dividend & 64'h8000000000000000 ) >> 63;
                Bit = (Dividend & 64'h8000000000000000 ) >> 63;
        Remainder = (Remainder << 1) | Bit;
        Remainder = (Remainder << 1) | Bit;
        d = Dividend;
        d = Dividend;
        Dividend = Dividend << 1;
        Dividend = Dividend << 1;
        num_bits = num_bits - 1;
        num_bits = num_bits - 1;
 
 
 
 
//              $display("num_bits %d Remainder %d Divisor %d\n",num_bits,Remainder,Divisor);
//              $display("num_bits %d Remainder %d Divisor %d\n",num_bits,Remainder,Divisor);
                NextState = (Remainder < Divisor) ?
                NextState = (Remainder < Divisor) ?
                        `PRE_CALCULATE_REMAINDER : `DIVISION_REVERSE_LAST_ITERATION;
                        `PRE_CALCULATE_REMAINDER : `DIVISION_REVERSE_LAST_ITERATION;
        end
        end
        //----------------------------------------
        //----------------------------------------
        /*
        /*
                The loop, above, always goes one iteration too far.
                The loop, above, always goes one iteration too far.
        To avoid inserting an "if" statement inside the loop
        To avoid inserting an "if" statement inside the loop
        the last iteration is simply reversed.
        the last iteration is simply reversed.
     */
     */
        `DIVISION_REVERSE_LAST_ITERATION:
        `DIVISION_REVERSE_LAST_ITERATION:
        begin
        begin
                Dividend = d;
                Dividend = d;
                Remainder = Remainder >> 1;
                Remainder = Remainder >> 1;
                num_bits = num_bits + 1;
                num_bits = num_bits + 1;
                i = 0;
                i = 0;
 
 
                NextState = `CALCULATE_REMAINDER;
                NextState = `CALCULATE_REMAINDER;
        end
        end
        //----------------------------------------
        //----------------------------------------
        `CALCULATE_REMAINDER:
        `CALCULATE_REMAINDER:
        begin
        begin
                        //Bit = (Dividend & 32'h80000000) >> 31;
                        //Bit = (Dividend & 32'h80000000) >> 31;
                        Bit = (Dividend & 64'h8000000000000000 ) >> 63;
                        Bit = (Dividend & 64'h8000000000000000 ) >> 63;
                Remainder = (Remainder << 1) | Bit;
                Remainder = (Remainder << 1) | Bit;
                t = Remainder - Divisor;
                t = Remainder - Divisor;
                //q = !((t & 32'h80000000) >> 31);
                //q = !((t & 32'h80000000) >> 31);
                        q = !((t & 64'h8000000000000000 ) >> 63);
                        q = !((t & 64'h8000000000000000 ) >> 63);
                Dividend = Dividend << 1;
                Dividend = Dividend << 1;
                Quotient = (Quotient << 1) | q;
                Quotient = (Quotient << 1) | q;
                if ( q != 0 )
                if ( q != 0 )
                        Remainder = t;
                        Remainder = t;
                i = i + 1;
                i = i + 1;
 
 
                if (i < num_bits)
                if (i < num_bits)
                        NextState = `CALCULATE_REMAINDER;
                        NextState = `CALCULATE_REMAINDER;
                else
                else
                        NextState = `WRITE_DIVISION_RESULT;
                        NextState = `WRITE_DIVISION_RESULT;
        end
        end
        //----------------------------------------
        //----------------------------------------
        //Will go to the IDLE leaving the Result Registers
        //Will go to the IDLE leaving the Result Registers
        //with the current results until next stuff comes
        //with the current results until next stuff comes
        //So, stay in this state until our client sets iInputReady
        //So, stay in this state until our client sets iInputReady
        //to 0 telling us he read the result
        //to 0 telling us he read the result
        `WRITE_DIVISION_RESULT:
        `WRITE_DIVISION_RESULT:
        begin
        begin
                xQuotient = Quotient[32:0];      //Simply chop to round
                xQuotient = Quotient[32:0];      //Simply chop to round
                OutputReady = 1;
                OutputReady = 1;
//              $display("Quotient = %h - %b \n", Quotient, Quotient);
//              $display("Quotient = %h - %b \n", Quotient, Quotient);
 
 
                NextState = (iInputReady == 0) ?
                NextState = (iInputReady == 0) ?
                 `FPS_AFTER_RESET_STATE : `WRITE_DIVISION_RESULT;
                 `FPS_AFTER_RESET_STATE : `WRITE_DIVISION_RESULT;
        end
        end
endcase
endcase
 
 
end //always
end //always
endmodule
endmodule
//-----------------------------------------------------------------
//-----------------------------------------------------------------
 
 

powered by: WebSVN 2.1.0

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