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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [trunk/] [rtl/] [Module_FixedPointDivision.v] - Blame information for rev 212

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

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

powered by: WebSVN 2.1.0

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