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

Subversion Repositories common

[/] [common/] [trunk/] [LPM_arithmetic.v] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 bbeaver
//------------------------------------------------------------------------
2
//   This Verilog file was developed by Altera Corporation.  It may be
3
// freely copied and/or distributed at no cost.  Any persons using this
4
// file for any purpose do so at their own risk, and are responsible for
5
// the results of such use.  Altera Corporation does not guarantee that
6
// this file is complete, correct, or fit for any particular purpose.
7
// NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.  This notice must
8
// accompany any copy of this file.
9
//
10
//------------------------------------------------------------------------
11
// Imported to Opencores directory.   Date Sept 10, 2001
12
// Split related modules into separate files, as the manual splits them.
13
// Added example instantiations to the beginning of each file.
14
//
15
/* EXAMPLE INSTANTIATIONS:
16
 
17
lpm_add_sub
18
#( 1,                         // lpm_width (width of input vector)
19
   "UNUSED",                  // lpm_direction, optional, {ADD, SUB}
20
   "UNSIGNED",                // lpm_representation, optional, {UNSIGNED, SIGNED}
21
 
22
 ) lpm_add_sub_example (
23
  .result                     (data_out[lpm_width-1:0]),
24
  .cout                       (carry_out_indicates_unsigned_result_too_big),  // OPTIONAL
25
  .overflow                   (overflow_indicates_MSB_sign_bit_wrong),  // OPTIONAL
26
  .dataa                      (data_in[lpm_width-1:0]),
27
  .datab                      (data_pl_mi_in[lpm_width-1:0]),
28
  .cin                        (add_1_if_HIGH_sub_1_if_LOW),      // OPTIONAL
29
  .add_sub                    (add_if_HIGH_must_set_HIGH_if_using_lpm_direction),  // OPTIONAL
30
  .clock                      (clock_if_pipelined),              // OPTIONAL
31
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
32
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
33
);
34
 
35
lpm_compare
36
#( 1,                         // lpm_width (width of input vector)
37
   "UNSIGNED",                // lpm_representation, optional, {UNSIGNED, SIGNED}
38
 
39
 ) lpm_compare_example (
40
  .agb                        (a_greater_than_b),
41
  .ageb                       (a_greater_or_equil_to_b),
42
  .aeb                        (a_equil_to_b),
43
  .aleb                       (a_less_or_equil_to_b),
44
  .alb                        (a_less_than_b),
45
  .aneb                       (a_not_equil_b),
46
  .dataa                      (data_in_a[lpm_width-1:0]),
47
  .datab                      (data_in_a[lpm_width-1:0]),
48
  .clock                      (clock_if_pipelined),              // OPTIONAL
49
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
50
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
51
);
52
 
53
module lpm_mult (
54
#( 1,                         // lpm_widtha (width of input vector)
55
   1,                         // lpm_widthb (width of input vector)
56
   1,                         // lpm_widths (width of partial sum vector)
57
   1,                         // lpm_widthp (width of product vector)
58
   "UNSIGNED",                // lpm_representation, optional, {UNSIGNED, SIGNED}
59
 
60
 ) lpm_mult_example (
61
  .result                     (data_out[lpm_widthp-1:0]),
62
  .sum                        (partial_sum_in[lpm_widths-1:0]),  // OPTIONAL
63
  .dataa                      (multiplicand_a_in[lpm_widtha-1:0]),
64
  .datab                      (multiplicand_b_in[lpm_widthb-1:0]),
65
  .clock                      (clock_if_pipelined),              // OPTIONAL
66
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
67
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
68
);
69
 
70
lpm_divide
71
#( 1,                         // lpm_widthn (width of numerator)
72
   1,                         // lpm_widthn (width of denominator)
73
   "UNSIGNED",                // lpm_nrepresentation, optional, {UNSIGNED, SIGNED}
74
   "UNSIGNED",                // lpm_drepresentation, optional, {UNSIGNED, SIGNED}
75
 
76
 ) lpm_divide_example (
77
  .quotient                   (data_out[lpm_widthn-1:0]),  // CHOICE
78
  .remain                     (data_out[lpm_widthd-1:0]),  // CHOICE
79
  .numer                      (data_out[lpm_widthn-1:0]),
80
  .denom                      (data_out[lpm_widthd-1:0]),
81
  .clock                      (clock_if_pipelined),              // OPTIONAL
82
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
83
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
84
);
85
 
86
lpm_abs
87
#( 1                          // lpm_width (width of input)
88
 ) lpm_abs_example (
89
  .result                     (data_out[lpm_width-1:0]),
90
  .overflow                   (overflow_because_negative_number_was_max),  // OPTIONAL
91
  .data                       (data_in[lpm_width-1:0])
92
);
93
 
94
module lpm_counter (
95
#( 1,                         // lpm_width (width of input)
96
   0,                         // lpm_modulus (max count plus 1)
97
   "UNUSED",                  // lpm_direction, optional, {UNUSED, UP, DOWN}
98
   "UNUSED",                  // lpm_avalue, value to load if ASET active
99
   "UNUSED",                  // lpm_svalue, value to load if SSET active
100
   "UNUSED",                  // lpm_pvalue, value to load at powerup
101
   "lpm_counter",             // lpm_type, optional, must be "lpm_counter if lpm_hint used
102
   "UNUSED"                   // lpm_hint, optional, {UNSIGNED, SIGNED, BCD, GRAY_CODE, JOHNSON, LFSR}
103
 ) lpm_counter_example (
104
  .cout                       (max_value_reached),                       // CHOICE
105
  .q                          (counter_out[lpm_width-1:0]),              // CHOICE
106
  .data                       (sync_data_in[lpm_width-1:0]),             // OPTIONAL
107
  .sload                      (load_counter_with_data_next_clock),       // OPTIONAL
108
  .sset                       (set_counter_to_max_or_lpm_svalue_next_clock),  // OPTIONAL
109
  .sclr                       (clear_counter_next_clock),                // OPTIONAL
110
  .cnt_en                     (enable_counting_when_HIGH),               // OPTIONAL
111
  .cin                        (carry_in_to_enable_counter),              // OPTIONAL
112
  .updown                     (inc_if_HIGH_must_set_LOW_if_using_lpm_direction),  // OPTIONAL
113
  .clock                      (clock_if_pipelined),
114
  .clk_en                     (enable_all_sync_activity_when_HIGH),      // OPTIONAL
115
  .aload                      (async_load_counter_with_data),            // OPTIONAL
116
  .aset                       (async_set_counter_to_max_or_lpm_avalue),  // OPTIONAL
117
  .aclr                       (async_clear_if_pipelined)                 // OPTIONAL
118
);
119
*/
120
 
