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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [beta_1.1/] [rtl/] [Collaterals/] [Module_FixedPointDivision.v] - Blame information for rev 68

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 42 diegovalve
/*
2
        Fixed point Multiplication Module Qm.n
3
        C = (A << n) / B
4
 
5
*/
6
`timescale 1ns / 1ps
7
`include "aDefinitions.v"
8
`define FPS_AFTER_RESET_STATE 0
9
//-----------------------------------------------------------------
10
//This only works if you dividend is power of 2
11
//x % 2^n == x & (2^n - 1).
12
/*
13
module Modulus2N
14
(
15
input wire                                              Clock,
16
input wire                                              Reset,
17
input wire [`WIDTH-1:0]         iDividend,iDivisor,
18
output reg  [`WIDTH-1:0]        oQuotient,
19
input  wire                                             iInputReady,            //Is the input data valid?
20
output reg                                              oOutputReady            //Our output data is ready!
21
);
22
 
23
 
24
 
25
FF1_POSEDGE_SYNCRONOUS_RESET FFOutputReadyDelay2
26
(
27
        .Clock( Clock ),
28
        .Clear( Reset ),
29
        .D( iInputReady ),
30
        .Q( oOutputReady )
31
);
32
 
33
assign oQuotient = (iDividend & (iDivisor-1'b1));
34
 
35
 
36
endmodule
37
*/
38
//-----------------------------------------------------------------
39
/*
40
Be aware that the unsgined division algorith doesn't know or care
41
about the sign bit of the Result (bit 31). So if you divisor is very
42
small there is a chance that the bit 31 from the usginned division is
43
one even thogh the result should be positive
44
 
45
*/
46
module SignedIntegerDivision
47
(
48
input    wire                   Clock,Reset,
49
input  wire [`WIDTH-1:0] iDividend,iDivisor,
50
output reg  [`WIDTH-1:0] xQuotient,
51
input  wire     iInputReady,            //Is the input data valid?
52
output reg      OutputReady             //Our output data is ready!
53
);
54
 
55
 
56
parameter SIGN = 31;
57
wire Sign;
58
 
59
 
60
//wire [7:0] wExitStatus;
61
wire [`WIDTH-1:0] wAbsDividend,wAbsDivisor;
62
wire [`WIDTH-1:0] wQuottientTemp;
63
wire  [`WIDTH-1:0] wAbsQuotient;
64
 
65
assign Sign = iDividend[SIGN] ^ iDivisor[SIGN];
66
 
67
assign wAbsDividend = ( iDividend[SIGN] == 1 )?
68
                        ~iDividend + 1'b1 : iDividend;
69
 
70
assign wAbsDivisor = ( iDivisor[SIGN] == 1 )?
71
                ~iDivisor + 1'b1 : iDivisor;
72
 
73
wire DivReady;
74
 
75
 
76
UnsignedIntegerDivision UDIV
77
(
78
                .Clock(Clock),
79
                .Reset( Reset ),
80
                .iDividend( wAbsDividend),
81
                .iDivisor( wAbsDivisor ),
82
                .xQuotient(wQuottientTemp),
83
                .iInputReady( iInputReady ),
84
                .OutputReady( DivReady )
85
 
86
        );
87
 
88
//Make sure the output from the 'unsigned' operation is really posity
89
assign wAbsQuotient = wQuottientTemp & 32'h7FFFFFFF;
90
 
91
//assign Quotient = wAbsQuotient;
92
 
93
        //-----------------------------------------------
94
        always @ ( posedge Clock )
95
        begin
96
 
97
                if ( DivReady )
98
                begin
99
                        if ( Sign == 1 )
100
                                xQuotient = ~wAbsQuotient + 1'b1;
101
                        else
102
                                xQuotient = wAbsQuotient;
103
 
104
                end
105
 
106
                OutputReady = DivReady;
107
 
108
                if (Reset == 1)
109
                        OutputReady = 0;
110
 
111
 
112
        end
113
        //-----------------------------------------------
114
 
115
endmodule
116
//-----------------------------------------------------------------
117
/*
118
 
119
        Returns the integer part (Quotient) of a division.
120
 
121
        Division is the process of repeated subtraction.
122
        Like the long division we learned in grade school,
123
        a binary division algorithm works from the high
124
        order digits to the low order digits and generates
125
        a quotient (division result) with each step.
126
        The division algorithm is divided into two steps:
127
   * Shift the upper bits of the dividend (the number
128
   we are dividing into) into the remainder.
129
   * Subtract the divisor from the value in the remainder.
130
   The high order bit of the result become a bit of
131
   the quotient (division result).
132
 
133
*/
134
 
