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

Subversion Repositories theia_gpu

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

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 70 diegovalve
wire [`WIDTH-1:0] wDividend,wDivisor;
60
wire wInputReady;
61
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD1
62
(
63
        .Clock( Clock ),
64
        .Reset( Reset),
65
        .Enable( iInputReady ),
66
        .D( iDividend ),
67
        .Q( wDividend)
68
);
69
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) FFD2
70
(
71
        .Clock( Clock ),
72
        .Reset( Reset),
73
        .Enable( iInputReady ),
74
        .D( iDivisor ),
75
        .Q( wDivisor )
76
);
77 42 diegovalve
 
78 70 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
79
(
80
        .Clock( Clock ),
81
        .Reset( Reset),
82
        .Enable( 1'b1 ),
83
        .D( iInputReady ),
84
        .Q( wInputReady )
85
);
86
 
87
 
88 42 diegovalve
//wire [7:0] wExitStatus;
89
wire [`WIDTH-1:0] wAbsDividend,wAbsDivisor;
90
wire [`WIDTH-1:0] wQuottientTemp;
91
wire  [`WIDTH-1:0] wAbsQuotient;
92
 
93 70 diegovalve
assign Sign = wDividend[SIGN] ^ wDivisor[SIGN];
94 42 diegovalve
 
95 70 diegovalve
assign wAbsDividend = ( wDividend[SIGN] == 1 )?
96
                        ~wDividend + 1'b1 : wDividend;
97 42 diegovalve
 
98 70 diegovalve
assign wAbsDivisor = ( wDivisor[SIGN] == 1 )?
99
                ~wDivisor + 1'b1 : wDivisor;
100 42 diegovalve
 
101
wire DivReady;
102
 
103
 
104
UnsignedIntegerDivision UDIV
105
(
106
                .Clock(Clock),
107
                .Reset( Reset ),
108
                .iDividend( wAbsDividend),
109
                .iDivisor( wAbsDivisor ),
110
                .xQuotient(wQuottientTemp),
111 70 diegovalve
                .iInputReady( wInputReady ),
112 42 diegovalve
                .OutputReady( DivReady )
113
 
114
        );
115
 
116
//Make sure the output from the 'unsigned' operation is really posity
117
assign wAbsQuotient = wQuottientTemp & 32'h7FFFFFFF;
118
 
119
//assign Quotient = wAbsQuotient;
120
 
121
        //-----------------------------------------------
122
        always @ ( posedge Clock )
123
        begin
124
 
125
                if ( DivReady )
126
                begin
127
                        if ( Sign == 1 )
128
                                xQuotient = ~wAbsQuotient + 1'b1;
129
                        else
130
                                xQuotient = wAbsQuotient;
131
 
132
                end
133
 
134
                OutputReady = DivReady;
135
 
136
                if (Reset == 1)
137
                        OutputReady = 0;
138
 
139
 
140
        end
141
        //-----------------------------------------------
142
 
143
endmodule
144
//-----------------------------------------------------------------
145
/*
146
 
147
        Returns the integer part (Quotient) of a division.
148
 
149
        Division is the process of repeated subtraction.
150
        Like the long division we learned in grade school,
151
        a binary division algorithm works from the high
152
        order digits to the low order digits and generates
153
        a quotient (division result) with each step.
154
        The division algorithm is divided into two steps:
155
   * Shift the upper bits of the dividend (the number
156
   we are dividing into) into the remainder.
157
   * Subtract the divisor from the value in the remainder.
158
   The high order bit of the result become a bit of
159
   the quotient (division result).
160
 
161
*/
162
 