121
//------------------------------------------------------------------------
122
// LPM Synthesizable Models
123
//------------------------------------------------------------------------
124
// Version 1.5 (lpm 220)      Date 12/17/99
125
//
126
// Modified LPM_ADD_SUB and LPM_MULT to accomodate LPM_WIDTH = 1.
127
//   Default values for LPM_WIDTH* are changed back to 1.
128
// Added LPM_HINT to LPM_DIVIDE.
129
// Rewritten LPM_FIFO_DC to output correctly.
130
// Modified LPM_FIFO to output 0s before first read, output correct
131
//   values after aclr and sclr, and output LPM_NUMWORDS mod
132
//   exp(2, LPM_WIDTHU) when FIFO is full.
133
//
134
//------------------------------------------------------------------------
135
// Version 1.4.1 (lpm 220)    Date 10/29/99
136
//
137
// Default values for LPM_WIDTH* of LPM_ADD_SUB and LPM_MULT are changed
138
//   from 1 to 2.
139
//
140
//------------------------------------------------------------------------
141
// Version 1.4 (lpm 220)      Date 10/18/99
142
//
143
// Default values for each optional inputs for ALL modules are added.
144
// Some LPM_PVALUE implementations were missing, and now implemented.
145
//
146
//------------------------------------------------------------------------
147
// Version 1.3 (lpm 220)      Date 06/23/99
148
//
149
// Corrected LPM_FIFO and LPM_FIFO_DC cout and empty/full flags.
150
// Implemented LPM_COUNTER cin/cout, and LPM_MODULUS is now working.
151
//
152
//------------------------------------------------------------------------
153
// Version 1.2 (lpm 220)      Date 06/16/99
154
//
155
// Added LPM_RAM_DP, LPM_RAM_DQ, LPM_IO, LPM_ROM, LPM_FIFO, LPM_FIFO_DC.
156
// Parameters and ports are added/discarded according to the spec.
157
//
158
//------------------------------------------------------------------------
159
// Version 1.1 (lpm 220)      Date 02/05/99
160
//
161
// Added LPM_DIVIDE module.
162
//
163
//------------------------------------------------------------------------
164
// Version 1.0                Date 07/09/97
165
//
166
//------------------------------------------------------------------------
167
// Excluded Functions:
168
//
169
//  LPM_FSM and LPM_TTABLE.
170
//
171
//------------------------------------------------------------------------
172
// Assumptions:
173
//
174
// 1. LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, and LPM_NUMWORDS,
175
//    LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE  default value is
176
//    string UNUSED.
177
//
178
//------------------------------------------------------------------------
179
// Verilog Language Issues:
180
//
181
// Two dimensional ports are not supported. Modules with two dimensional
182
// ports are implemented as one dimensional signal of (LPM_SIZE * LPM_WIDTH)
183
// bits wide.
184
//
185
//------------------------------------------------------------------------
186
// Synthesis Issues:
187
// 
188
// 1. LPM_COUNTER 
189
//
190
// Currently synthesis tools do not allow mixing of level and edge
191
// sensetive signals. To overcome that problem the "data" signal is
192
// removed from the clock always block of lpm_counter, however the
193
// synthesis result is accurate. For correct simulation add the "data"
194
// pin to the sensetivity list as follows:
195
//
196
//  always @(posedge clock or posedge aclr or posedge aset or 
197
//           posedge aload or data)
198
//------------------------------------------------------------------------
199
 
200
module lpm_add_sub ( result, cout, overflow,
201
                                         add_sub, cin, dataa, datab, clock, clken, aclr );
202
 
203
// NOTE: Parameters must be declared in the same order as the Properties
204
//       are specified in the Cell Specification document.
205
        parameter lpm_width = 1;
206
        parameter lpm_direction  = "UNUSED";
207
        parameter lpm_representation = "UNSIGNED";
208
        parameter lpm_pipeline = 0;
209
        parameter lpm_type = "lpm_add_sub";