135
//-----------------------------------------------------------------
136
/*
137
Try to implemet the division as a FSM,
138
this basically because the behavioral Division has a for loop,
139
with a variable loop limit counter which I think is not friendly
140
to the synthetiser (dumb dumb synthetizer :) )
141
*/
142
module UnsignedIntegerDivision(
143
input   wire                            Clock,Reset,
144
input   wire [`WIDTH-1:0]        iDividend,iDivisor,
145
//output reg    [`WIDTH-1:0]    Quotient,Remainder,
146
 
147
output reg      [`WIDTH-1:0]     xQuotient,
148
 
149
input  wire     iInputReady,            //Is the input data valid?
150
output reg      OutputReady     //Our output data is ready!
151
//output reg  [7:0]                     ExitStatus
152
);
153
 
154
//reg           [`WIDTH-1:0] Dividend, Divisor;
155
 
156
reg [63:0] Dividend,Divisor;
157
 
158
//reg   [`WIDTH-1:0] t, q, d, i,Bit,  num_bits; 
159
reg     [`WIDTH-1:0]  i,num_bits;
160
reg [63:0] t, q, d, Bit;
161
reg     [63:0]   Quotient,Remainder;
162
 
163
reg     [5:0]    CurrentState, NextState;
164
//----------------------------------------
165
//Next states logic and Reset sequence
166
always @(negedge Clock)
167
begin
168
        if( Reset!=1 )
169
           CurrentState = NextState;
170
                  else
171
                          CurrentState = `FPS_AFTER_RESET_STATE;
172
end
173
//----------------------------------------
174
 
175
always @ (posedge Clock)
176
begin
177
case (CurrentState)
178
        //----------------------------------------
179
        `FPS_AFTER_RESET_STATE:
180
        begin
181
                OutputReady = 0;
182
                NextState = ( iInputReady == 1 ) ?
183
                        `INITIAL_DIVISION_STATE : `FPS_AFTER_RESET_STATE;
184
        end
185
        //----------------------------------------
186
        `INITIAL_DIVISION_STATE:
187
        begin
188
                Dividend = iDividend;
189
                Dividend =  Dividend << `SCALE;
190
 
191
                Divisor  = iDivisor;
192
                Remainder = 0;
193
                Quotient = 0;
194
 
195
                if (Divisor == 0)
196
                begin
197
                                Quotient[31:0] = 32'h0FFF_FFFF;
198
                //      ExitStatus = `DIVISION_BY_ZERO; 
199
                                NextState = `WRITE_DIVISION_RESULT;
200
                end
201
                else if (Divisor > Dividend)
202
                begin
203
                Remainder       = Dividend;
204
                        //ExitStatus    = `NORMAL_EXIT; 
205
                        NextState = `WRITE_DIVISION_RESULT;
206
        end
207
                else if (Divisor == Dividend)
208
                begin
209
                Quotient = 1;
210
        //      ExitStatus      = `NORMAL_EXIT; 
211
                        NextState = `WRITE_DIVISION_RESULT;
212
      end
213
                else
214
                begin
215
         NextState = `PRE_CALCULATE_REMAINDER;
216
                end
217
                  //num_bits = 32;
218
                  num_bits = 64;
219
        end
220
 
221
        //----------------------------------------
222
        `PRE_CALCULATE_REMAINDER:
223
        begin
224
 
225
                //Bit = (Dividend & 32'h80000000) >> 31;
226
                Bit = (Dividend & 64'h8000000000000000 ) >> 63;
227
        Remainder = (Remainder << 1) | Bit;
228
        d = Dividend;
229
        Dividend = Dividend << 1;
230
        num_bits = num_bits - 1;
231
 
232
 
233
//              $display("num_bits %d Remainder %d Divisor %d\n",num_bits,Remainder,Divisor);
234
                NextState = (Remainder < Divisor) ?
235
                        `PRE_CALCULATE_REMAINDER : `DIVISION_REVERSE_LAST_ITERATION;
236
        end
237
        //----------------------------------------
238
        /*
239
                The loop, above, always goes one iteration too far.
240
        To avoid inserting an "if" statement inside the loop
241
        the last iteration is simply reversed.
242
     */
243
        `DIVISION_REVERSE_LAST_ITERATION:
244
        begin
245
                Dividend = d;
246
                Remainder = Remainder >> 1;
247
                num_bits = num_bits + 1;
248
                i = 0;
249
 
250
                NextState = `CALCULATE_REMAINDER;
251
        end
252
        //----------------------------------------
253
        `CALCULATE_REMAINDER:
254
        begin
255
                        //Bit = (Dividend & 32'h80000000) >> 31;
256
                        Bit = (Dividend & 64'h8000000000000000 ) >> 63;
257
                Remainder = (Remainder << 1) | Bit;
258
                t = Remainder - Divisor;
259
                //q = !((t & 32'h80000000) >> 31);
260
                        q = !((t & 64'h8000000000000000 ) >> 63);
261
                Dividend = Dividend << 1;
262
                Quotient = (Quotient << 1) | q;
263
                if ( q != 0 )
264
                        Remainder = t;
265
                i = i + 1;
266
 
267
                if (i < num_bits)
268
                        NextState = `CALCULATE_REMAINDER;
269
                else
270
                        NextState = `WRITE_DIVISION_RESULT;
271
        end
272
        //----------------------------------------
273
        //Will go to the IDLE leaving the Result Registers
274
        //with the current results until next stuff comes
275
        //So, stay in this state until our client sets iInputReady
276
        //to 0 telling us he read the result
277
        `WRITE_DIVISION_RESULT:
278
        begin
279
                xQuotient = Quotient[32:0];      //Simply chop to round
280
                OutputReady = 1;
281
//              $display("Quotient = %h - %b \n", Quotient, Quotient);
282
 
283
                NextState = (iInputReady == 0) ?
284
                 `FPS_AFTER_RESET_STATE : `WRITE_DIVISION_RESULT;
285
        end
286
endcase
287
 
288
end //always
289
endmodule
290
//-----------------------------------------------------------------

powered by: WebSVN 2.1.0

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