163
//-----------------------------------------------------------------
164
/*
165
Try to implemet the division as a FSM,
166
this basically because the behavioral Division has a for loop,
167
with a variable loop limit counter which I think is not friendly
168
to the synthetiser (dumb dumb synthetizer :) )
169
*/
170
module UnsignedIntegerDivision(
171
input   wire                            Clock,Reset,
172
input   wire [`WIDTH-1:0]        iDividend,iDivisor,
173
//output reg    [`WIDTH-1:0]    Quotient,Remainder,
174
 
175
output reg      [`WIDTH-1:0]     xQuotient,
176
 
177
input  wire     iInputReady,            //Is the input data valid?
178
output reg      OutputReady     //Our output data is ready!
179
//output reg  [7:0]                     ExitStatus
180
);
181
 
182
//reg           [`WIDTH-1:0] Dividend, Divisor;
183
 
184
reg [63:0] Dividend,Divisor;
185
 
186
//reg   [`WIDTH-1:0] t, q, d, i,Bit,  num_bits; 
187
reg     [`WIDTH-1:0]  i,num_bits;
188
reg [63:0] t, q, d, Bit;
189
reg     [63:0]   Quotient,Remainder;
190
 
191
reg     [5:0]    CurrentState, NextState;
192
//----------------------------------------
193
//Next states logic and Reset sequence
194
always @(negedge Clock)
195
begin
196
        if( Reset!=1 )
197
           CurrentState = NextState;
198
                  else
199
                          CurrentState = `FPS_AFTER_RESET_STATE;
200
end
201
//----------------------------------------
202
 
203
always @ (posedge Clock)
204
begin
205
case (CurrentState)
206
        //----------------------------------------
207
        `FPS_AFTER_RESET_STATE:
208
        begin
209
                OutputReady = 0;
210
                NextState = ( iInputReady == 1 ) ?
211
                        `INITIAL_DIVISION_STATE : `FPS_AFTER_RESET_STATE;
212
        end
213
        //----------------------------------------
214
        `INITIAL_DIVISION_STATE:
215
        begin
216
                Dividend = iDividend;
217
                Dividend =  Dividend << `SCALE;
218
 
219
                Divisor  = iDivisor;
220
                Remainder = 0;
221
                Quotient = 0;
222
 
223
                if (Divisor == 0)
224
                begin
225
                                Quotient[31:0] = 32'h0FFF_FFFF;
226
                //      ExitStatus = `DIVISION_BY_ZERO; 
227
                                NextState = `WRITE_DIVISION_RESULT;
228
                end
229
                else if (Divisor > Dividend)
230
                begin
231
                Remainder       = Dividend;
232
                        //ExitStatus    = `NORMAL_EXIT; 
233
                        NextState = `WRITE_DIVISION_RESULT;
234
        end
235
                else if (Divisor == Dividend)
236
                begin
237
                Quotient = 1;
238
        //      ExitStatus      = `NORMAL_EXIT; 
239
                        NextState = `WRITE_DIVISION_RESULT;
240
      end
241
                else
242
                begin
243
         NextState = `PRE_CALCULATE_REMAINDER;
244
                end
245
                  //num_bits = 32;
246
                  num_bits = 64;
247
        end
248
 
249
        //----------------------------------------
250
        `PRE_CALCULATE_REMAINDER:
251
        begin
252
 
253
                //Bit = (Dividend & 32'h80000000) >> 31;
254
                Bit = (Dividend & 64'h8000000000000000 ) >> 63;
255
        Remainder = (Remainder << 1) | Bit;
256
        d = Dividend;
257
        Dividend = Dividend << 1;
258
        num_bits = num_bits - 1;
259
 
260
 
261
//              $display("num_bits %d Remainder %d Divisor %d\n",num_bits,Remainder,Divisor);
262
                NextState = (Remainder < Divisor) ?
263
                        `PRE_CALCULATE_REMAINDER : `DIVISION_REVERSE_LAST_ITERATION;
264
        end
265
        //----------------------------------------
266
        /*
267
                The loop, above, always goes one iteration too far.
268
        To avoid inserting an "if" statement inside the loop
269
        the last iteration is simply reversed.
270
     */
271
        `DIVISION_REVERSE_LAST_ITERATION:
272
        begin
273
                Dividend = d;
274
                Remainder = Remainder >> 1;
275
                num_bits = num_bits + 1;
276
                i = 0;
277
 
278
                NextState = `CALCULATE_REMAINDER;
279
        end
280
        //----------------------------------------
281
        `CALCULATE_REMAINDER:
282
        begin
283
                        //Bit = (Dividend & 32'h80000000) >> 31;
284
                        Bit = (Dividend & 64'h8000000000000000 ) >> 63;
285
                Remainder = (Remainder << 1) | Bit;
286
                t = Remainder - Divisor;
287
                //q = !((t & 32'h80000000) >> 31);
288
                        q = !((t & 64'h8000000000000000 ) >> 63);
289
                Dividend = Dividend << 1;
290
                Quotient = (Quotient << 1) | q;
291
                if ( q != 0 )
292
                        Remainder = t;
293
                i = i + 1;
294
 
295
                if (i < num_bits)
296
                        NextState = `CALCULATE_REMAINDER;
297
                else
298
                        NextState = `WRITE_DIVISION_RESULT;
299
        end
300
        //----------------------------------------
301
        //Will go to the IDLE leaving the Result Registers
302
        //with the current results until next stuff comes
303
        //So, stay in this state until our client sets iInputReady
304
        //to 0 telling us he read the result
305
        `WRITE_DIVISION_RESULT:
306
        begin
307
                xQuotient = Quotient[32:0];      //Simply chop to round
308
                OutputReady = 1;
309
//              $display("Quotient = %h - %b \n", Quotient, Quotient);
310
 
311
                NextState = (iInputReady == 0) ?
312
                 `FPS_AFTER_RESET_STATE : `WRITE_DIVISION_RESULT;
313
        end
314
endcase
315
 
316
end //always
317
endmodule
318
//-----------------------------------------------------------------

powered by: WebSVN 2.1.0

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