210
        parameter lpm_hint = "UNUSED";
211
        parameter lpm_source_version = "lpm 220 version 1.6";
212
 
213
        input  [lpm_width-1:0] dataa, datab;
214
        input  add_sub, cin;
215
        input  clock;
216
        input  clken;
217
        input  aclr;
218
        output [lpm_width-1:0] result;
219
        output cout, overflow;
220
 
221
        reg  [lpm_width-1:0] tmp_result;
222
        reg  [lpm_width-1:0] tmp_result2 [lpm_pipeline:0];
223
        reg  [lpm_pipeline:0] tmp_cout2;
224
        reg  [lpm_pipeline:0] tmp_overflow2;
225
        reg  tmp_cout;
226
        reg  tmp_overflow;
227
        reg  [lpm_width-1:0] tmp_a, tmp_b;
228
        integer i, j, k, n;
229
        integer dataa_int, datab_int, result_int, compare, borrow;
230
 
231
        tri0 aclr;
232
        tri0 clock;
233
        tri1 clken;
234
        tri0 cin;
235
        tri1 add_sub;
236
 
237
        buf (i_aclr, aclr);
238
        buf (i_clock, clock);
239
        buf (i_clken, clken);
240
        buf (i_cin, cin);
241
        buf (i_add_sub, add_sub);
242
 
243
 
244
        always @(i_cin or dataa or datab or i_add_sub)
245
        begin
246
                borrow = i_cin ? 0 : 1;
247
                // cout is the same for both signed and unsign representation.  
248
                if (lpm_direction == "ADD" || i_add_sub == 1)
249
                begin
250
                        {tmp_cout,tmp_result} = dataa + datab + i_cin;
251
                        tmp_overflow = tmp_cout;
252
                end
253
                else if (lpm_direction == "SUB" || i_add_sub == 0)
254
                begin
255
                        // subtraction
256
                        {tmp_overflow, tmp_result} = dataa - datab - borrow;
257
                        tmp_cout = (dataa >= (datab+borrow))?1:0;
258
                end
259
 
260
                if (lpm_representation == "SIGNED")
261
                begin
262
                        // convert to negative integer
263
                        if (dataa[lpm_width-1] == 1)
264
                        begin
265
                                for (j = 0; j < lpm_width; j = j + 1)
266
                                        tmp_a[j] = dataa[j] ^ 1;
267
                                dataa_int = (tmp_a) * (-1) - 1;
268
                        end
269
                        else
270
                                dataa_int = dataa;
271
 
272
                        // convert to negative integer
273
                        if (datab[lpm_width-1] == 1)
274
                        begin
275
                                for (k = 0; k < lpm_width; k = k + 1)
276
                                        tmp_b[k] = datab[k] ^ 1;
277
                                datab_int = (tmp_b) * (-1) - 1;
278
                        end
279
                        else
280
                                datab_int = datab;
281
 
282
                        // perform the addtion or subtraction operation
283
                        if (lpm_direction == "ADD" || i_add_sub == 1)
284
                                result_int = dataa_int + datab_int + i_cin;
285
                        else if (lpm_direction == "SUB" || i_add_sub == 0)
286
                                result_int = dataa_int - datab_int - borrow;
287
                        tmp_result = result_int;
288
 
289
                        // set the overflow
290
                        compare = 1 << (lpm_width -1);
291
                        if ((result_int > (compare - 1)) || (result_int < (-1)*(compare)))
292
                                tmp_overflow = 1;
293
                        else
294
                                tmp_overflow = 0;
295
                end
296
        end
297
 
298
 
299
        always @(posedge i_clock or posedge i_aclr)
300
        begin
301
                if (i_aclr)
302
                begin
303
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
304
                        begin
305
                                tmp_result2[i] = 'b0;
306
                                tmp_cout2[i] = 1'b0;
307
                                tmp_overflow2[i] = 1'b0;
308
                        end
309
                end
310
                else if (i_clken == 1)
311
                begin
312
                        tmp_result2[lpm_pipeline] = tmp_result;
313
                        tmp_cout2[lpm_pipeline] = tmp_cout;
314
                        tmp_overflow2[lpm_pipeline] = tmp_overflow;
315
                        for (n = 0; n < lpm_pipeline; n = n + 1)
316
                        begin
317
                                tmp_result2[n] = tmp_result2[n+1];
318
                                tmp_cout2[n] = tmp_cout2[n+1];
319
                                tmp_overflow2[n] = tmp_overflow2[n+1];
320
                        end
321
                end
322
        end
323
 
324
 
325
        assign result = (lpm_pipeline >0) ? tmp_result2[0]:tmp_result;
326
        assign cout = (lpm_pipeline >0) ? tmp_cout2[0]  : tmp_cout;
327
        assign overflow = (lpm_pipeline >0) ? tmp_overflow2[0] : tmp_overflow;
328
 
329
// Check for previous Parameter declaration order
330
initial if ((lpm_width === "lpm_add_sub") || (lpm_type !== "lpm_add_sub"))
331
  begin
332
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
333
    $finish;
334
  end
335
endmodule // lpm_add_sub
336
 
337
//------------------------------------------------------------------------
338
 
339
module lpm_compare ( alb, aeb, agb, aleb, aneb, ageb, dataa, datab,
340
                                         clock, clken, aclr );
341
 
342
// NOTE: Parameters must be declared in the same order as the Properties
343
//       are specified in the Cell Specification document.
344
        parameter lpm_width = 1;
345
        parameter lpm_representation = "UNSIGNED";
346
        parameter lpm_pipeline = 0;
347
        parameter lpm_type = "lpm_compare";
348
        parameter lpm_hint = "UNUSED";
349
        parameter lpm_source_version = "lpm 220 version 1.6";
350
 
351
        input  [lpm_width-1:0] dataa, datab;
352
        input  clock;
353
        input  clken;
354
        input  aclr;
355
        output alb, aeb, agb, aleb, aneb, ageb;
356
 
357
        reg    tmp_alb, tmp_aeb, tmp_agb;
358
        reg    tmp_aleb, tmp_aneb, tmp_ageb;
359
        reg    [lpm_pipeline:0] tmp_alb2, tmp_aeb2, tmp_agb2;
360
        reg    [lpm_pipeline:0] tmp_aleb2, tmp_aneb2, tmp_ageb2;
361
        reg    [lpm_width-1:0] a_int;
362
        integer i, j, k, l, m, n, o, p, u, dataa_int, datab_int;
363
 
364
        tri0 aclr;
365
        tri0 clock;
366
        tri1 clken;
367
 
368
        buf (i_aclr, aclr);
369
        buf (i_clock, clock);
370
        buf (i_clken, clken);
371
 
372
 
373
        always @(dataa or datab)
374
        begin
375
                if (lpm_representation == "UNSIGNED")
376
                begin
377
                        dataa_int = dataa[lpm_width-1:0];
378
                        datab_int = datab[lpm_width-1:0];
379
                end
380
                else if (lpm_representation == "SIGNED")
381
                begin
382
                        // convert to negative integer
383
                        if (dataa[lpm_width-1] == 1)
384
                        begin
385
                                for (j = 0; j < lpm_width; j = j + 1)
386
                                        a_int[j] = dataa[j] ^ 1;
387
                                dataa_int = (a_int) * (-1) - 1;
388
                        end
389
                        else
390
                                dataa_int = dataa;
391
 
392
                        // convert to negative integer
393
                        if (datab[lpm_width-1] == 1)
394
                        begin
395
                                for (j = 0; j < lpm_width; j = j + 1)
396
                                        a_int[j] = datab[j] ^ 1;
397
                                datab_int = (a_int) * (-1) - 1;
398
                        end
399
                        else
400
                                datab_int = datab;
401
                end
402
 
403
                tmp_alb = (dataa_int < datab_int);
404
                tmp_aeb = (dataa_int == datab_int);
405
                tmp_agb = (dataa_int > datab_int);
406
                tmp_aleb = (dataa_int <= datab_int);
407
                tmp_aneb = (dataa_int != datab_int);
408
                tmp_ageb = (dataa_int >= datab_int);
409
        end
410
 
411
        always @(posedge i_clock or posedge i_aclr)
412
        begin
413
                if (i_aclr)
414
                begin
415
                        for (u = 0; u <= lpm_pipeline; u = u +1)
416
                        begin
417
                                tmp_aeb2[u] = 'b0;
418
                                tmp_agb2[u] = 'b0;
419
                                tmp_alb2[u] = 'b0;
420
                                tmp_aleb2[u] = 'b0;
421
                                tmp_aneb2[u] = 'b0;
422
                                tmp_ageb2[u] = 'b0;
423
                        end
424
                end
425
                else if (i_clken == 1)
426
                begin
427
                        // Assign results to registers
428
                        tmp_alb2[lpm_pipeline] = tmp_alb;
429
                        tmp_aeb2[lpm_pipeline] = tmp_aeb;
430
                        tmp_agb2[lpm_pipeline] = tmp_agb;
431
                        tmp_aleb2[lpm_pipeline] = tmp_aleb;
432
                        tmp_aneb2[lpm_pipeline] = tmp_aneb;
433
                        tmp_ageb2[lpm_pipeline] = tmp_ageb;
434
 
435
                        for (k = 0; k < lpm_pipeline; k = k +1)
436
                                tmp_alb2[k] = tmp_alb2[k+1];
437
                        for (l = 0; l < lpm_pipeline; l = l +1)
438
                                tmp_aeb2[l] = tmp_aeb2[l+1];
439
                        for (m = 0; m < lpm_pipeline; m = m +1)
440
                                tmp_agb2[m] = tmp_agb2[m+1];
441
                        for (n = 0; n < lpm_pipeline; n = n +1)
442
                                tmp_aleb2[n] = tmp_aleb2[n+1];
443
                        for (o = 0; o < lpm_pipeline; o = o +1)
444
                                tmp_aneb2[o] = tmp_aneb2[o+1];
445
                        for (p = 0; p < lpm_pipeline; p = p +1)
446
                                tmp_ageb2[p] = tmp_ageb2[p+1];
447
                end
448
        end
449
 
450
        assign alb = (lpm_pipeline > 0) ? tmp_alb2[0] : tmp_alb;
451
        assign aeb = (lpm_pipeline > 0) ? tmp_aeb2[0] : tmp_aeb;
452
        assign agb = (lpm_pipeline > 0) ? tmp_agb2[0] : tmp_agb;
453
        assign aleb = (lpm_pipeline > 0) ? tmp_aleb2[0] : tmp_aleb;
454
        assign aneb = (lpm_pipeline > 0) ? tmp_aneb2[0] : tmp_aneb;
455
        assign ageb = (lpm_pipeline > 0) ? tmp_ageb2[0] : tmp_ageb;
456
 
457
// Check for previous Parameter declaration order
458
initial if ((lpm_width === "lpm_compare") || (lpm_type !== "lpm_compare"))
459
  begin
460
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
461
    $finish;
462
  end
463
endmodule // lpm_compare
464
 
465
//------------------------------------------------------------------------
466
 
467
module lpm_mult ( result, dataa, datab, sum, clock, clken, aclr );
468
 
469
// NOTE: Parameters must be declared in the same order as the Properties
470
//       are specified in the Cell Specification document.
471
        parameter lpm_widtha = 1;
472
        parameter lpm_widthb = 1;
473
        parameter lpm_widths = 1;
474
        parameter lpm_widthp = 1;
475
        parameter lpm_representation  = "UNSIGNED";
476
        parameter lpm_pipeline  = 0;
477
        parameter lpm_type = "lpm_mult";
478
        parameter lpm_hint = "UNUSED";
479
        parameter lpm_source_version = "lpm 220 version 1.6";
480
 
481
        input  clock;
482
        input  clken;
483
        input  aclr;
484
        input  [lpm_widtha-1:0] dataa;
485
        input  [lpm_widthb-1:0] datab;
486
        input  [lpm_widths-1:0] sum;
487
        output [lpm_widthp-1:0] result;
488
 
489
        // inernal reg
490
        reg   [lpm_widthp-1:0] tmp_result;
491
        reg   [lpm_widthp-1:0] tmp_result2 [lpm_pipeline:0];
492
        reg   [lpm_widtha-1:0] a_int;
493
        reg   [lpm_widthb-1:0] b_int;
494
        reg   [lpm_widths-1:0] s_int;
495
        reg   [lpm_widthp-1:0] p_reg;
496
        integer p_int;
497
        integer i, j, k, m, n, p, maxs_mn;
498
        integer int_dataa, int_datab, int_sum, int_result;
499
 
500
        tri0 aclr;
501
        tri0 clock;
502
        tri1 clken;
503
 
504
        buf (i_aclr, aclr);
505
        buf (i_clock, clock);
506
        buf (i_clken, clken);
507
 
508
 
509
        always @(dataa or datab or sum)
510
        begin
511
                if (lpm_representation == "UNSIGNED")
512
                begin
513
                        int_dataa = dataa;
514
                        int_datab = datab;
515
                        int_sum = sum;
516
                end
517
                else if (lpm_representation == "SIGNED")
518
                begin
519
                        // convert signed dataa
520
                        if (dataa[lpm_widtha-1] == 1)
521
                        begin
522
                                for (i = 0; i < lpm_widtha; i = i + 1)
523
                                        a_int[i] = dataa[i] ^ 1;
524
                                int_dataa = (a_int) * (-1) - 1;
525
                        end
526
                        else
527
                                int_dataa = dataa;
528
 
529
                        // convert signed datab
530
                        if (datab[lpm_widthb-1] == 1)
531
                        begin
532
                                for (j = 0; j < lpm_widthb; j = j + 1)
533
                                        b_int[j] = datab[j] ^ 1;
534
                                int_datab = (b_int) * (-1) - 1;
535
                        end
536
                        else
537
                                int_datab = datab;
538
 
539
                        // convert signed sum
540
                        if (sum[lpm_widths-1] == 1)
541
                        begin
542
                                for (k = 0; k < lpm_widths; k = k + 1)
543
                                        s_int[k] = sum[k] ^ 1;
544
                                int_sum = (s_int) * (-1) - 1;
545
                        end
546
                        else
547
                                int_sum = sum;
548
                end
549
                else
550
                begin
551
                        int_dataa = {lpm_widtha{1'bx}};
552
                        int_datab = {lpm_widthb{1'bx}};
553
                        int_sum   = {lpm_widths{1'bx}};
554
                end
555
 
556
                p_int = int_dataa * int_datab + int_sum;
557
                maxs_mn = ((lpm_widtha+lpm_widthb)>lpm_widths)?lpm_widtha+lpm_widthb:lpm_widths;
558
                if (lpm_widthp >= maxs_mn)
559
                        tmp_result = p_int;
560
                else
561
                begin
562
                        p_reg = p_int;
563
                        for (m = 0; m < lpm_widthp; m = m + 1)
564
                                tmp_result[lpm_widthp-1-m] = p_reg[maxs_mn-1-m];
565
                end
566
        end
567
 
568
        always @(posedge i_clock or posedge i_aclr)
569
        begin
570
          if (i_aclr)
571
                begin
572
                        for (p = 0; p <= lpm_pipeline; p = p + 1)
573
                                tmp_result2[p] = 'b0;
574
                end
575
          else if (i_clken == 1)
576
          begin :syn_block
577
                tmp_result2[lpm_pipeline] = tmp_result;
578
                for (n = 0; n < lpm_pipeline; n = n +1)
579
                        tmp_result2[n] = tmp_result2[n+1];
580
          end
581
        end
582
 
583
  assign result = (lpm_pipeline > 0) ? tmp_result2[0] : tmp_result;
584
 
585
// Check for previous Parameter declaration order
586
initial if ((lpm_widtha === "lpm_mult") || (lpm_type !== "lpm_mult"))
587
  begin
588
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
589
    $finish;
590
  end
591
endmodule // lpm_mult
592
 
593
//------------------------------------------------------------------------
594
 
595
module lpm_divide ( quotient,remain, numer, denom, clock, clken, aclr );
596
 
597
// NOTE: Parameters must be declared in the same order as the Properties
598
//       are specified in the Cell Specification document.
599
        parameter lpm_widthn = 1;
600
        parameter lpm_widthd = 1;
601
        //parameter lpm_widthq = 1;
602
        //parameter lpm_widthr = 1;
603
        parameter lpm_nrepresentation = "UNSIGNED";
604
        parameter lpm_drepresentation = "UNSIGNED";
605
        parameter lpm_pipeline = 0;
606
        parameter lpm_type = "lpm_divide";
607
        parameter lpm_hint = "UNUSED";
608
        parameter lpm_source_version = "lpm 220 version 1.6";
609
 
610
        input  clock;
611
        input  clken;
612
        input  aclr;
613
        input  [lpm_widthn-1:0] numer;
614
        input  [lpm_widthd-1:0] denom;
615
        output [lpm_widthn-1:0] quotient;
616
        output [lpm_widthd-1:0] remain;
617
 
618
        // inernal reg
619
        reg   [lpm_widthn-1:0] tmp_quotient [lpm_pipeline:0];
620
        reg   [lpm_widthd-1:0] tmp_remain [lpm_pipeline:0];
621
        reg   [lpm_widthn-1:0] ONES, ZEROS, UNKNOWN, HiZ;
622
        reg   [lpm_widthd-1:0] DZEROS, DUNKNOWN;
623
        reg   [lpm_widthn-1:0] NUNKNOWN;
624
        reg   [lpm_widthd-1:0] RZEROS ;
625
        integer i;
626
        integer int_numer, int_denom, int_quotient, int_remain;
627
 
628
        tri0 aclr;
629
        tri0 clock;
630
        tri1 clken;
631
 
632
        buf (i_aclr, aclr);
633
        buf (i_clock, clock);
634
        buf (i_clken, clken);
635
 
636
 
637
        initial
638
        begin
639
 
640
        // check if lpm_widthn > 0
641
        if (lpm_widthn <= 0)
642
                $display("%t: Error! LPM_WIDTHN must be greater than 0.\n", $time);
643
        // check if lpm_widthd > 0
644
        if (lpm_widthd <= 0)
645
                $display("%t: Error! LPM_WIDTHD must be greater than 0.\n", $time);
646
        // check if lpm_widthn > 0
647
                //if (lpm_widthq <= 0)
648
                //    $display("%t: Error! LPM_WIDTHQ must be greater than 0.\n", $time);
649
        // check if lpm_widthR > 0
650
                //if (lpm_widthr <= 0)
651
                //    $display("%t: Error! LPM_WIDTHR must be greater than 0.\n", $time);
652
        // check for valid lpm_nrep value
653
        if ((lpm_nrepresentation !== "SIGNED") && (lpm_nrepresentation !== "UNSIGNED"))
654
                $display("%t: Error! LPM_NREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".", $time);
655
 
656
        // check for valid lpm_drep value
657
        if ((lpm_drepresentation !== "SIGNED") && (lpm_drepresentation !== "UNSIGNED"))
658
                $display("%t: Error! LPM_DREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".", $time);
659
 
660
        // check if lpm_pipeline is > 1 and clock is not used
661
        if ((lpm_pipeline >=1) && (clock === 1'bz))
662
                $display("%t: Error! The clock pin is requied if lpm_pipeline is used\n", $time);
663
        else if ((lpm_pipeline == 0) && (clock !== 1'bz))
664
                $display("%t: Error! If the clock pin is used, lpm_pipeline must be greater than 0.\n", $time);
665
 
666
        for (i=0; i < lpm_widthn; i=i+1)
667
        begin
668
                ONES[i] = 1'b1;
669
                ZEROS[i] = 1'b0;
670
                UNKNOWN[i] = 1'bx;
671
                HiZ[i] = 1'bz;
672
        end
673
 
674
        for (i=0; i < lpm_widthd; i=i+1)
675
                DUNKNOWN[i] = 1'bx;
676
 
677
        for (i=0; i < lpm_widthn; i=i+1)
678
                NUNKNOWN[i] = 1'bx;
679
 
680
        for (i=0; i < lpm_widthd; i=i+1)
681
                RZEROS[i] = 1'b0;
682
 
683
        end
684
 
685
        always @(numer or denom)
686
        begin
687
                if (lpm_nrepresentation == "UNSIGNED")
688
                        int_numer = numer;
689
                else if (lpm_nrepresentation == "SIGNED")
690
                begin
691
                        // convert signed numer
692
                        if (numer[lpm_widthn-1] == 1)
693
                        begin
694
                                int_numer = 0;
695
                                for (i = 0; i < lpm_widthn - 1; i = i + 1)
696
                                        int_numer[i] = numer[i] ^ 1;
697
                                int_numer = -(int_numer + 1);
698
                        end
699
                        else
700
                                int_numer = numer;
701
                end
702
                else
703
                        int_numer = NUNKNOWN;
704
 
705
                if (lpm_drepresentation == "UNSIGNED")
706
                        int_denom = denom;
707
                else if (lpm_drepresentation == "SIGNED")
708
                begin
709
                        // convert signed denom
710
                        if (denom[lpm_widthd-1] == 1)
711
                        begin
712
                                int_denom = 0;
713
                                for (i = 0; i < lpm_widthd - 1; i = i + 1)
714
                                        int_denom[i] = denom[i] ^ 1;
715
                                int_denom = -(int_denom + 1);
716
                        end
717
                        else
718
                                int_denom = denom;
719
                end
720
                else
721
                        int_denom = DUNKNOWN;
722
 
723
                int_quotient = int_numer / int_denom;
724
                int_remain = int_numer % int_denom;
725
 
726
                tmp_quotient[lpm_pipeline] = int_quotient;
727
                tmp_remain[lpm_pipeline] = int_remain;
728
        end
729
 
730
        always @(posedge i_clock or i_aclr)
731
        begin :syn_block
732
                if (i_aclr)
733
                begin
734
                        disable syn_block;
735
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
736
                                tmp_quotient[i] = ZEROS;
737
                        tmp_remain[i] = RZEROS;
738
                end
739
                else if (i_clken)
740
                        for (i = 0; i < lpm_pipeline; i = i +1)
741
                        begin
742
                                tmp_quotient[i] = tmp_quotient[i+1];
743
                                tmp_remain[i] = tmp_remain[i+1];
744
                        end
745
        end
746
 
747
        assign quotient = tmp_quotient[0];
748
        assign remain = tmp_remain[0];
749
 
750
// Check for previous Parameter declaration order
751
initial if ((lpm_widthn === "lpm_divide") || (lpm_type !== "lpm_divide"))
752
  begin
753
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
754
    $finish;
755
  end
756
endmodule // lpm_divide
757
 
758
//------------------------------------------------------------------------
759
 
760
module lpm_abs ( result, overflow, data );
761
 
762
// NOTE: Parameters must be declared in the same order as the Properties
763
//       are specified in the Cell Specification document.
764
        parameter lpm_width = 1;
765
        parameter lpm_type = "lpm_abs";
766
        parameter lpm_hint = "UNUSED";
767
        parameter lpm_source_version = "lpm 220 version 1.6";
768
 
769
        input  [lpm_width-1:0] data;
770
        output [lpm_width-1:0] result;
771
        output overflow;
772
 
773
        reg    [lpm_width-1:0] a_int;
774
        reg    [lpm_width-1:0] result;
775
        reg    overflow;
776
        integer i;
777
 
778
        always @(data)
779
        begin
780
                overflow = 0;
781
                if (data[lpm_width-1] == 1)
782
                begin
783
                        for (i = 0; i < lpm_width; i = i + 1)
784
                                a_int[i] = data[i] ^ 1;
785
                        result = (a_int + 1);
786
                        overflow = (result == ( 1<<(lpm_width -1)));
787
                end
788
                else
789
                        result = data;
790
        end
791
 
792
// Check for previous Parameter declaration order
793
initial if ((lpm_width === "lpm_abs") || (lpm_type !== "lpm_abs"))
794
  begin
795
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
796
    $finish;
797
  end
798
endmodule // lpm_abs
799
 
800
//------------------------------------------------------------------------
801
 
802
module lpm_counter ( q, data, clock, cin, cout,clk_en, cnt_en, updown,
803
                                         aset, aclr, aload, sset, sclr, sload );
804
 
805
// NOTE: Parameters must be declared in the same order as the Properties
806
//       are specified in the Cell Specification document.
807
        parameter lpm_width = 1;
808
        parameter lpm_modulus = 0;
809
        parameter lpm_direction = "UNUSED";
810
        parameter lpm_avalue = "UNUSED";
811
        parameter lpm_svalue = "UNUSED";
812
        parameter lpm_pvalue = "UNUSED";
813
        parameter lpm_type = "lpm_counter";
814
        parameter lpm_hint = "UNUSED";
815
        parameter lpm_source_version = "lpm 220 version 1.6";
816
 
817
        output [lpm_width-1:0] q;
818
        //output [lpm_modulus-1:0] eq;
819
        output cout;
820
        input  cin;
821
        input  [lpm_width-1:0] data;
822
        input  clock, clk_en, cnt_en, updown;
823
        input  aset, aclr, aload;
824
        input  sset, sclr, sload;
825
 
826
        reg  [lpm_width-1:0] tmp_count;
827
        reg  tmp_updown;
828
        integer tmp_modulus;
829
 
830
        tri1 clk_en;
831
        tri1 cnt_en;
832
        tri1 updown;
833
        tri0 sload;
834
        tri0 sset;
835
        tri0 sclr;
836
        tri0 aload;
837
        tri0 aset;
838
        tri0 aclr;
839
        tri0 cin;
840
 
841
        buf (i_clk_en, clk_en);
842
        buf (i_cnt_en, cnt_en);
843
        buf (i_updown, updown);
844
        buf (i_sload, sload);
845
        buf (i_sset, sset);
846
        buf (i_sclr, sclr);
847
        buf (i_aload, aload);
848
        buf (i_aset, aset);
849
        buf (i_aclr, aclr);
850
        buf (i_cin, cin);
851
 
852
 
853
//---------------------------------------------------------------//
854
        function [lpm_width-1:0] NextBin;
855
                input [lpm_width-1:0] count;
856
 
857
                //reg  [lpm_width-1:0] re_start;
858
                //reg  [lpm_width-1:0] tmp_nextbin;
859
                //integer up_limit;
860
 
861
                begin
862
                        if (tmp_updown == 1)
863
                        begin
864
                                if (i_cin == 1 && count == tmp_modulus-2)
865
                                        NextBin = 0;
866
                                else
867
                                        NextBin = (count >= tmp_modulus-1) ? i_cin : count+1+i_cin;
868
                        end
869
                        else
870
                        begin
871
                                if (i_cin == 1 && count == 1)
872
                                        NextBin = tmp_modulus - 1;
873
                                else
874
                                        NextBin = (count <= 0) ? tmp_modulus-1-i_cin : count-1-i_cin;
875
                        end
876
                end
877
        endfunction
878
 
879
//---------------------------------------------------------------//
880
//  function [(1<<lpm_width)-1:0] CountDecode;
881
//---------------------------------------------------------------//
882
//  function [lpm_modulus:0] CountDecode;
883
//      input [lpm_width-1:0] count;
884
//
885
//      integer eq_index;
886
//
887
//      begin
888
//          CountDecode = 0;
889
//          eq_index = 0;
890
//          if (count < lpm_modulus)
891
//          begin
892
//              eq_index = count;
893
//              CountDecode[eq_index] = 1'b1;
894
//          end
895
//      end
896
//  endfunction
897
 
898
//---------------------------------------------------------------//
899
//  function integer str_to_int;
900
//---------------------------------------------------------------//
901
        function integer str_to_int;
902
                input  [8*16:1] s;
903
 
904
                reg [8*16:1] reg_s;
905
                reg [8:1] digit;
906
                reg [8:1] tmp;
907
                integer m, ivalue;
908
 
909
                begin
910
                        ivalue = 0;
911
                        reg_s = s;
912
                        for (m=1; m<=16; m=m+1)
913
                        begin
914
                                tmp = reg_s[128:121];
915
                                digit = tmp & 8'b00001111;
916
                                reg_s = reg_s << 8;
917
                                ivalue = ivalue * 10 + digit;
918
                        end
919
                        str_to_int = ivalue;
920
                end
921
        endfunction
922
 
923
//---------------------------------------------------------------//
924
 
925
        initial
926
        begin
927
                // check if lpm_modulus < 0
928
                if (lpm_modulus < 0)
929
                        $display("%t: Error! LPM_MODULUS must be greater than 0.\n", $time);
930
                // check if lpm_modulus > 1<<lpm_width
931
                if (lpm_modulus > 1<<lpm_width)
932
                        $display("%t: Error! LPM_MODULUS must be less than or equal to 1<<LPM_WIDTH.\n", $time);
933
 
934
                if (lpm_direction == "UNUSED")
935
                        tmp_updown = (i_updown == 0) ? 0 : 1;
936
                else
937
                        tmp_updown = (lpm_direction == "DOWN") ? 0 : 1;
938
 
939
                tmp_modulus = (lpm_modulus == 0) ? (1 << lpm_width) : lpm_modulus;
940
                tmp_count = (lpm_pvalue == "UNUSED") ? 0 : str_to_int(lpm_pvalue);
941
        end
942
 
943
        always @(i_updown)
944
        begin
945
                if (lpm_direction == "UNUSED")
946
                        tmp_updown = (i_updown == 0) ? 0 : 1;
947
                else
948
                        $display("%t: Error! LPM_DIRECTION and UPDOWN cannot be used at the same time.\n", $time);
949
        end
950
 
951
        always @(posedge clock or posedge i_aclr or posedge i_aset or
952
                          posedge i_aload)
953
        begin :asyn_block
954
                if (i_aclr)
955
                        tmp_count = 0;
956
                else if (i_aset)
957
                        tmp_count = (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
958
                                                                                                 : str_to_int(lpm_avalue);
959
                else if (i_aload)
960
                        tmp_count = data;
961
                else
962
                begin :syn_block
963
                        if (i_clk_en)
964
                        begin
965
                                if (i_sclr)
966
                                        tmp_count = 0;
967
                                else if (i_sset)
968
                                        tmp_count = (lpm_svalue == "UNUSED") ? {lpm_width{1'b1}}
969
                                                                                                                 : str_to_int(lpm_svalue);
970
                                else if (i_sload)
971
                                        tmp_count = data;
972
                                else if (i_cnt_en)
973
                                        tmp_count = NextBin(tmp_count);
974
                        end
975
                end
976
        end
977
 
978
        assign q =  tmp_count;
979
        //assign eq = CountDecode(tmp_count);
980
        assign cout = (((tmp_count >= tmp_modulus-1-i_cin) && tmp_updown)
981
                                  || ((tmp_count <= i_cin) && !tmp_updown)) ? 1 : 0;
982
 
983
// Check for previous Parameter declaration order
984
initial if ((lpm_width === "lpm_counter") || (lpm_type !== "lpm_counter"))
985
  begin
986
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
987
    $finish;
988
  end
989
endmodule // lpm_counter

powered by: WebSVN 2.1.0

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