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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [orp/] [orp_soc/] [lib/] [altera/] [220model.v] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1136 lampret
//------------------------------------------------------------------------
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
// LPM Synthesizable Models 
12
// These models are based on LPM version 220 (EIA-IS103 October 1998).
13
//-----------------------------------------------------------------------
14
// Version Quartus v2.0 (lpm 220)      Date 08/28/01
15
//
16
// 08/28/01: Support for non-pli flow for convert_hex2ver
17
//
18
//----------------------------------------------------------------------- 
19
// Version Quartus v1.1 (lpm 220)      Date 04/17/01
20
//
21
// 04/09/01: Fix 82832; inappropriate use of blocking assignments in
22
//           lpm_ram_dq, lpm_ram_io, lpm_ram_dp, lpm_rom.
23
// 04/09/01: Make dcfifo and lpm_fifo_dc models consistent.
24
// 04/05/01: Fix 82832; race condition in lpm_ram_dq with VerilogXL.
25
// 03/20/01: Fix SPR 82096; the memenab & outenab signals are not 
26
//           initialized for lpm_ram_io.
27
// 01/23/01: Adding use_eab=on support for lpm_ram_io, lpm_ram_dp and
28
//           lpm_ram_dq.
29
//------------------------------------------------------------------------
30
// Version Quartus v1.0 (lpm 220)      Date 12/8/00
31
//
32
// 12/8/00: Fix SPR78303. Remove use of blocking assignments in
33
//          lpm_fifo_dc
34
// 12/5/00: Changed lpm_ram_dp rdclken, and wrclken to connect to pull up
35
//          properly.
36
//------------------------------------------------------------------------
37
// Version 1.6 (lpm 220)      Date 10/2/00
38
//
39
// Changed the behaviour of LPM_FIFO_DC to match that of Quartus.
40
// Changed data port of LPM_LATCH to be initialized with 0.
41
// Fixed LPM_COUNTER, LPM_FF, LPM_SHIFTREG to output correctly after
42
//   aclr goes low but before any clock edge, and to output x's when
43
//   both aclr and aset are high.
44
// Changed q port of LPM_FF and LPM_SHIFTREG to be initialized with 0.
45
// Fixed underflow and overflow port of LPM_CLSHIFT in ROTATE mode.
46
// Added LPM_REMAINDERPOSITIVE parameter to LPM_DIVIDE.  This is a
47
//   non-LPM 220 standard parameter.  It defaults to TRUE for LPM 220
48
//   behaviour.
49
// Fixed LPM_MULT to output correctly.
50
// Changed default value of CIN port of LPM_ADD_SUB when subtract.
51
// Changed output pipelines of LPM_ADD_SUB to be initialized with 0's.
52
// Fixed overflow port of LPM_ADD_SUB for singned inputs.
53
// Added DATA port to the sensitivity list in LPM_COUNTER and LPM_FF.
54
//   Synthesis tools do not allow mixing of level and edge sensitive
55
//   signals, and hence DATA port was omitted from the list.
56
// Corrected the interpretation of CIN port of LPM_COUNTER.
57
// Fixed LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO to write data at rising
58
//   clock edge and to output correctly.
59
// Fixed COUT port of LPM_COUNTER to go high when count is all 1's.
60
//
61
//------------------------------------------------------------------------
62
// Version 1.59 (lpm 220)     Date 5/4/00
63
//
64
// Corrected LPM_FIFO_DC rdempty flag.
65
// Updated comments in header about synthesis issues.
66
// Fixed error detection of LPM_DIRECTION and UPDOWN conflict in
67
//   LPM_COUNTER.
68
// Changed LPM_ROM to have no default name for initialization file.
69
//
70
//------------------------------------------------------------------------
71
// Version 1.5 (lpm 220)      Date 12/17/99
72
//
73
// Modified LPM_ADD_SUB and LPM_MULT to accomodate LPM_WIDTH = 1.
74
//   Default values for LPM_WIDTH* are changed back to 1.
75
// Added LPM_HINT to LPM_DIVIDE.
76
// Rewritten LPM_FIFO_DC to output correctly.
77
// Modified LPM_FIFO to output 0s before first read, output correct
78
//   values after aclr and sclr, and output LPM_NUMWORDS mod
79
//   exp(2, LPM_WIDTHU) when FIFO is full.
80
//
81
//------------------------------------------------------------------------
82
// Version 1.4.1 (lpm 220)    Date 10/29/99
83
//
84
// Default values for LPM_WIDTH* of LPM_ADD_SUB and LPM_MULT are changed
85
//   from 1 to 2.
86
//
87
//------------------------------------------------------------------------
88
// Version 1.4 (lpm 220)      Date 10/18/99
89
//
90
// Default values for each optional inputs for ALL modules are added.
91
// Some LPM_PVALUE implementations were missing, and now implemented.
92
//
93
//------------------------------------------------------------------------
94
// Version 1.3 (lpm 220)      Date 06/23/99
95
//
96
// Corrected LPM_FIFO and LPM_FIFO_DC cout and empty/full flags.
97
// Implemented LPM_COUNTER cin/cout, and LPM_MODULUS is now working.
98
//
99
//------------------------------------------------------------------------
100
// Version 1.2 (lpm 220)      Date 06/16/99
101
//
102
// Added LPM_RAM_DP, LPM_RAM_DQ, LPM_IO, LPM_ROM, LPM_FIFO, LPM_FIFO_DC.
103
// Parameters and ports are added/discarded according to the spec.
104
//
105
//------------------------------------------------------------------------
106
// Version 1.1 (lpm 220)      Date 02/05/99
107
//
108
// Added LPM_DIVIDE module.
109
//
110
//------------------------------------------------------------------------
111
// Version 1.0                Date 07/09/97
112
//
113
//------------------------------------------------------------------------
114
// Excluded Functions:
115
//
116
//  LPM_FSM and LPM_TTABLE.
117
//
118
//------------------------------------------------------------------------
119
// Assumptions:
120
//
121
// 1. The default value for LPM_SVALUE, LPM_AVALUE, LPM_PVALUE, and
122
//    LPM_STRENGTH is string UNUSED.
123
//
124
//------------------------------------------------------------------------
125
// Verilog Language Issues:
126
//
127
// Two dimensional ports are not supported. Modules with two dimensional
128
// ports are implemented as one dimensional signal of (LPM_SIZE * LPM_WIDTH)
129
// bits wide.
130
//
131
//------------------------------------------------------------------------
132
 
133
 
134
`define NO_PLI
135
 
136
module lpm_constant ( result );
137
 
138
        parameter lpm_type = "lpm_constant";
139
        parameter lpm_width = 1;
140
        parameter lpm_cvalue = 0;
141
        parameter lpm_strength = "UNUSED";
142
        parameter lpm_hint = "UNUSED";
143
 
144
        output [lpm_width-1:0] result;
145
 
146
        assign result = lpm_cvalue;
147
 
148
endmodule // lpm_constant
149
 
150
//------------------------------------------------------------------------
151
 
152
module lpm_inv ( result, data );
153
 
154
        parameter lpm_type = "lpm_inv";
155
        parameter lpm_width = 1;
156
        parameter lpm_hint = "UNUSED";
157
 
158
        input  [lpm_width-1:0] data;
159
        output [lpm_width-1:0] result;
160
 
161
        reg    [lpm_width-1:0] result;
162
 
163
    always @(data)
164
        result = ~data;
165
 
166
endmodule // lpm_inv
167
 
168
//------------------------------------------------------------------------
169
 
170
module lpm_and ( result, data );
171
 
172
        parameter lpm_type = "lpm_and";
173
        parameter lpm_width = 1;
174
        parameter lpm_size = 1;
175
        parameter lpm_hint = "UNUSED";
176
 
177
        input  [(lpm_size * lpm_width)-1:0] data;
178
        output [lpm_width-1:0] result;
179
 
180
        reg    [lpm_width-1:0] result;
181
        integer i, j, k;
182
 
183
        always @(data)
184
        begin
185
                for (i=0; i<lpm_width; i=i+1)
186
                begin
187
                        result[i] = data[i];
188
                        for (j=1; j<lpm_size; j=j+1)
189
                        begin
190
                                k = j * lpm_width + i;
191
                                result[i] = result[i] & data[k];
192
                        end
193
                end
194
        end
195
 
196
endmodule // lpm_and
197
 
198
//------------------------------------------------------------------------
199
 
200
module lpm_or ( result, data );
201
 
202
    parameter lpm_type = "lpm_or";
203
        parameter lpm_width = 1;
204
        parameter lpm_size = 1;
205
        parameter lpm_hint  = "UNUSED";
206
 
207
        input  [(lpm_size * lpm_width)-1:0] data;
208
        output [lpm_width-1:0] result;
209
 
210
        reg    [lpm_width-1:0] result;
211
        integer i, j, k;
212
 
213
        always @(data)
214
        begin
215
                for (i=0; i<lpm_width; i=i+1)
216
                begin
217
                        result[i] = data[i];
218
                        for (j=1; j<lpm_size; j=j+1)
219
                        begin
220
                                k = j * lpm_width + i;
221
                                result[i] = result[i] | data[k];
222
                        end
223
                end
224
        end
225
 
226
endmodule // lpm_or
227
 
228
//------------------------------------------------------------------------
229
 
230
module lpm_xor ( result, data );
231
 
232
        parameter lpm_type = "lpm_xor";
233
        parameter lpm_width = 1;
234
        parameter lpm_size = 1;
235
        parameter lpm_hint  = "UNUSED";
236
 
237
        input  [(lpm_size * lpm_width)-1:0] data;
238
        output [lpm_width-1:0] result;
239
 
240
        reg    [lpm_width-1:0] result;
241
        integer i, j, k;
242
 
243
        always @(data)
244
        begin
245
                for (i=0; i<lpm_width; i=i+1)
246
                begin
247
                        result[i] = data[i];
248
                        for (j=1; j<lpm_size; j=j+1)
249
                        begin
250
                                k = j * lpm_width + i;
251
                                result[i] = result[i] ^ data[k];
252
                        end
253
                end
254
        end
255
 
256
endmodule // lpm_xor
257
 
258
//------------------------------------------------------------------------
259
 
260
module lpm_bustri ( result, tridata, data, enabledt, enabletr );
261
 
262
        parameter lpm_type = "lpm_bustri";
263
        parameter lpm_width = 1;
264
        parameter lpm_hint = "UNUSED";
265
 
266
        input  [lpm_width-1:0] data;
267
        input  enabledt;
268
        input  enabletr;
269
        output [lpm_width-1:0] result;
270
        inout  [lpm_width-1:0] tridata;
271
 
272
        reg    [lpm_width-1:0] result;
273
        reg    [lpm_width-1:0] tmp_tridata;
274
 
275
        tri0  enabledt;
276
        tri0  enabletr;
277
        buf (i_enabledt, enabledt);
278
        buf (i_enabletr, enabletr);
279
 
280
        always @(data or tridata or i_enabletr or i_enabledt)
281
        begin
282
        if (i_enabledt == 0 && i_enabletr == 1)
283
                begin
284
                        result = tridata;
285
                        tmp_tridata = 'bz;
286
                end
287
        else if (i_enabledt == 1 && i_enabletr == 0)
288
                begin
289
                        result = 'bz;
290
                        tmp_tridata = data;
291
                end
292
        else if (i_enabledt == 1 && i_enabletr == 1)
293
                begin
294
                        result = data;
295
                        tmp_tridata = data;
296
                end
297
                else
298
                begin
299
                        result = 'bz;
300
                        tmp_tridata = 'bz;
301
                end
302
        end
303
 
304
        assign tridata = tmp_tridata;
305
 
306
endmodule // lpm_bustri
307
 
308
//------------------------------------------------------------------------
309
 
310
module lpm_mux ( result, clock, clken, data, aclr, sel );
311
 
312
        parameter lpm_type = "lpm_mux";
313
        parameter lpm_width = 1;
314
        parameter lpm_size = 1;
315
        parameter lpm_widths = 1;
316
        parameter lpm_pipeline = 0;
317
        parameter lpm_hint  = "UNUSED";
318
 
319
        input [(lpm_size * lpm_width)-1:0] data;
320
        input aclr;
321
        input clock;
322
        input clken;
323
        input [lpm_widths-1:0] sel;
324
        output [lpm_width-1:0] result;
325
 
326
        reg [lpm_width-1:0] tmp_result2 [lpm_pipeline:0];
327
    reg [lpm_width-1:0] tmp_result;
328
    integer i;
329
 
330
        tri0 aclr;
331
        tri0 clock;
332
        tri1 clken;
333
 
334
        buf (i_aclr, aclr);
335
        buf (i_clock, clock);
336
        buf (i_clken, clken);
337
 
338
    always @(data or sel or i_aclr)
339
        begin
340
                if (i_aclr)
341
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
342
                                tmp_result2[i] = 'b0;
343
        else
344
        begin
345
            tmp_result = 0;
346
            for (i = 0; i < lpm_width; i = i + 1)
347
                tmp_result[i] = data[sel * lpm_width + i];
348
            tmp_result2[lpm_pipeline] = tmp_result;
349
        end
350
        end
351
 
352
    always @(posedge i_clock)
353
        begin
354
        if (!i_aclr && i_clken == 1)
355
            for (i = 0; i < lpm_pipeline; i = i + 1)
356
                tmp_result2[i] <= tmp_result2[i+1];
357
        end
358
 
359
    assign result = tmp_result2[0];
360
endmodule // lpm_mux
361
 
362
//------------------------------------------------------------------------
363
 
364
module lpm_decode ( eq, data, enable, clock, clken, aclr );
365
 
366
        parameter lpm_type = "lpm_decode";
367
        parameter lpm_width = 1;
368
        parameter lpm_decodes = 1 << lpm_width;
369
        parameter lpm_pipeline = 0;
370
        parameter lpm_hint = "UNUSED";
371
 
372
        input  [lpm_width-1:0] data;
373
        input  enable;
374
    input  clock;
375
        input  clken;
376
        input  aclr;
377
        output [lpm_decodes-1:0] eq;
378
 
379
    reg    [lpm_decodes-1:0] tmp_eq2 [lpm_pipeline:0];
380
    reg    [lpm_decodes-1:0] tmp_eq;
381
    integer i;
382
 
383
        tri0   clock;
384
        tri1   clken;
385
        tri0   aclr;
386
        tri1   enable;
387
 
388
        buf (i_clock, clock);
389
        buf (i_clken, clken);
390
        buf (i_aclr, aclr);
391
        buf (i_enable, enable);
392
 
393
 
394
    always @(data or i_enable or i_aclr)
395
        begin
396
        if (i_aclr)
397
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
398
                tmp_eq2[i] = 'b0;
399
        else
400
        begin
401
            tmp_eq = 0;
402
            if (i_enable)
403
                tmp_eq[data] = 1'b1;
404
            tmp_eq2[lpm_pipeline] = tmp_eq;
405
        end
406
        end
407
 
408
    always @(posedge i_clock)
409
        begin
410
        if (!i_aclr && clken == 1)
411
            for (i = 0; i < lpm_pipeline; i = i + 1)
412
                tmp_eq2[i] <= tmp_eq2[i+1];
413
        end
414
 
415
    assign eq = tmp_eq2[0];
416
 
417
endmodule // lpm_decode
418
 
419
//------------------------------------------------------------------------
420
 
421
module lpm_clshift ( result, overflow, underflow, data, direction, distance );
422
 
423
        parameter lpm_type = "lpm_clshift";
424
        parameter lpm_width = 1;
425
        parameter lpm_widthdist = 1;
426
        parameter lpm_shifttype = "LOGICAL";
427
        parameter lpm_hint = "UNUSED";
428
 
429
        input  [lpm_width-1:0] data;
430
        input  [lpm_widthdist-1:0] distance;
431
        input  direction;
432
        output [lpm_width-1:0] result;
433
        output overflow;
434
        output underflow;
435
 
436
        reg    [lpm_width-1:0] ONES;
437
        reg    [lpm_width-1:0] result;
438
        reg    overflow, underflow;
439
        integer i;
440
 
441
        tri0  direction;
442
 
443
        buf (i_direction, direction);
444
 
445
//---------------------------------------------------------------//
446
        function [lpm_width+1:0] LogicShift;
447
                input [lpm_width-1:0] data;
448
                input [lpm_widthdist-1:0] dist;
449
                input direction;
450
                reg   [lpm_width-1:0] tmp_buf;
451
                reg   overflow, underflow;
452
 
453
                begin
454
                        tmp_buf = data;
455
                        overflow = 1'b0;
456
                        underflow = 1'b0;
457
                        if ((direction) && (dist > 0)) // shift right
458
                        begin
459
                                tmp_buf = data >> dist;
460
                                if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
461
                                        underflow = 1'b1;
462
                        end
463
                        else if (dist > 0) // shift left
464
                        begin
465
                                tmp_buf = data << dist;
466
                                if ((data != 0) && ((dist >= lpm_width)
467
                                        || ((data >> (lpm_width-dist)) != 0)))
468
                                        overflow = 1'b1;
469
                        end
470
                        LogicShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
471
                end
472
        endfunction
473
 
474
//---------------------------------------------------------------//
475
        function [lpm_width+1:0] ArithShift;
476
                input [lpm_width-1:0] data;
477
                input [lpm_widthdist-1:0] dist;
478
                input direction;
479
                reg   [lpm_width-1:0] tmp_buf;
480
                reg   overflow, underflow;
481
 
482
                begin
483
                        tmp_buf = data;
484
                        overflow = 1'b0;
485
                        underflow = 1'b0;
486
 
487
                        if (direction && (dist > 0))   // shift right
488
                        begin
489
                                if (data[lpm_width-1] == 0) // positive number
490
                                begin
491
                                        tmp_buf = data >> dist;
492
                                        if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
493
                                                underflow = 1'b1;
494
                                end
495
                                else // negative number
496
                                begin
497
                                        tmp_buf = (data >> dist) | (ONES << (lpm_width - dist));
498
                                        if ((data != ONES) && ((dist >= lpm_width-1) || (tmp_buf == ONES)))
499
                                                underflow = 1'b1;
500
                                end
501
                        end
502
                        else if (dist > 0) // shift left
503
                        begin
504
                                tmp_buf = data << dist;
505
                                if (data[lpm_width-1] == 0) // positive number
506
                                begin
507
                                        if ((data != 0) && ((dist >= lpm_width-1)
508
                                        || ((data >> (lpm_width-dist-1)) != 0)))
509
                                                overflow = 1'b1;
510
                                end
511
                                else // negative number
512
                                begin
513
                                        if ((data != ONES) && ((dist >= lpm_width)
514
                                        || (((data >> (lpm_width-dist-1))|(ONES << (dist+1))) != ONES)))
515
                                                overflow = 1'b1;
516
                                end
517
                        end
518
                        ArithShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
519
                end
520
        endfunction
521
 
522
//---------------------------------------------------------------//
523
    function [lpm_width+1:0] RotateShift;
524
        input [lpm_width-1:0] data;
525
                input [lpm_widthdist-1:0] dist;
526
                input direction;
527
                reg   [lpm_width-1:0] tmp_buf;
528
 
529
                begin
530
                        tmp_buf = data;
531
                        if ((direction) && (dist > 0)) // shift right
532
                                tmp_buf = (data >> dist) | (data << (lpm_width - dist));
533
                        else if (dist > 0) // shift left
534
                                tmp_buf = (data << dist) | (data >> (lpm_width - dist));
535
            RotateShift = {2'bx, tmp_buf[lpm_width-1:0]};
536
                end
537
        endfunction
538
//---------------------------------------------------------------//
539
 
540
        initial
541
        begin
542
        if (lpm_shifttype != "LOGICAL" &&
543
            lpm_shifttype != "ARITHMETIC" &&
544
            lpm_shifttype != "ROTATE" &&
545
            lpm_shifttype != "UNUSED")          // non-LPM 220 standard
546
            $display("Error!  LPM_SHIFTTYPE value must be \"LOGICAL\", \"ARITHMETIC\", or \"ROTATE\".");
547
 
548
                for (i=0; i < lpm_width; i=i+1)
549
                        ONES[i] = 1'b1;
550
        end
551
 
552
        always @(data or i_direction or distance)
553
        begin
554
        if ((lpm_shifttype == "LOGICAL") || (lpm_shifttype == "UNUSED"))
555
            {overflow, underflow, result} = LogicShift(data, distance, i_direction);
556
                else if (lpm_shifttype == "ARITHMETIC")
557
            {overflow, underflow, result} = ArithShift(data, distance, i_direction);
558
                else if (lpm_shifttype == "ROTATE")
559
            {overflow, underflow, result} = RotateShift(data, distance, i_direction);
560
        end
561
 
562
endmodule // lpm_clshift
563
 
564
//------------------------------------------------------------------------
565
 
566
module lpm_add_sub ( result, cout, overflow,
567
                                         add_sub, cin, dataa, datab, clock, clken, aclr );
568
 
569
        parameter lpm_type = "lpm_add_sub";
570
        parameter lpm_width = 1;
571
        parameter lpm_direction  = "UNUSED";
572
        parameter lpm_representation = "UNSIGNED";
573
        parameter lpm_pipeline = 0;
574
        parameter lpm_hint = "UNUSED";
575
 
576
        input  [lpm_width-1:0] dataa, datab;
577
        input  add_sub, cin;
578
        input  clock;
579
        input  clken;
580
        input  aclr;
581
        output [lpm_width-1:0] result;
582
        output cout, overflow;
583
 
584
    reg [lpm_width-1:0] tmp_result2 [lpm_pipeline:0];
585
    reg [lpm_pipeline:0] tmp_cout2;
586
    reg [lpm_pipeline:0] tmp_overflow2;
587
    reg [lpm_width-1:0] not_a, not_b, tmp_result;
588
    reg i_cin;
589
    integer dataa_int, datab_int, result_int, borrow, i;
590
 
591
        tri0 aclr;
592
        tri0 clock;
593
        tri1 clken;
594
        tri1 add_sub;
595
 
596
        buf (i_aclr, aclr);
597
        buf (i_clock, clock);
598
        buf (i_clken, clken);
599
        buf (i_add_sub, add_sub);
600
 
601
 
602
    initial
603
    begin
604
        if (lpm_direction != "ADD" &&
605
            lpm_direction != "SUB" &&
606
            lpm_direction != "UNUSED" &&            // non-LPM 220 standard
607
            lpm_direction != "DEFAULT")             // non-LPM 220 standard
608
            $display("Error!  LPM_DIRECTION value must be \"ADD\" or \"SUB\".");
609
        if (lpm_representation != "SIGNED" &&
610
            lpm_representation != "UNSIGNED")
611
            $display("Error!  LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
612
 
613
        for (i = 0; i <= lpm_pipeline; i = i + 1)
614
        begin
615
            tmp_result2[i] = 'b0;
616
            tmp_cout2[i] = 1'b0;
617
            tmp_overflow2[i] = 1'b0;
618
        end
619
    end
620
 
621
    always @(cin or dataa or datab or i_add_sub or i_aclr)
622
        begin
623
                if (i_aclr)
624
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
625
                        begin
626
                                tmp_result2[i] = 'b0;
627
                                tmp_cout2[i] = 1'b0;
628
                                tmp_overflow2[i] = 1'b0;
629
                        end
630
        else
631
        begin
632
 
633
            // cout is the same for both signed and unsign representation.  
634
            if (lpm_direction == "ADD" || (i_add_sub == 1 &&
635
                (lpm_direction == "UNUSED" || lpm_direction == "DEFAULT") ))
636
            begin
637
                i_cin = (cin === 1'bz) ? 0 : cin;
638
                {tmp_cout2[lpm_pipeline], tmp_result2[lpm_pipeline]} = dataa + datab + i_cin;
639
                tmp_overflow2[lpm_pipeline] = tmp_cout2[lpm_pipeline];
640
            end
641
            else if (lpm_direction == "SUB" || (i_add_sub == 0 &&
642
                    (lpm_direction == "UNUSED" || lpm_direction == "DEFAULT") ))
643
            begin
644
                i_cin = (cin === 1'bz) ? 1 : cin;
645
                borrow = (~i_cin) ? 1 : 0;
646
                {tmp_overflow2[lpm_pipeline], tmp_result2[lpm_pipeline]} = dataa - datab - borrow;
647
                tmp_cout2[lpm_pipeline] = (dataa >= (datab+borrow))?1:0;
648
            end
649
 
650
            if (lpm_representation == "SIGNED")
651
            begin
652
                not_a = ~dataa;
653
                not_b = ~datab;
654
 
655
                dataa_int = (dataa[lpm_width-1]) ? (not_a)*(-1)-1 : dataa;
656
                datab_int = (datab[lpm_width-1]) ? (not_b)*(-1)-1 : datab;
657
 
658
                // perform the addtion or subtraction operation
659
                if (lpm_direction == "ADD" || (i_add_sub == 1 &&
660
                    (lpm_direction == "UNUSED" || lpm_direction == "DEFAULT") ))
661
                begin
662
                    i_cin = (cin === 1'bz) ? 0 : cin;
663
                    result_int = dataa_int + datab_int + i_cin;
664
                    tmp_result = result_int;
665
                    tmp_overflow2[lpm_pipeline] = ((dataa[lpm_width-1] == datab[lpm_width-1]) &&
666
                                                   (dataa[lpm_width-1] != tmp_result[lpm_width-1])) ?
667
                                                  1 : 0;
668
                end
669
                else if (lpm_direction == "SUB" || (i_add_sub == 0 &&
670
                        (lpm_direction == "UNUSED" || lpm_direction == "DEFAULT") ))
671
                begin
672
                    i_cin = (cin === 1'bz) ? 1 : cin;
673
                    borrow = (~i_cin) ? 1 : 0;
674
                    result_int = dataa_int - datab_int - borrow;
675
                    tmp_result = result_int;
676
                    tmp_overflow2[lpm_pipeline] = ((dataa[lpm_width-1] != datab[lpm_width-1]) &&
677
                                                   (dataa[lpm_width-1] != tmp_result[lpm_width-1])) ?
678
                                                  1 : 0;
679
                end
680
                tmp_result2[lpm_pipeline] = result_int;
681
            end
682
        end
683
        end
684
 
685
    always @(posedge i_clock)
686
        begin
687
        if (!i_aclr && i_clken == 1)
688
            for (i = 0; i < lpm_pipeline; i = i + 1)
689
                        begin
690
                tmp_result2[i] <= tmp_result2[i+1];
691
                tmp_cout2[i] <= tmp_cout2[i+1];
692
                tmp_overflow2[i] <= tmp_overflow2[i+1];
693
                        end
694
        end
695
 
696
    assign result = tmp_result2[0];
697
    assign cout = tmp_cout2[0];
698
    assign overflow = tmp_overflow2[0];
699
 
700
endmodule // lpm_add_sub
701
 
702
//------------------------------------------------------------------------
703
 
704
module lpm_compare ( alb, aeb, agb, aleb, aneb, ageb, dataa, datab,
705
                                         clock, clken, aclr );
706
 
707
        parameter lpm_type = "lpm_compare";
708
        parameter lpm_width = 1;
709
        parameter lpm_representation = "UNSIGNED";
710
    parameter lpm_pipeline = 0;
711
        parameter lpm_hint = "UNUSED";
712
 
713
        input  [lpm_width-1:0] dataa, datab;
714
        input  clock;
715
        input  clken;
716
        input  aclr;
717
        output alb, aeb, agb, aleb, aneb, ageb;
718
 
719
    reg [lpm_pipeline:0] tmp_alb2, tmp_aeb2, tmp_agb2;
720
    reg [lpm_pipeline:0] tmp_aleb2, tmp_aneb2, tmp_ageb2;
721
    reg [lpm_width-1:0] not_a, not_b;
722
    integer dataa_int, datab_int, i;
723
 
724
        tri0 aclr;
725
        tri0 clock;
726
        tri1 clken;
727
 
728
        buf (i_aclr, aclr);
729
        buf (i_clock, clock);
730
        buf (i_clken, clken);
731
 
732
    initial
733
    begin
734
        if (lpm_representation != "SIGNED" &&
735
            lpm_representation != "UNSIGNED")
736
            $display("Error!  LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
737
    end
738
 
739
 
740
    always @(dataa or datab or i_aclr)
741
        begin
742
                if (i_aclr)
743
            for (i = 0; i <= lpm_pipeline; i = i + 1)
744
                        begin
745
                tmp_aeb2[i] = 'b0;
746
                tmp_agb2[i] = 'b0;
747
                tmp_alb2[i] = 'b0;
748
                tmp_aleb2[i] = 'b0;
749
                tmp_aneb2[i] = 'b0;
750
                tmp_ageb2[i] = 'b0;
751
                        end
752
        else
753
        begin
754
            dataa_int = dataa;
755
            datab_int = datab;
756
            not_a = ~dataa;
757
            not_b = ~datab;
758
 
759
            if (lpm_representation == "SIGNED")
760
            begin
761
                if (dataa[lpm_width-1] == 1)
762
                    dataa_int = (not_a) * (-1) - 1;
763
                if (datab[lpm_width-1] == 1)
764
                    datab_int = (not_b) * (-1) - 1;
765
            end
766
 
767
            tmp_alb2[lpm_pipeline] = (dataa_int < datab_int);
768
            tmp_aeb2[lpm_pipeline] = (dataa_int == datab_int);
769
            tmp_agb2[lpm_pipeline] = (dataa_int > datab_int);
770
            tmp_aleb2[lpm_pipeline] = (dataa_int <= datab_int);
771
            tmp_aneb2[lpm_pipeline] = (dataa_int != datab_int);
772
            tmp_ageb2[lpm_pipeline] = (dataa_int >= datab_int);
773
        end
774
        end
775
 
776
    always @(posedge i_clock)
777
        begin
778
        if (!i_aclr && i_clken == 1)
779
            for (i = 0; i < lpm_pipeline; i = i + 1)
780
            begin
781
                tmp_alb2[i] <= tmp_alb2[i+1];
782
                tmp_aeb2[i] <= tmp_aeb2[i+1];
783
                tmp_agb2[i] <= tmp_agb2[i+1];
784
                tmp_aleb2[i] <= tmp_aleb2[i+1];
785
                tmp_aneb2[i] <= tmp_aneb2[i+1];
786
                tmp_ageb2[i] <= tmp_ageb2[i+1];
787
            end
788
        end
789
 
790
    assign alb = tmp_alb2[0];
791
    assign aeb = tmp_aeb2[0];
792
    assign agb = tmp_agb2[0];
793
    assign aleb = tmp_aleb2[0];
794
    assign aneb = tmp_aneb2[0];
795
    assign ageb = tmp_ageb2[0];
796
 
797
endmodule // lpm_compare
798
 
799
//------------------------------------------------------------------------
800
 
801
module lpm_mult ( result, dataa, datab, sum, clock, clken, aclr );
802
 
803
        parameter lpm_type = "lpm_mult";
804
        parameter lpm_widtha = 1;
805
        parameter lpm_widthb = 1;
806
        parameter lpm_widths = 1;
807
        parameter lpm_widthp = 1;
808
        parameter lpm_representation  = "UNSIGNED";
809
        parameter lpm_pipeline  = 0;
810
        parameter lpm_hint = "UNUSED";
811
 
812
        input  clock;
813
        input  clken;
814
        input  aclr;
815
        input  [lpm_widtha-1:0] dataa;
816
        input  [lpm_widthb-1:0] datab;
817
        input  [lpm_widths-1:0] sum;
818
        output [lpm_widthp-1:0] result;
819
 
820
        // inernal reg
821
    reg [lpm_widthp-1:0] resulttmp [lpm_pipeline:0];
822
    reg [lpm_widthp-1:0] i_prod, t_p;
823
    reg [lpm_widths-1:0] i_prod_s, t_s;
824
    reg [lpm_widtha+lpm_widthb-1:0] i_prod_ab;
825
    reg [lpm_widtha-1:0] t_a;
826
    reg [lpm_widthb-1:0] t_b;
827
    reg sign_ab, sign_s;
828
    integer i;
829
 
830
        tri0 aclr;
831
        tri0 clock;
832
        tri1 clken;
833
 
834
        buf (i_aclr, aclr);
835
        buf (i_clock, clock);
836
        buf (i_clken, clken);
837
 
838
 
839
        initial
840
        begin
841
        // check if lpm_widtha > 0
842
        if (lpm_widtha <= 0)
843
            $display("Error!  LPM_WIDTHA must be greater than 0.\n");
844
        // check if lpm_widthb > 0
845
        if (lpm_widthb <= 0)
846
            $display("Error!  LPM_WIDTHB must be greater than 0.\n");
847
        // check if lpm_widthp > 0
848
        if (lpm_widthp <= 0)
849
            $display("Error!  LPM_WIDTHP must be greater than 0.\n");
850
        // check for valid lpm_rep value
851
        if ((lpm_representation != "SIGNED") && (lpm_representation != "UNSIGNED"))
852
            $display("Error!  LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".", $time);
853
        end
854
 
855
    always @(dataa or datab or sum or i_aclr)
856
        begin
857
        if (i_aclr)
858
            for (i = 0; i <= lpm_pipeline; i = i + 1)
859
                resulttmp[i] = 'b0;
860
        else
861
        begin
862
            t_a = dataa;
863
            t_b = datab;
864
            t_s = sum;
865
            sign_ab = 0;
866
            sign_s = 0;
867
 
868
            if (lpm_representation == "SIGNED")
869
            begin
870
                sign_ab = dataa[lpm_widtha-1] ^ datab[lpm_widthb-1];
871
                sign_s = sum[lpm_widths-1];
872
 
873
                if (dataa[lpm_widtha-1] == 1)
874
                    t_a = ~dataa + 1;
875
                if (datab[lpm_widthb-1] == 1)
876
                    t_b = ~datab + 1;
877
                if (sum[lpm_widths-1] == 1)
878
                    t_s = ~sum + 1;
879
            end
880
 
881
            if (sum === {lpm_widths{1'bz}})
882
            begin
883
                t_s = 0;
884
                sign_s = 0;
885
            end
886
 
887
            if (sign_ab == sign_s)
888
            begin
889
                i_prod = t_a * t_b + t_s;
890
                i_prod_s = t_a * t_b + t_s;
891
                i_prod_ab = t_a * t_b + t_s;
892
            end
893
            else
894
            begin
895
                i_prod = t_a * t_b - t_s;
896
                i_prod_s = t_a * t_b - t_s;
897
                i_prod_ab = t_a * t_b - t_s;
898
            end
899
 
900
            if (sign_ab)
901
            begin
902
                i_prod = ~i_prod + 1;
903
                i_prod_s = ~i_prod_s + 1;
904
                i_prod_ab = ~i_prod_ab + 1;
905
            end
906
 
907
            if (lpm_widthp < lpm_widths || lpm_widthp < lpm_widtha+lpm_widthb)
908
                for (i = 0; i < lpm_widthp; i = i + 1)
909
                    i_prod[lpm_widthp-1-i] = (lpm_widths > lpm_widtha+lpm_widthb)
910
                                             ? i_prod_s[lpm_widths-1-i]
911
                                             : i_prod_ab[lpm_widtha+lpm_widthb-1-i];
912
 
913
            resulttmp[lpm_pipeline] = i_prod;
914
        end
915
        end
916
 
917
    always @(posedge i_clock)
918
        begin
919
        if (!i_aclr && i_clken == 1)
920
            for (i = 0; i < lpm_pipeline; i = i + 1)
921
                resulttmp[i] <= resulttmp[i+1];
922
        end
923
 
924
    assign result = resulttmp[0];
925
 
926
endmodule // lpm_mult
927
 
928
//------------------------------------------------------------------------
929
 
930
module lpm_divide ( quotient, remain, numer, denom, clock, clken, aclr );
931
 
932
        parameter lpm_type = "lpm_divide";
933
        parameter lpm_widthn = 1;
934
        parameter lpm_widthd = 1;
935
        parameter lpm_nrepresentation = "UNSIGNED";
936
        parameter lpm_drepresentation = "UNSIGNED";
937
        parameter lpm_remainderpositive = "TRUE";
938
        parameter lpm_pipeline = 0;
939
        parameter lpm_hint = "UNUSED";
940
 
941
        input  clock;
942
        input  clken;
943
        input  aclr;
944
        input  [lpm_widthn-1:0] numer;
945
        input  [lpm_widthd-1:0] denom;
946
        output [lpm_widthn-1:0] quotient;
947
        output [lpm_widthd-1:0] remain;
948
 
949
        // inernal reg
950
    reg [lpm_widthn-1:0] tmp_quotient [lpm_pipeline:0];
951
    reg [lpm_widthd-1:0] tmp_remain [lpm_pipeline:0];
952
    reg [lpm_widthn-1:0] ONES, ZEROS, UNKNOWN, HiZ;
953
    reg [lpm_widthd-1:0] DZEROS, DUNKNOWN;
954
    reg [lpm_widthn-1:0] NUNKNOWN;
955
    reg [lpm_widthd-1:0] RZEROS;
956
    reg [lpm_widthn-1:0] not_numer, int_numer;
957
    reg [lpm_widthd-1:0] not_denom, int_denom;
958
        integer i;
959
        integer int_quotient, int_remain;
960
 
961
        tri0 aclr;
962
        tri0 clock;
963
        tri1 clken;
964
 
965
        buf (i_aclr, aclr);
966
        buf (i_clock, clock);
967
        buf (i_clken, clken);
968
 
969
 
970
        initial
971
        begin
972
        // check if lpm_widthn > 0
973
        if (lpm_widthn <= 0)
974
            $display("Error!  LPM_WIDTHN must be greater than 0.\n");
975
        // check if lpm_widthd > 0
976
        if (lpm_widthd <= 0)
977
            $display("Error!  LPM_WIDTHD must be greater than 0.\n");
978
        // check for valid lpm_nrep value
979
        if ((lpm_nrepresentation != "SIGNED") && (lpm_nrepresentation != "UNSIGNED"))
980
            $display("Error!  LPM_NREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
981
        // check for valid lpm_drep value
982
        if ((lpm_drepresentation != "SIGNED") && (lpm_drepresentation != "UNSIGNED"))
983
            $display("Error!  LPM_DREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
984
        // check for valid lpm_remainderpositive value
985
        if ((lpm_remainderpositive != "TRUE") && (lpm_remainderpositive != "FALSE"))
986
            $display("Error!  LPM_REMAINDERPOSITIVE value must be \"TRUE\" or \"FALSE\".");
987
 
988
        for (i=0; i < lpm_widthn; i=i+1)
989
        begin
990
            ONES[i] = 1'b1;
991
            ZEROS[i] = 1'b0;
992
            UNKNOWN[i] = 1'bx;
993
            HiZ[i] = 1'bz;
994
        end
995
 
996
        for (i=0; i < lpm_widthd; i=i+1)
997
            DUNKNOWN[i] = 1'bx;
998
        for (i=0; i < lpm_widthn; i=i+1)
999
            NUNKNOWN[i] = 1'bx;
1000
        for (i=0; i < lpm_widthd; i=i+1)
1001
            RZEROS[i] = 1'b0;
1002
        end
1003
 
1004
    always @(numer or denom or i_aclr)
1005
        begin
1006
                if (i_aclr)
1007
                begin
1008
                        for (i = 0; i <= lpm_pipeline; i = i + 1)
1009
                                tmp_quotient[i] = ZEROS;
1010
                        tmp_remain[i] = RZEROS;
1011
                end
1012
        else
1013
        begin
1014
            int_numer = numer;
1015
            int_denom = denom;
1016
            not_numer = ~numer;
1017
            not_denom = ~denom;
1018
 
1019
            if (lpm_nrepresentation == "SIGNED")
1020
                if (numer[lpm_widthn-1] == 1)
1021
                    int_numer = (not_numer) * (-1) - 1;
1022
            if (lpm_drepresentation == "SIGNED")
1023
                if (denom[lpm_widthd-1] == 1)
1024
                    int_denom = (not_denom) * (-1) - 1;
1025
 
1026
            int_quotient = int_numer / int_denom;
1027
            int_remain = int_numer % int_denom;
1028
 
1029
            // LPM 220 standard
1030
            if ((lpm_remainderpositive == "TRUE") && (int_remain < 0))
1031
            begin
1032
                int_quotient = int_quotient + ((int_denom < 0) ? 1 : (-1));
1033
                int_remain = int_numer - int_quotient*int_denom;
1034
            end
1035
 
1036
            tmp_quotient[lpm_pipeline] = int_quotient;
1037
            tmp_remain[lpm_pipeline] = int_remain;
1038
        end
1039
        end
1040
 
1041
    always @(posedge i_clock)
1042
    begin
1043
        if (!i_aclr && i_clken)
1044
            for (i = 0; i < lpm_pipeline; i = i + 1)
1045
                        begin
1046
                                tmp_quotient[i] <= tmp_quotient[i+1];
1047
                                tmp_remain[i] <= tmp_remain[i+1];
1048
                        end
1049
        end
1050
 
1051
        assign quotient = tmp_quotient[0];
1052
        assign remain = tmp_remain[0];
1053
 
1054
endmodule // lpm_divide
1055
 
1056
//------------------------------------------------------------------------
1057
 
1058
module lpm_abs ( result, overflow, data );
1059
 
1060
        parameter lpm_type = "lpm_abs";
1061
        parameter lpm_width = 1;
1062
        parameter lpm_hint = "UNUSED";
1063
 
1064
        input  [lpm_width-1:0] data;
1065
        output [lpm_width-1:0] result;
1066
        output overflow;
1067
 
1068
    reg [lpm_width-1:0] result, not_r;
1069
    reg overflow;
1070
 
1071
 
1072
        always @(data)
1073
        begin
1074
                overflow = 0;
1075
        result = data;
1076
        not_r = ~data;
1077
 
1078
                if (data[lpm_width-1] == 1)
1079
                begin
1080
            result = (not_r) + 1;
1081
            overflow = (result == (1<<(lpm_width-1)));
1082
                end
1083
        end
1084
 
1085
endmodule // lpm_abs
1086
 
1087
//------------------------------------------------------------------------
1088
 
1089
module lpm_counter ( q, data, clock, cin, cout, clk_en, cnt_en, updown,
1090
                                         aset, aclr, aload, sset, sclr, sload );
1091
 
1092
        parameter lpm_type = "lpm_counter";
1093
        parameter lpm_width = 1;
1094
        parameter lpm_modulus = 0;
1095
        parameter lpm_direction = "UNUSED";
1096
        parameter lpm_avalue = "UNUSED";
1097
        parameter lpm_svalue = "UNUSED";
1098
        parameter lpm_pvalue = "UNUSED";
1099
        parameter lpm_hint = "UNUSED";
1100
 
1101
        output [lpm_width-1:0] q;
1102
        output cout;
1103
        input  cin;
1104
        input  [lpm_width-1:0] data;
1105
        input  clock, clk_en, cnt_en, updown;
1106
        input  aset, aclr, aload;
1107
        input  sset, sclr, sload;
1108
 
1109
    reg  [lpm_width-1:0] tmp_count;
1110
    reg  prev_clock;
1111
    reg  tmp_updown;
1112
    reg  [lpm_width-1:0] ONES;
1113
    integer tmp_modulus, i;
1114
 
1115
        tri1 clk_en;
1116
        tri1 cnt_en;
1117
        tri0 sload;
1118
        tri0 sset;
1119
        tri0 sclr;
1120
        tri0 aload;
1121
        tri0 aset;
1122
        tri0 aclr;
1123
    tri1 cin;
1124
    tri1 updown;
1125
 
1126
        buf (i_clk_en, clk_en);
1127
        buf (i_cnt_en, cnt_en);
1128
        buf (i_sload, sload);
1129
        buf (i_sset, sset);
1130
        buf (i_sclr, sclr);
1131
        buf (i_aload, aload);
1132
        buf (i_aset, aset);
1133
        buf (i_aclr, aclr);
1134
        buf (i_cin, cin);
1135
    buf (i_updown, updown);
1136
 
1137
 
1138
//---------------------------------------------------------------//
1139
//  function integer str_to_int;
1140
//---------------------------------------------------------------//
1141
        function integer str_to_int;
1142
        input [8*16:1] s;
1143
 
1144
                reg [8*16:1] reg_s;
1145
                reg [8:1] digit;
1146
                reg [8:1] tmp;
1147
                integer m, ivalue;
1148
 
1149
                begin
1150
                        ivalue = 0;
1151
                        reg_s = s;
1152
                        for (m=1; m<=16; m=m+1)
1153
                        begin
1154
                                tmp = reg_s[128:121];
1155
                                digit = tmp & 8'b00001111;
1156
                                reg_s = reg_s << 8;
1157
                                ivalue = ivalue * 10 + digit;
1158
                        end
1159
                        str_to_int = ivalue;
1160
                end
1161
        endfunction
1162
 
1163
//---------------------------------------------------------------//
1164
 
1165
        initial
1166
        begin
1167
                // check if lpm_modulus < 0
1168
                if (lpm_modulus < 0)
1169
            $display("Error!  LPM_MODULUS must be greater than 0.\n");
1170
                // check if lpm_modulus > 1<<lpm_width
1171
                if (lpm_modulus > 1<<lpm_width)
1172
            $display("Error!  LPM_MODULUS must be less than or equal to 1<<LPM_WIDTH.\n");
1173
        // check if lpm_direction valid
1174
        if (lpm_direction != "UNUSED" && lpm_direction != "UP" && lpm_direction != "DOWN")
1175
            $display("Error!  LPM_DIRECTION must be \"UP\" or \"DOWN\" if used.\n");
1176
        else if (lpm_direction != "UNUSED" && ((updown == 1'b0) || (updown == 1'b1)))
1177
            $display("Error!  LPM_DIRECTION and UPDOWN cannot be used at the same time.\n");
1178
 
1179
        for (i=0; i < lpm_width; i=i+1)
1180
            ONES[i] = 1'b1;
1181
 
1182
        prev_clock = clock;
1183
 
1184
                tmp_modulus = (lpm_modulus == 0) ? (1 << lpm_width) : lpm_modulus;
1185
                tmp_count = (lpm_pvalue == "UNUSED") ? 0 : str_to_int(lpm_pvalue);
1186
        end
1187
 
1188
    always @(i_aclr or i_aset or i_aload or data or clock or i_updown)
1189
        begin :asyn_block
1190
 
1191
        tmp_updown = ((lpm_direction == "UNUSED" && i_updown == 1) || lpm_direction == "UP")
1192
                     ? 1 : 0;
1193
                if (i_aclr)
1194
            tmp_count <= 0;
1195
                else if (i_aset)
1196
            tmp_count <= (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
1197
                                                 : str_to_int(lpm_avalue);
1198
                else if (i_aload)
1199
            tmp_count <= data;
1200
        else if (clock === 1 && prev_clock !== 1 && $time > 0)
1201
                begin :syn_block
1202
                        if (i_clk_en)
1203
                        begin
1204
                                if (i_sclr)
1205
                    tmp_count <= 0;
1206
                                else if (i_sset)
1207
                    tmp_count <= (lpm_svalue == "UNUSED") ? {lpm_width{1'b1}}
1208
                                                         : str_to_int(lpm_svalue);
1209
                                else if (i_sload)
1210
                    tmp_count <= data;
1211
                else if (i_cnt_en && i_cin)
1212
                begin
1213
                    if (tmp_updown == 1)
1214
                        tmp_count <= (tmp_count == tmp_modulus-1) ? 0
1215
                                                                 : tmp_count+1;
1216
                    else
1217
                        tmp_count <= (tmp_count == 0) ? tmp_modulus-1
1218
                                                     : tmp_count-1;
1219
                end
1220
                        end
1221
                end
1222
 
1223
        prev_clock = clock;
1224
        end
1225
 
1226
    assign q = tmp_count;
1227
    assign cout = (i_cin && ((tmp_updown==0 && tmp_count==0) ||
1228
                             (tmp_updown==1 && (tmp_count==tmp_modulus-1 ||
1229
                                                tmp_count==ONES)) ))
1230
                    ? 1 : 0;
1231
 
1232
endmodule // lpm_counter
1233
 
1234
//------------------------------------------------------------------------
1235
 
1236
module lpm_latch ( q, data, gate, aset, aclr );
1237
 
1238
  parameter lpm_type = "lpm_latch";
1239
  parameter lpm_width = 1;
1240
  parameter lpm_avalue = "UNUSED";
1241
  parameter lpm_pvalue = "UNUSED";
1242
  parameter lpm_hint = "UNUSED";
1243
 
1244
  input  [lpm_width-1:0] data;
1245
  input  gate, aset, aclr;
1246
  output [lpm_width-1:0] q;
1247
 
1248
  reg [lpm_width-1:0] q;
1249
  reg [lpm_width-1:0] i_data;
1250
 
1251
  tri0 aset;
1252
  tri0 aclr;
1253
 
1254
  buf (i_aset, aset);
1255
  buf (i_aclr, aclr);
1256
 
1257
//---------------------------------------------------------------//
1258
//  function integer str_to_int;
1259
//---------------------------------------------------------------//
1260
        function integer str_to_int;
1261
        input [8*16:1] s;
1262
 
1263
                reg [8*16:1] reg_s;
1264
                reg [8:1] digit;
1265
                reg [8:1] tmp;
1266
        integer m, ivalue;
1267
 
1268
                begin
1269
                        ivalue = 0;
1270
                        reg_s = s;
1271
                        for (m=1; m<=16; m= m+1)
1272
                        begin
1273
                                tmp = reg_s[128:121];
1274
                                digit = tmp & 8'b00001111;
1275
                                reg_s = reg_s << 8;
1276
                                ivalue = ivalue * 10 + digit;
1277
                        end
1278
                        str_to_int = ivalue;
1279
                end
1280
        endfunction
1281
//---------------------------------------------------------------//
1282
 
1283
        initial
1284
        begin
1285
                if (lpm_pvalue != "UNUSED")
1286
                        q = str_to_int(lpm_pvalue);
1287
        i_data = (data === {lpm_width{1'bz}}) ? 0 : data;
1288
        end
1289
 
1290
    always @(data)
1291
        i_data = data;
1292
 
1293
    always @(i_data or gate or i_aclr or i_aset)
1294
        begin
1295
                if (i_aclr)
1296
                        q = 'b0;
1297
                else if (i_aset)
1298
            q = (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
1299
                                         : str_to_int(lpm_avalue);
1300
                else if (gate)
1301
            q = i_data;
1302
        end
1303
 
1304
endmodule // lpm_latch
1305
 
1306
//------------------------------------------------------------------------
1307
 
1308
module lpm_ff ( q, data, clock, enable, aclr, aset,
1309
                                sclr, sset, aload, sload );
1310
 
1311
        parameter lpm_type = "lpm_ff";
1312
        parameter lpm_width  = 1;
1313
        parameter lpm_avalue = "UNUSED";
1314
        parameter lpm_svalue = "UNUSED";
1315
        parameter lpm_pvalue = "UNUSED";
1316
        parameter lpm_fftype = "DFF";
1317
        parameter lpm_hint = "UNUSED";
1318
 
1319
 
1320
        input  [lpm_width-1:0] data;
1321
        input  clock, enable;
1322
        input  aclr, aset;
1323
        input  sclr, sset;
1324
        input  aload, sload ;
1325
        output [lpm_width-1:0] q;
1326
 
1327
    reg  [lpm_width-1:0] tmp_q;
1328
    reg  prev_clock;
1329
        integer i;
1330
 
1331
        tri1 enable;
1332
        tri0 sload;
1333
        tri0 sclr;
1334
        tri0 sset;
1335
        tri0 aload;
1336
        tri0 aclr;
1337
        tri0 aset;
1338
 
1339
        buf (i_enable, enable);
1340
        buf (i_sload, sload);
1341
        buf (i_sclr, sclr);
1342
        buf (i_sset, sset);
1343
        buf (i_aload, aload);
1344
        buf (i_aclr, aclr);
1345
        buf (i_aset, aset);
1346
 
1347
//---------------------------------------------------------------//
1348
//  function integer str_to_int;
1349
//---------------------------------------------------------------//
1350
        function integer str_to_int;
1351
        input [8*16:1] s;
1352
 
1353
                reg [8*16:1] reg_s;
1354
        reg [8:1] digit;
1355
                reg [8:1] tmp;
1356
        integer m, ivalue;
1357
 
1358
                begin
1359
                        ivalue = 0;
1360
                        reg_s = s;
1361
                        for (m=1; m<=16; m= m+1)
1362
                        begin
1363
                                tmp = reg_s[128:121];
1364
                                digit = tmp & 8'b00001111;
1365
                                reg_s = reg_s << 8;
1366
                                ivalue = ivalue * 10 + digit;
1367
                        end
1368
                        str_to_int = ivalue;
1369
                end
1370
        endfunction
1371
//---------------------------------------------------------------//
1372
 
1373
        initial
1374
    begin
1375
        if (lpm_fftype != "DFF" &&
1376
            lpm_fftype != "TFF" &&
1377
            lpm_fftype != "UNUSED")          // non-LPM 220 standard
1378
            $display("Error!  LPM_FFTYPE value must be \"DFF\" or \"TFF\".");
1379
 
1380
        tmp_q = (lpm_pvalue == "UNUSED") ? 0 : str_to_int(lpm_pvalue);
1381
        prev_clock = clock;
1382
    end
1383
 
1384
    always @(i_aclr or i_aset or i_aload or data or clock)
1385
        begin :asyn_block // Asynchronous process
1386
                if (i_aclr)
1387
            tmp_q = (i_aset) ? 'bx : 0;
1388
        else if (i_aset)
1389
            tmp_q = (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
1390
                                             : str_to_int(lpm_avalue);
1391
                else if (i_aload)
1392
            tmp_q = data;
1393
        else if (clock === 1 && prev_clock !== 1 && $time > 0)
1394
                begin :syn_block // Synchronous process
1395
                        if (i_enable)
1396
                        begin
1397
                                if (i_sclr)
1398
                                        tmp_q <= 0;
1399
                                else if (i_sset)
1400
                    tmp_q <= (lpm_svalue == "UNUSED") ? {lpm_width{1'b1}}
1401
                                                     : str_to_int(lpm_svalue);
1402
                                else if (i_sload)  // Load data
1403
                                        tmp_q <= data;
1404
                                else
1405
                                begin
1406
                    if (lpm_fftype == "TFF") // toggle
1407
                                        begin
1408
                                                for (i = 0; i < lpm_width; i=i+1)
1409
                                                        if (data[i] == 1'b1)
1410
                                                                tmp_q[i] <= ~tmp_q[i];
1411
                                        end
1412
                    else    // DFF, load data
1413
                        tmp_q <= data;
1414
                                end
1415
                        end
1416
                end
1417
        prev_clock = clock;
1418
        end
1419
 
1420
        assign q = tmp_q;
1421
endmodule // lpm_ff
1422
 
1423
//------------------------------------------------------------------------
1424
 
1425
module lpm_shiftreg ( q, shiftout, data, clock, enable, aclr, aset,
1426
                                          sclr, sset, shiftin, load );
1427
 
1428
        parameter lpm_type = "lpm_shiftreg";
1429
        parameter lpm_width  = 1;
1430
        parameter lpm_avalue = "UNUSED";
1431
        parameter lpm_svalue = "UNUSED";
1432
        parameter lpm_pvalue = "UNUSED";
1433
        parameter lpm_direction = "LEFT";
1434
        parameter lpm_hint  = "UNUSED";
1435
 
1436
        input  [lpm_width-1:0] data;
1437
        input  clock, enable;
1438
        input  aclr, aset;
1439
        input  sclr, sset;
1440
        input  shiftin, load;
1441
        output [lpm_width-1:0] q;
1442
        output shiftout;
1443
 
1444
        reg  [lpm_width-1:0] tmp_q;
1445
        reg  abit;
1446
        integer i;
1447
 
1448
        wire tmp_shiftout;
1449
 
1450
        tri1 enable;
1451
        tri1 shiftin;
1452
        tri0 load;
1453
        tri0 sclr;
1454
        tri0 sset;
1455
        tri0 aclr;
1456
        tri0 aset;
1457
 
1458
        buf (i_enable, enable);
1459
        buf (i_shiftin, shiftin);
1460
        buf (i_load, load);
1461
        buf (i_sclr, sclr);
1462
        buf (i_sset, sset);
1463
        buf (i_aclr, aclr);
1464
        buf (i_aset, aset);
1465
 
1466
 
1467
//---------------------------------------------------------------//
1468
//  function integer str_to_int;
1469
//---------------------------------------------------------------//
1470
        function integer str_to_int;
1471
        input [8*16:1] s;
1472
 
1473
                reg [8*16:1] reg_s;
1474
        reg [8:1] digit;
1475
                reg [8:1] tmp;
1476
        integer m, ivalue;
1477
 
1478
                begin
1479
                        ivalue = 0;
1480
                        reg_s = s;
1481
                        for (m=1; m<=16; m= m+1)
1482
                        begin
1483
                                tmp = reg_s[128:121];
1484
                                digit = tmp & 8'b00001111;
1485
                                reg_s = reg_s << 8;
1486
                                ivalue = ivalue * 10 + digit;
1487
                        end
1488
                        str_to_int = ivalue;
1489
                end
1490
        endfunction
1491
//---------------------------------------------------------------//
1492
 
1493
        initial
1494
    begin
1495
        if (lpm_direction != "LEFT" &&
1496
            lpm_direction != "RIGHT" &&
1497
            lpm_direction != "UNUSED")          // non-LPM 220 standard
1498
            $display("Error!  LPM_DIRECTION value must be \"LEFT\" or \"RIGHT\".");
1499
 
1500
        tmp_q = (lpm_pvalue == "UNUSED") ? 0 : str_to_int(lpm_pvalue);
1501
    end
1502
 
1503
    always @(i_aclr or i_aset)
1504
    begin
1505
                if (i_aclr)
1506
            tmp_q <= (i_aset) ? 'bx : 0;
1507
                else if (i_aset)
1508
            tmp_q <= (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
1509
                                             : str_to_int(lpm_avalue);
1510
    end
1511
 
1512
    always @(posedge clock)
1513
        begin :asyn_block // Asynchronous process
1514
                if (i_aclr)
1515
            tmp_q <= (i_aset) ? 'bx : 0;
1516
                else if (i_aset)
1517
            tmp_q <= (lpm_avalue == "UNUSED") ? {lpm_width{1'b1}}
1518
                                             : str_to_int(lpm_avalue);
1519
                else
1520
                begin :syn_block // Synchronous process
1521
                        if (i_enable)
1522
                        begin
1523
                                if (i_sclr)
1524
                                        tmp_q <= 0;
1525
                                else if (i_sset)
1526
                    tmp_q <= (lpm_svalue == "UNUSED") ? {lpm_width{1'b1}}
1527
                                                     : str_to_int(lpm_svalue);
1528
                                else if (i_load)
1529
                                        tmp_q <= data;
1530
                                else if (!i_load)
1531
                                begin
1532
                    if (lpm_direction == "LEFT" || lpm_direction == "UNUSED")
1533
                                                {abit,tmp_q} <= {tmp_q,i_shiftin};
1534
                    else if (lpm_direction == "RIGHT")
1535
                                                {tmp_q,abit} <= {i_shiftin,tmp_q};
1536
                                end
1537
                        end
1538
                end
1539
        end
1540
 
1541
 
1542
    assign tmp_shiftout = (lpm_direction == "RIGHT") ? tmp_q[0]
1543
                                                     : tmp_q[lpm_width-1];
1544
        assign q = tmp_q;
1545
        assign shiftout = tmp_shiftout;
1546
 
1547
endmodule // lpm_shiftreg
1548
 
1549
//------------------------------------------------------------------------
1550
 
1551
module lpm_ram_dq ( q, data, inclock, outclock, we, address );
1552
 
1553
  parameter lpm_type = "lpm_ram_dq";
1554
  parameter lpm_width = 1;
1555
  parameter lpm_widthad = 1;
1556
  parameter lpm_numwords = 1 << lpm_widthad;
1557
  parameter lpm_indata = "REGISTERED";
1558
  parameter lpm_address_control = "REGISTERED";
1559
  parameter lpm_outdata = "REGISTERED";
1560
  parameter lpm_file = "UNUSED";
1561
  parameter lpm_hint = "UNUSED";
1562
  parameter use_eab = "OFF";
1563
  parameter intended_device_family = "UNUSED";
1564
 
1565
  input  [lpm_width-1:0] data;
1566
  input  [lpm_widthad-1:0] address;
1567
  input  inclock, outclock, we;
1568
  output [lpm_width-1:0] q;
1569
 
1570
 
1571
  // internal reg 
1572
  reg  [lpm_width-1:0] mem_data [lpm_numwords-1:0];
1573
  reg  [lpm_width-1:0] tmp_q;
1574
  reg  [lpm_width-1:0] pdata;
1575
  reg  [lpm_width-1:0] in_data;
1576
  reg  [lpm_widthad-1:0] paddress;
1577
  reg  pwe;
1578
  reg  [lpm_width-1:0]  ZEROS, ONES, UNKNOWN;
1579
  reg  [8*256:1] ram_initf;
1580
  integer i;
1581
 
1582
  tri0 inclock;
1583
  tri0 outclock;
1584
 
1585
  buf (i_inclock, inclock);
1586
  buf (i_outclock, outclock);
1587
 
1588
//---------------------------------------------------------------//
1589
        function ValidAddress;
1590
                input [lpm_widthad-1:0] paddress;
1591
 
1592
                begin
1593
                        ValidAddress = 1'b0;
1594
                        if (^paddress ==='bx)
1595
                            $display("%t:Error!  Invalid address.\n", $time);
1596
                        else if (paddress >= lpm_numwords)
1597
                            $display("%t:Error!  Address out of bound on RAM.\n", $time);
1598
                        else
1599
                                ValidAddress = 1'b1;
1600
                end
1601
  endfunction
1602
//---------------------------------------------------------------//
1603
 
1604
        initial
1605
        begin
1606
 
1607
                // Initialize the internal data register.
1608
                pdata = 0;
1609
                paddress = 0;
1610
                pwe = 0;
1611
 
1612
                if (lpm_width <= 0)
1613
                    $display("Error!  LPM_WIDTH parameter must be greater than 0.");
1614
 
1615
                if (lpm_widthad <= 0)
1616
                    $display("Error!  LPM_WIDTHAD parameter must be greater than 0.");
1617
                // check for number of words out of bound
1618
                if ((lpm_numwords > (1 << lpm_widthad))
1619
                        ||(lpm_numwords <= (1 << (lpm_widthad-1))))
1620
                    $display("Error!  The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
1621
 
1622
                if ((lpm_address_control != "REGISTERED") && (lpm_address_control != "UNREGISTERED"))
1623
                    $display("Error!  LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
1624
                if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
1625
                    $display("Error!  LPM_INDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
1626
                if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
1627
                    $display("Error!  LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
1628
 
1629
 
1630
                for (i=0; i < lpm_width; i=i+1)
1631
                begin
1632
                        ZEROS[i] = 1'b0;
1633
                        ONES[i] = 1'b1;
1634
                        UNKNOWN[i] = 1'bX;
1635
                end
1636
 
1637
                for (i = 0; i < lpm_numwords; i=i+1)
1638
                        mem_data[i] = ZEROS;
1639
 
1640
                // load data to the RAM
1641
                if (lpm_file != "UNUSED")
1642
                begin
1643
`ifdef NO_PLI
1644
                        $readmemh(lpm_file, mem_data);
1645
`else
1646
                        $convert_hex2ver(lpm_file, lpm_width, ram_initf);
1647
                        $readmemh(ram_initf, mem_data);
1648
`endif
1649
                end
1650
 
1651
                tmp_q = ZEROS;
1652
        end
1653
 
1654
 
1655
        always @(posedge i_inclock)
1656
        begin
1657
        if (lpm_address_control == "REGISTERED")
1658
        begin
1659
            if ((we) && ((use_eab == "OFF")  && ((lpm_hint == "USE_EAB=OFF") || (lpm_hint == "UNUSED"))))
1660
            begin
1661
                if (lpm_indata == "REGISTERED")
1662
                    mem_data[address] <= data;
1663
                else
1664
                    mem_data[address] <= pdata;
1665
            end
1666
            paddress <= address;
1667
            pwe <= we;
1668
        end
1669
        if (lpm_indata == "REGISTERED")
1670
            pdata <= data;
1671
        end
1672
 
1673
        always @(data)
1674
        begin
1675
        if (lpm_indata == "UNREGISTERED")
1676
            pdata <= data;
1677
        end
1678
 
1679
        always @(address)
1680
        begin
1681
        if (lpm_address_control == "UNREGISTERED")
1682
            paddress <= address;
1683
        end
1684
 
1685
        always @(we)
1686
        begin
1687
        if (lpm_address_control == "UNREGISTERED")
1688
            pwe <= we;
1689
        end
1690
 
1691
        always @(pdata or paddress or pwe)
1692
        begin :unregistered_inclock
1693
                if (ValidAddress(paddress))
1694
                begin
1695
                    if ((lpm_address_control == "UNREGISTERED") && (pwe))
1696
                        mem_data[paddress] <= pdata;
1697
                end
1698
                else
1699
                begin
1700
                    if (lpm_outdata == "UNREGISTERED")
1701
                        tmp_q <= UNKNOWN;
1702
                end
1703
        end
1704
 
1705
        always @(posedge i_outclock)
1706
        begin
1707
        if (lpm_outdata == "REGISTERED")
1708
                begin
1709
                        if (ValidAddress(paddress))
1710
                            tmp_q <= mem_data[paddress];
1711
                        else
1712
                            tmp_q <= UNKNOWN;
1713
                end
1714
        end
1715
 
1716
        always @(negedge i_inclock or pdata)
1717
        begin
1718
        if ((lpm_address_control == "REGISTERED") && (pwe))
1719
            if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
1720
            begin
1721
                if (i_inclock == 0) mem_data[paddress] = pdata;
1722
            end
1723
        end
1724
 
1725
    assign q = (lpm_outdata == "UNREGISTERED") ? mem_data[paddress] : tmp_q;
1726
 
1727
endmodule // lpm_ram_dq
1728
 
1729
//--------------------------------------------------------------------------
1730
 
1731
module lpm_ram_dp ( q, data, wraddress, rdaddress, rdclock, wrclock, rdclken, wrclken, rden, wren);
1732
 
1733
        parameter lpm_type = "lpm_ram_dp";
1734
        parameter lpm_width = 1;
1735
        parameter lpm_widthad = 1;
1736
        parameter lpm_numwords = 1<< lpm_widthad;
1737
        parameter lpm_indata = "REGISTERED";
1738
        parameter lpm_outdata = "REGISTERED";
1739
        parameter lpm_rdaddress_control  = "REGISTERED";
1740
        parameter lpm_wraddress_control  = "REGISTERED";
1741
        parameter lpm_file = "UNUSED";
1742
        parameter lpm_hint = "UNUSED";
1743
        parameter use_eab = "OFF";
1744
        parameter intended_device_family = "UNUSED";
1745
        parameter rden_used = "TRUE";
1746
 
1747
        input  [lpm_width-1:0] data;
1748
        input  [lpm_widthad-1:0] rdaddress, wraddress;
1749
        input  rdclock, wrclock, rdclken, wrclken, rden, wren;
1750
        output [lpm_width-1:0] q;
1751
 
1752
    // internal reg
1753
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthad)-1:0];
1754
    reg [lpm_width-1:0] i_data_reg, i_data_tmp, i_q_reg, i_q_tmp;
1755
    reg [lpm_width-1:0] ZEROS, ONES, UNKNOWN;
1756
    reg [lpm_widthad-1:0] i_wraddress_reg, i_wraddress_tmp;
1757
    reg [lpm_widthad-1:0] i_rdaddress_reg, i_rdaddress_tmp;
1758
    reg [lpm_widthad-1:0] ZEROS_AD;
1759
    reg i_wren_reg, i_wren_tmp, i_rden_reg, i_rden_tmp;
1760
    reg [8*256:1] ram_initf;
1761
    reg mem_updated;
1762
    integer i, i_numwords;
1763
 
1764
    tri0 wrclock;
1765
    tri1 wrclken;
1766
    tri0 rdclock;
1767
    tri1 rdclken;
1768
    tri0 wren;
1769
    tri1 rden;
1770
 
1771
    buf (i_inclock, wrclock);
1772
    buf (i_inclocken, wrclken);
1773
    buf (i_outclock, rdclock);
1774
    buf (i_outclocken, rdclken);
1775
    buf (i_wren, wren);
1776
    buf (i_rden, rden);
1777
 
1778
//---------------------------------------------------------------//
1779
        function ValidAddress;
1780
                input [lpm_widthad-1:0] paddress;
1781
 
1782
                begin
1783
                        ValidAddress = 1'b0;
1784
            if (^paddress === 'bx)
1785
                $display("%t:Error!  Invalid address.\n", $time);
1786
                        else if (paddress >= lpm_numwords)
1787
                $display("%t:Error!  Address out of bound on RAM.\n", $time);
1788
                        else
1789
                                ValidAddress = 1'b1;
1790
                end
1791
        endfunction
1792
//---------------------------------------------------------------//
1793
 
1794
        initial
1795
        begin
1796
        // Check for invalid parameters
1797
        if (lpm_width < 1)
1798
            $display("Error! lpm_width parameter must be greater than 0.");
1799
        if (lpm_widthad < 1)
1800
            $display("Error! lpm_widthad parameter must be greater than 0.");
1801
 
1802
        if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
1803
            $display("Error! lpm_indata must be \"REGISTERED\" or \"UNREGISTERED\".");
1804
        if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
1805
            $display("Error! lpm_outdata must be \"REGISTERED\" or \"UNREGISTERED\".");
1806
        if ((lpm_wraddress_control != "REGISTERED") && (lpm_wraddress_control != "UNREGISTERED"))
1807
            $display("Error! lpm_wraddress_control must be \"REGISTERED\" or \"UNREGISTERED\".");
1808
        if ((lpm_rdaddress_control != "REGISTERED") && (lpm_rdaddress_control != "UNREGISTERED"))
1809
            $display("Error! lpm_rdaddress_control must be \"REGISTERED\" or \"UNREGISTERED\".");
1810
 
1811
        // Initialize constants
1812
        for (i=0; i<lpm_width; i=i+1)
1813
        begin
1814
            ZEROS[i] = 1'b0;
1815
            ONES[i] = 1'b1;
1816
            UNKNOWN[i] = 1'bx;
1817
        end
1818
        for (i=0; i<lpm_widthad; i=i+1)
1819
            ZEROS_AD[i] = 1'b0;
1820
 
1821
        // Initialize mem_data
1822
        i_numwords = (lpm_numwords) ? lpm_numwords : 1<<lpm_widthad;
1823
        if (lpm_file == "UNUSED")
1824
            for (i=0; i<i_numwords; i=i+1)
1825
                mem_data[i] = ZEROS;
1826
        else
1827
                begin
1828
`ifdef NO_PLI
1829
                        $readmemh(lpm_file, mem_data);
1830
`else
1831
            $convert_hex2ver(lpm_file, lpm_width, ram_initf);
1832
                    $readmemh(ram_initf, mem_data);
1833
`endif
1834
                end
1835
 
1836
        mem_updated = 0;
1837
 
1838
        // Initialize registers
1839
        i_data_reg <= ZEROS;
1840
        i_wraddress_reg <= ZEROS_AD;
1841
        i_rdaddress_reg <= ZEROS_AD;
1842
        i_wren_reg <= 0;
1843
        if (rden_used == "TRUE")
1844
            i_rden_reg <= 0;
1845
        else
1846
            i_rden_reg <= 1;
1847
 
1848
        // Initialize output
1849
        i_q_reg = ZEROS;
1850
        if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
1851
        begin
1852
            if (intended_device_family == "APEX20K")
1853
                i_q_tmp = ZEROS;
1854
            else
1855
                i_q_tmp = ONES;
1856
        end
1857
        else i_q_tmp = ZEROS;
1858
 
1859
 
1860
        end
1861
 
1862
 
1863
    //=========
1864
    // Clocks
1865
    //=========
1866
 
1867
    always @(posedge i_inclock)
1868
        begin
1869
        if (lpm_indata == "REGISTERED")
1870
            if (i_inclocken == 1 && $time > 0)
1871
                i_data_reg <= data;
1872
 
1873
        if (lpm_wraddress_control == "REGISTERED")
1874
            if (i_inclocken == 1 && $time > 0)
1875
            begin
1876
                i_wraddress_reg <= wraddress;
1877
                i_wren_reg <= i_wren;
1878
            end
1879
 
1880
    end
1881
 
1882
    always @(posedge i_outclock)
1883
        begin
1884
        if (lpm_outdata == "REGISTERED")
1885
            if (i_outclocken == 1 && $time > 0)
1886
            begin
1887
                i_q_reg <= i_q_tmp;
1888
            end
1889
 
1890
        if (lpm_rdaddress_control == "REGISTERED")
1891
            if (i_outclocken == 1 && $time > 0)
1892
            begin
1893
                i_rdaddress_reg <= rdaddress;
1894
                i_rden_reg <= i_rden;
1895
            end
1896
    end
1897
 
1898
 
1899
    //=========
1900
    // Memory
1901
    //=========
1902
 
1903
    always @(i_data_tmp or i_wren_tmp or i_wraddress_tmp or negedge i_inclock)
1904
        begin
1905
        if (i_wren_tmp == 1)
1906
            if (ValidAddress(i_wraddress_tmp))
1907
            begin
1908
                if (((use_eab == "ON") || (lpm_hint == "USE_EAB=ON")) && (lpm_wraddress_control == "REGISTERED"))
1909
                begin
1910
                    if (i_inclock == 0)
1911
                    begin
1912
                        mem_data[i_wraddress_tmp] = i_data_tmp;
1913
                        mem_updated <= ~mem_updated;
1914
                    end
1915
                end
1916
                else
1917
                begin
1918
                        mem_data[i_wraddress_tmp] = i_data_tmp;
1919
                        mem_updated <= ~mem_updated;
1920
                end
1921
            end
1922
        end
1923
 
1924
    always @(i_rden_tmp or i_rdaddress_tmp or mem_updated)
1925
        begin
1926
        if (i_rden_tmp == 1)
1927
                    i_q_tmp = (ValidAddress(i_rdaddress_tmp))
1928
                        ? mem_data[i_rdaddress_tmp]
1929
                        : UNKNOWN;
1930
        else if ((intended_device_family == "APEX20K") && ((use_eab == "ON")  || (lpm_hint == "USE_EAB=ON")))
1931
            i_q_tmp = 0;
1932
 
1933
        end
1934
 
1935
 
1936
    //=======
1937
    // Sync
1938
    //=======
1939
 
1940
    always @(wraddress or i_wraddress_reg)
1941
            i_wraddress_tmp = (lpm_wraddress_control == "REGISTERED")
1942
                            ? i_wraddress_reg
1943
                            : wraddress;
1944
    always @(rdaddress or i_rdaddress_reg)
1945
        i_rdaddress_tmp = (lpm_rdaddress_control == "REGISTERED")
1946
                            ? i_rdaddress_reg
1947
                            : rdaddress;
1948
    always @(i_wren or i_wren_reg)
1949
        i_wren_tmp = (lpm_wraddress_control == "REGISTERED")
1950
                       ? i_wren_reg
1951
                       : i_wren;
1952
    always @(i_rden or i_rden_reg)
1953
        i_rden_tmp = (lpm_rdaddress_control == "REGISTERED")
1954
                       ? i_rden_reg
1955
                       : i_rden;
1956
    always @(data or i_data_reg)
1957
        i_data_tmp = (lpm_indata == "REGISTERED")
1958
                       ? i_data_reg
1959
                       : data;
1960
 
1961
    assign q = (lpm_outdata == "REGISTERED") ? i_q_reg : i_q_tmp;
1962
 
1963
endmodule // lpm_ram_dp
1964
 
1965
//------------------------------------------------------------------------
1966
 
1967
module lpm_ram_io ( dio, inclock, outclock, we, memenab, outenab, address );
1968
 
1969
        parameter lpm_type = "lpm_ram_io";
1970
        parameter lpm_width = 1;
1971
        parameter lpm_widthad = 1;
1972
        parameter lpm_numwords = 1<< lpm_widthad;
1973
        parameter lpm_indata = "REGISTERED";
1974
        parameter lpm_address_control = "REGISTERED";
1975
        parameter lpm_outdata = "REGISTERED";
1976
        parameter lpm_file = "UNUSED";
1977
        parameter lpm_hint = "UNUSED";
1978
        parameter use_eab = "OFF";
1979
        parameter intended_device_family = "UNUSED";
1980
 
1981
        input  [lpm_widthad-1:0] address;
1982
        input  inclock, outclock, we;
1983
        input  memenab;
1984
        input  outenab;
1985
        inout  [lpm_width-1:0] dio;
1986
 
1987
 
1988
        // inernal reg 
1989
        reg  [lpm_width-1:0] mem_data [lpm_numwords-1:0];
1990
        reg  [lpm_width-1:0] tmp_io;
1991
        reg  [lpm_width-1:0] tmp_q;
1992
        reg  [lpm_width-1:0] pdio;
1993
        reg  [lpm_widthad-1:0] paddress;
1994
        reg  pwe;
1995
        reg  [lpm_width-1:0] ZEROS, ONES, UNKNOWN, HiZ;
1996
        reg  [8*256:1] ram_initf;
1997
        integer i;
1998
 
1999
        tri0 inclock;
2000
        tri0 outclock;
2001
        tri1 memenab;
2002
        tri1 outenab;
2003
 
2004
 
2005
        buf (i_inclock, inclock);
2006
        buf (i_outclock, outclock);
2007
        buf (i_memenab, memenab);
2008
        buf (i_outenab, outenab);
2009
 
2010
 
2011
//---------------------------------------------------------------//
2012
        function ValidAddress;
2013
                input [lpm_widthad-1:0] paddress;
2014
 
2015
                begin
2016
                        ValidAddress = 1'b0;
2017
                        if (^paddress ==='bx)
2018
                             $display("%t:Error:  Invalid address.", $time);
2019
                         else if (paddress >= lpm_numwords)
2020
                             $display("%t:Error:  Address out of bound on RAM.", $time);
2021
                        else
2022
                                ValidAddress = 1'b1;
2023
                end
2024
        endfunction
2025
//---------------------------------------------------------------//
2026
 
2027
        initial
2028
        begin
2029
 
2030
                if (lpm_width <= 0)
2031
                    $display("Error!  LPM_WIDTH parameter must be greater than 0.");
2032
 
2033
                if (lpm_widthad <= 0)
2034
                    $display("Error!  LPM_WIDTHAD parameter must be greater than 0.");
2035
 
2036
                // check for number of words out of bound
2037
                if ((lpm_numwords > (1 << lpm_widthad))
2038
                        ||(lpm_numwords <= (1 << (lpm_widthad-1))))
2039
                begin
2040
                    $display("Error!  The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
2041
                end
2042
 
2043
                if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
2044
                    $display("Error!  LPM_INDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
2045
 
2046
                if ((lpm_address_control != "REGISTERED") && (lpm_address_control != "UNREGISTERED"))
2047
                    $display("Error!  LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
2048
 
2049
                if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
2050
                    $display("Error!  LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
2051
 
2052
 
2053
                for (i=0; i < lpm_width; i=i+1)
2054
                begin
2055
                        ZEROS[i] = 1'b0;
2056
                        ONES[i] = 1'b1;
2057
                        UNKNOWN[i] = 1'bX;
2058
                        HiZ[i] = 1'bZ;
2059
                end
2060
 
2061
                for (i = 0; i < lpm_numwords; i=i+1)
2062
                        mem_data[i] = ZEROS;
2063
 
2064
                // Initialize input/output 
2065
                pwe <= 0;
2066
                pdio <= 0;
2067
                paddress <= 0;
2068
                tmp_io = 0;
2069
                tmp_q <= ZEROS;
2070
 
2071
                // load data to the RAM
2072
                if (lpm_file != "UNUSED")
2073
                begin
2074
`ifdef NO_PLI
2075
                        $readmemh(lpm_file, mem_data);
2076
`else
2077
                        $convert_hex2ver(lpm_file, lpm_width, ram_initf);
2078
                        $readmemh(ram_initf, mem_data);
2079
`endif
2080
                end
2081
        end
2082
 
2083
 
2084
        always @(dio)
2085
        begin
2086
        if (lpm_indata == "UNREGISTERED")
2087
            pdio <=  dio;
2088
        end
2089
 
2090
        always @(address)
2091
        begin
2092
        if (lpm_address_control == "UNREGISTERED")
2093
            paddress <=  address;
2094
        end
2095
 
2096
 
2097
        always @(we)
2098
        begin
2099
        if (lpm_address_control == "UNREGISTERED")
2100
            pwe <=  we;
2101
        end
2102
 
2103
        always @(posedge i_inclock)
2104
        begin
2105
        if (lpm_indata == "REGISTERED")
2106
            pdio <=  dio;
2107
 
2108
        if (lpm_address_control == "REGISTERED")
2109
                begin
2110
                    paddress <=  address;
2111
                    pwe <=  we;
2112
                end
2113
        end
2114
 
2115
        always @(pdio or paddress or pwe or i_memenab)
2116
        begin :block_a
2117
                if (ValidAddress(paddress))
2118
                begin
2119
                    if (lpm_address_control == "UNREGISTERED")
2120
                        if (pwe && i_memenab)
2121
                            mem_data[paddress] <= pdio;
2122
 
2123
                    if (lpm_outdata == "UNREGISTERED")
2124
                        tmp_q <= mem_data[paddress];
2125
                end
2126
                else
2127
                begin
2128
                    if (lpm_outdata == "UNREGISTERED")
2129
                        tmp_q <= UNKNOWN;
2130
                end
2131
        end
2132
 
2133
        always @(negedge i_inclock or pdio)
2134
        begin
2135
        if (lpm_address_control == "REGISTERED")
2136
                if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
2137
                        if (pwe && i_memenab && (i_inclock == 0))
2138
                            mem_data[paddress] = pdio;
2139
        end
2140
 
2141
        always @(posedge i_inclock)
2142
        begin
2143
        if (lpm_address_control == "REGISTERED")
2144
                if ((use_eab == "OFF") && pwe && i_memenab)
2145
                            mem_data[paddress] <= pdio;
2146
        end
2147
 
2148
        always @(posedge i_outclock)
2149
        begin
2150
        if (lpm_outdata == "REGISTERED")
2151
            tmp_q <= mem_data[paddress];
2152
        end
2153
 
2154
        always @(i_memenab or i_outenab or tmp_q)
2155
        begin
2156
                if (i_memenab && i_outenab)
2157
                    tmp_io = tmp_q;
2158
                else if (!i_memenab || (i_memenab && !i_outenab))
2159
                    tmp_io = HiZ;
2160
        end
2161
 
2162
        assign dio =  tmp_io;
2163
 
2164
endmodule // lpm_ram_io
2165
 
2166
//------------------------------------------------------------------------
2167
 
2168
module lpm_rom ( q, inclock, outclock, memenab, address );
2169
 
2170
        parameter lpm_type = "lpm_rom";
2171
        parameter lpm_width = 1;
2172
        parameter lpm_widthad = 1;
2173
        parameter lpm_numwords = 1 << lpm_widthad;
2174
        parameter lpm_address_control = "REGISTERED";
2175
        parameter lpm_outdata = "REGISTERED";
2176
        parameter lpm_file = "";
2177
        parameter lpm_hint = "UNUSED";
2178
        parameter intended_device_family = "UNUSED";
2179
 
2180
        input  [lpm_widthad-1:0] address;
2181
        input  inclock, outclock;
2182
        input  memenab;
2183
        output [lpm_width-1:0] q;
2184
 
2185
        // inernal reg 
2186
        reg  [lpm_width-1:0] mem_data [lpm_numwords-1:0];
2187
        reg  [lpm_widthad-1:0] paddress;
2188
        reg  [lpm_width-1:0] tmp_q;
2189
        reg  [lpm_width-1:0] tmp_q_reg;
2190
        reg  [lpm_width-1:0] ZEROS, UNKNOWN, HiZ;
2191
        reg  [8*256:1] rom_initf;
2192
        integer i;
2193
 
2194
        tri0 inclock;
2195
        tri0 outclock;
2196
        tri1 memenab;
2197
 
2198
        buf (i_inclock, inclock);
2199
        buf (i_outclock, outclock);
2200
        buf (i_memenab, memenab);
2201
 
2202
 
2203
//---------------------------------------------------------------//
2204
        function ValidAddress;
2205
                input [lpm_widthad-1:0] address;
2206
                begin
2207
                        ValidAddress = 1'b0;
2208
                        if (^address =='bx)
2209
                            $display("%d:Error:  Invalid address.", $time);
2210
                        else if (address >= lpm_numwords)
2211
                            $display("%d:Error:  Address out of bound on ROM.", $time);
2212
                        else
2213
                                ValidAddress = 1'b1;
2214
                end
2215
        endfunction
2216
//---------------------------------------------------------------//
2217
 
2218
        initial
2219
        begin
2220
                // Initialize output
2221
                tmp_q <= 0;
2222
                tmp_q_reg <= 0;
2223
                paddress <= 0;
2224
 
2225
                if (lpm_width <= 0)
2226
                    $display("Error!  LPM_WIDTH parameter must be greater than 0.");
2227
 
2228
                if (lpm_widthad <= 0)
2229
                    $display("Error!  LPM_WIDTHAD parameter must be greater than 0.");
2230
 
2231
                // check for number of words out of bound
2232
                if ((lpm_numwords > (1 << lpm_widthad))
2233
                        ||(lpm_numwords <= (1 << (lpm_widthad-1))))
2234
                    $display("Error!  The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
2235
 
2236
                if ((lpm_address_control != "REGISTERED") && (lpm_address_control != "UNREGISTERED"))
2237
                    $display("Error!  LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
2238
 
2239
                if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
2240
                    $display("Error!  LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
2241
 
2242
 
2243
                for (i=0; i < lpm_width; i=i+1)
2244
                begin
2245
                        ZEROS[i] = 1'b0;
2246
                        UNKNOWN[i] = 1'bX;
2247
                        HiZ[i] = 1'bZ;
2248
                end
2249
 
2250
                for (i = 0; i < lpm_numwords; i=i+1)
2251
                        mem_data[i] = ZEROS;
2252
 
2253
                // load data to the ROM
2254
                if (lpm_file == "" || lpm_file == "UNUSED")
2255
                    $display("Warning:  LPM_ROM must have data file for initialization.\n");
2256
                else
2257
                begin
2258
`ifdef NO_PLI
2259
                        $readmemh(lpm_file, mem_data);
2260
`else
2261
                        $convert_hex2ver(lpm_file, lpm_width, rom_initf);
2262
                        $readmemh(rom_initf, mem_data);
2263
`endif
2264
                end
2265
        end
2266
 
2267
        always @(posedge i_inclock)
2268
        begin
2269
        if (lpm_address_control == "REGISTERED")
2270
            paddress <=  address;
2271
        end
2272
 
2273
        always @(address)
2274
        begin
2275
        if (lpm_address_control == "UNREGISTERED")
2276
            paddress <=  address;
2277
        end
2278
 
2279
        always @(paddress)
2280
        begin
2281
                if (ValidAddress(paddress))
2282
                begin
2283
                    if (lpm_outdata == "UNREGISTERED")
2284
                        tmp_q_reg <=  mem_data[paddress];
2285
                end
2286
                else
2287
                begin
2288
                    if (lpm_outdata == "UNREGISTERED")
2289
                        tmp_q_reg <= UNKNOWN;
2290
                end
2291
        end
2292
 
2293
        always @(posedge i_outclock)
2294
        begin
2295
        if (lpm_outdata == "REGISTERED")
2296
                begin
2297
                        if (ValidAddress(paddress))
2298
                            tmp_q_reg <=  mem_data[paddress];
2299
                        else
2300
                            tmp_q_reg <= UNKNOWN;
2301
                end
2302
        end
2303
 
2304
 
2305
        always @(i_memenab or tmp_q_reg)
2306
        begin
2307
            tmp_q <= (i_memenab) ? tmp_q_reg : HiZ;
2308
        end
2309
 
2310
        assign q = tmp_q;
2311
 
2312
endmodule // lpm_rom
2313
 
2314
//------------------------------------------------------------------------
2315
 
2316
module lpm_fifo ( data, clock, wrreq, rdreq, aclr, sclr, q, usedw, full, empty );
2317
 
2318
        parameter lpm_type = "lpm_fifo";
2319
        parameter lpm_width  = 1;
2320
        parameter lpm_widthu  = 1;
2321
    parameter lpm_numwords = 1;
2322
        parameter lpm_showahead = "OFF";
2323
        parameter lpm_hint = "UNUSED";
2324
 
2325
    input  [lpm_width-1:0] data;
2326
    input  clock;
2327
    input  wrreq;
2328
    input  rdreq;
2329
    input  aclr;
2330
    input  sclr;
2331
        output [lpm_width-1:0] q;
2332
        output [lpm_widthu-1:0] usedw;
2333
        output full;
2334
        output empty;
2335
 
2336
 
2337
        // internal reg
2338
        reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
2339
        reg [lpm_width-1:0] tmp_q;
2340
        reg [lpm_width-1:0] ZEROS;
2341
        reg [lpm_widthu+1:0] count_id;
2342
        reg [lpm_widthu-1:0] write_id;
2343
        reg [lpm_widthu-1:0] read_id;
2344
        reg empty_flag;
2345
        reg full_flag;
2346
        integer i;
2347
 
2348
        // VCS fix
2349
        reg [lpm_widthu+1:0] usedw_tmp;
2350
 
2351
        tri0 aclr;
2352
        tri0 sclr;
2353
 
2354
        buf (i_aclr, aclr);
2355
        buf (i_sclr, sclr);
2356
 
2357
 
2358
        initial
2359
        begin
2360
        if (lpm_width <= 0)
2361
            $display("Error!  LPM_WIDTH must be greater than 0.");
2362
 
2363
        if (lpm_numwords < 1)
2364
            $display("Error!  LPM_NUMWORDS must be greater than 0.");
2365
 
2366
                // check for number of words out of bound
2367
        if ((lpm_widthu != 1) && (lpm_numwords > (1 << lpm_widthu)))
2368
            $display("Error!  The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHU.");
2369
        if (lpm_numwords <= (1 << (lpm_widthu-1)) && lpm_numwords > 1)
2370
            $display("Error!  The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHU.");
2371
 
2372
        if (lpm_showahead != "ON" && lpm_showahead != "OFF")
2373
            $display("Error!  LPM_SHOWAHEAD must be \"ON\" or \"OFF\".");
2374
 
2375
 
2376
                for (i=0; i < lpm_width; i=i+1)
2377
                        ZEROS[i] = 1'b0;
2378
 
2379
                for (i = 0; i < lpm_numwords; i=i+1)
2380
                        mem_data[i] = ZEROS;
2381
 
2382
                full_flag = 0;
2383
                empty_flag = 1;
2384
                read_id = 0;
2385
                write_id = 0;
2386
                count_id = 0;
2387
                usedw_tmp = 0;
2388
                tmp_q = ZEROS;
2389
        end
2390
 
2391
    always @(posedge clock or posedge i_aclr)
2392
        begin
2393
                if (i_aclr)
2394
                begin
2395
                        tmp_q = ZEROS;
2396
                        full_flag = 0;
2397
                        empty_flag = 1;
2398
                        read_id = 0;
2399
                        write_id = 0;
2400
                        count_id = 0;
2401
                        if (lpm_showahead == "ON")
2402
                                tmp_q = mem_data[0];
2403
                end
2404
                else if (clock)
2405
                begin
2406
                        if (i_sclr)
2407
                        begin
2408
                                tmp_q <= mem_data[read_id];
2409
                                full_flag <= 0;
2410
                                empty_flag <= 1;
2411
                                read_id = 0;
2412
                                write_id = 0;
2413
                                count_id = 0;
2414
                                if (lpm_showahead == "ON")
2415
                                        tmp_q <= mem_data[0];
2416
                        end
2417
                        else
2418
                        begin
2419
                                // both WRITE and READ
2420
                                if ((wrreq && !full_flag) && (rdreq && !empty_flag))
2421
                                begin
2422
                                        mem_data[write_id] = data;
2423
                                        if (write_id >= lpm_numwords-1)
2424
                                                write_id = 0;
2425
                                        else
2426
                                                write_id = write_id + 1;
2427
 
2428
                                        tmp_q <= mem_data[read_id];
2429
                                        if (read_id >= lpm_numwords-1)
2430
                                                read_id = 0;
2431
                                        else
2432
                                                read_id = read_id + 1;
2433
                                        if (lpm_showahead == "ON")
2434
                                                tmp_q <= mem_data[read_id];
2435
                                end
2436
 
2437
                                // WRITE
2438
                                else if (wrreq && !full_flag)
2439
                                begin
2440
                                        mem_data[write_id] = data;
2441
                                        if (lpm_showahead == "ON")
2442
                                        begin
2443
                                                // changed by M.Singal :
2444
                                                // showahead should show current
2445
                                                // write data
2446
//                                              tmp_q <= mem_data[read_id];
2447
                                                tmp_q <= data;
2448
                                        end
2449
                                        count_id = count_id + 1;
2450
                                        empty_flag <= 0;
2451
                                        if (count_id >= lpm_numwords)
2452
                                        begin
2453
                                                full_flag <= 1;
2454
                                                count_id = lpm_numwords;
2455
                                        end
2456
                                        if (write_id >= lpm_numwords-1)
2457
                                                write_id = 0;
2458
                                        else
2459
                                                write_id = write_id + 1;
2460
                                end
2461
 
2462
                                // READ
2463
                                else if (rdreq && !empty_flag)
2464
                                begin
2465
                                        tmp_q <= mem_data[read_id];
2466
                                        count_id = count_id - 1;
2467
                                        full_flag <= 0;
2468
                                        if (count_id <= 0)
2469
                                        begin
2470
                                                empty_flag <= 1;
2471
                                                count_id = 0;
2472
                                        end
2473
                                        if (read_id >= lpm_numwords-1)
2474
                                                read_id = 0;
2475
                                        else
2476
                                                read_id = read_id + 1;
2477
                                        if (lpm_showahead == "ON")
2478
                                                tmp_q <= mem_data[read_id];
2479
                                end
2480
                        end
2481
                end
2482
                usedw_tmp <= count_id;
2483
        end
2484
 
2485
        assign q = tmp_q;
2486
        assign full = full_flag;
2487
        assign empty = empty_flag;
2488
//      assign usedw = count_id;
2489
        assign usedw = usedw_tmp;
2490
 
2491
endmodule // lpm_fifo
2492
 
2493
//------------------------------------------------------------------------
2494
 
2495
module lpm_fifo_dc_dffpipe ( d, q, clock, aclr );
2496
 
2497
    parameter lpm_delay = 1;
2498
    parameter lpm_width = 128;
2499
 
2500
    input [lpm_width-1:0] d;
2501
    input clock;
2502
    input aclr;
2503
    output [lpm_width-1:0] q;
2504
 
2505
        // internal reg
2506
    reg [lpm_width-1:0] dffpipe [lpm_delay:0];
2507
    reg [lpm_width-1:0] i_q;
2508
    integer delay, i;
2509
 
2510
    initial
2511
    begin
2512
        delay = lpm_delay-1;
2513
        for (i=0; i<lpm_delay; i=i+1)
2514
            dffpipe[i] = 0;
2515
        i_q = 0;
2516
    end
2517
 
2518
    always @(d)
2519
    begin
2520
        if (lpm_delay == 0 && !aclr)
2521
            i_q <= (aclr) ? 0 : d;
2522
    end
2523
 
2524
    always @(aclr)
2525
    begin
2526
        if (aclr)
2527
        begin
2528
            for (i=0; i<lpm_delay; i=i+1)
2529
                dffpipe[i] = 0;
2530
            i_q <= 0;
2531
        end
2532
    end
2533
 
2534
    always @(posedge clock)
2535
    begin
2536
        if (!aclr && lpm_delay > 0 && $time > 0)
2537
        begin
2538
            if (delay > 0)
2539
                for (i=delay; i>0; i=i-1)
2540
                    dffpipe[i] = dffpipe[i-1];
2541
            dffpipe[0] = d;
2542
            i_q <= dffpipe[delay];
2543
        end
2544
    end
2545
 
2546
    assign q = i_q;
2547
 
2548
endmodule // lpm_fifo_dc_dffpipe
2549
 
2550
//------------------------------------------------------------------------
2551
 
2552
module lpm_fifo_dc_fefifo ( usedw_in, wreq, rreq, empty, full, clock, aclr );
2553
 
2554
    parameter lpm_widthad = 1;
2555
    parameter lpm_numwords = 1;
2556
    parameter lpm_mode = "READ";
2557
    parameter underflow_checking = "ON";
2558
    parameter overflow_checking = "ON";
2559
 
2560
    input [lpm_widthad-1:0] usedw_in;
2561
    input wreq, rreq;
2562
    output empty, full;
2563
    input clock;
2564
    input aclr;
2565
 
2566
        // internal reg
2567
    reg [1:0] sm_empty;
2568
    reg i_empty;
2569
    reg lrreq;
2570
    reg valid_rreq;
2571
    reg i_full;
2572
    integer almostfull;
2573
 
2574
    initial
2575
    begin
2576
        if (lpm_mode != "READ" && lpm_mode != "WRITE")
2577
            $display("Error!  LPM_MODE must be \"READ\" or \"WRITE\".");
2578
        if(underflow_checking != "ON" && underflow_checking != "OFF")
2579
            $display("Error! underflow_checking must be ON or OFF.");
2580
        if(overflow_checking != "ON" && overflow_checking != "OFF")
2581
            $display("Error! overflow_checking must be ON or OFF.");
2582
 
2583
        sm_empty = 2'b00;
2584
        i_empty = 1'b1;
2585
        lrreq = 1'b0;
2586
        i_full = 1'b0;
2587
        almostfull = (lpm_numwords >= 3) ? lpm_numwords-3 : 0;
2588
    end
2589
 
2590
    always @(rreq or i_empty)
2591
        valid_rreq = (underflow_checking == "OFF") ? rreq
2592
                                                   : rreq && !i_empty;
2593
 
2594
    always @(posedge clock or posedge aclr)
2595
    begin
2596
        if (aclr)
2597
        begin
2598
            sm_empty = 2'b00;
2599
            lrreq <= 1'b0;
2600
        end
2601
        else // if ($time > 0)
2602
        begin
2603
            lrreq <= valid_rreq;
2604
            if (lpm_mode == "READ")
2605
            begin
2606
               casex (sm_empty)
2607
                    2'b00:                          // state_empty
2608
                        if (usedw_in != 0)
2609
                            sm_empty = 2'b01;
2610
                    2'b01:                          // state_non_empty
2611
                        if (rreq && ((usedw_in==1 && !lrreq) || (usedw_in==2 && lrreq)))
2612
                            sm_empty = 2'b10;
2613
                    2'b10:                          // state_emptywait
2614
                        if (usedw_in > 1) sm_empty = 2'b01;
2615
                        else sm_empty = 2'b00;
2616
                endcase
2617
            end
2618
            else if (lpm_mode == "WRITE")
2619
            begin
2620
                casex (sm_empty)
2621
                    2'b00:                          // state_empty
2622
                        if (wreq)
2623
                            sm_empty = 2'b01;
2624
                    2'b01:                          // state_one
2625
                        if (!wreq)
2626
                            sm_empty = 2'b11;
2627
                    2'b11:                          // state_non_empty
2628
                        if (wreq)
2629
                            sm_empty = 2'b01;
2630
                        else if (usedw_in == 0)
2631
                            sm_empty = 2'b00;
2632
                endcase
2633
            end
2634
        end
2635
 
2636
        i_empty <= !sm_empty[0];
2637
        i_full <= (!aclr && $time>0 && usedw_in>=almostfull) ? 1'b1 : 1'b0;
2638
    end
2639
 
2640
    assign empty = i_empty;
2641
    assign full = i_full;
2642
 
2643
endmodule // lpm_fifo_dc_fefifo
2644
 
2645
//------------------------------------------------------------------------
2646
//------------------------------------------------------------------------
2647
module lpm_fifo_dc ( data, rdclock, wrclock, aclr, rdreq, wrreq, rdfull,
2648
                      wrfull, rdempty, wrempty, rdusedw, wrusedw, q );
2649
 
2650
        parameter lpm_type = "lpm_fifo_dc";
2651
        parameter lpm_width = 1;
2652
        parameter lpm_widthu = 1;
2653
        parameter lpm_numwords = 1;
2654
        parameter lpm_showahead = "OFF";
2655
        parameter lpm_hint = "USE_EAB=ON";
2656
        parameter underflow_checking = "ON";
2657
        parameter overflow_checking = "ON";
2658
        parameter delay_rdusedw = 1;
2659
        parameter delay_wrusedw = 1;
2660
        parameter rdsync_delaypipe = 3;
2661
        parameter wrsync_delaypipe = 3;
2662
 
2663
        input [lpm_width-1:0] data;
2664
        input rdclock;
2665
        input wrclock;
2666
        input wrreq;
2667
        input rdreq;
2668
        input aclr;
2669
        output rdfull;
2670
        output wrfull;
2671
        output rdempty;
2672
        output wrempty;
2673
        output [lpm_widthu-1:0] rdusedw;
2674
        output [lpm_widthu-1:0] wrusedw;
2675
        output [lpm_width-1:0] q;
2676
 
2677
        // internal reg
2678
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0];
2679
    reg [lpm_widthu-1:0] i_rdptr, i_wrptr;
2680
    wire [lpm_widthu-1:0] w_rdptrrg, w_wrdelaycycle;
2681
    wire [lpm_widthu-1:0] w_ws_nbrp, w_rs_nbwp, w_ws_dbrp, w_rs_dbwp;
2682
    wire [lpm_widthu-1:0] w_wr_dbuw, w_rd_dbuw, w_rdusedw, w_wrusedw;
2683
    reg [lpm_widthu-1:0] i_wr_udwn, i_rd_udwn;
2684
    wire w_rdempty, w_wrempty, wrdfull, w_wrfull;
2685
    reg i_rdempty, i_wrempty;
2686
    reg i_rdfull, i_wrfull;
2687
    reg i_rden, i_wren, i_rdenclock;
2688
    reg [lpm_width-1:0] i_q;
2689
    integer i;
2690
 
2691
    reg [lpm_width-1:0] i_data_tmp, i_data_reg;
2692
    reg [lpm_width-1:0] i_q_tmp, i_q_reg;
2693
    reg [lpm_widthu-1:0] i_rdptr_tmp, i_wrptr_tmp, i_wrptr_reg;
2694
    reg i_wren_tmp, i_wren_reg;
2695
 
2696
        tri0 aclr;
2697
        buf (i_aclr, aclr);
2698
 
2699
 
2700
    initial
2701
    begin
2702
        if(lpm_showahead != "ON" && lpm_showahead != "OFF")
2703
            $display("Error! lpm_showahead must be ON or OFF.");
2704
        if(underflow_checking != "ON" && underflow_checking != "OFF")
2705
            $display("Error! underflow_checking must be ON or OFF.");
2706
        if(overflow_checking != "ON" && overflow_checking != "OFF")
2707
            $display("Error! overflow_checking must be ON or OFF.");
2708
 
2709
        i_rdptr = 0;
2710
        i_wrptr = 0;
2711
        i_rdempty = 1;
2712
        i_wrempty = 1;
2713
        i_rdfull = 0;
2714
        i_wrfull = 0;
2715
        i_rden = 0;
2716
        i_rdenclock = 0;
2717
        i_wren = 0;
2718
        i_q = 0;
2719
 
2720
        i_data_tmp = 0;
2721
        i_data_reg = 0;
2722
        i_q_tmp = 0;
2723
        i_q_reg = 0;
2724
        i_rdptr_tmp = 0;
2725
        i_wrptr_tmp = 0;
2726
        i_wrptr_reg = 0;
2727
        i_wren_tmp = 0;
2728
        i_wren_reg = 0;
2729
        i_wr_udwn = 0;
2730
        i_rd_udwn = 0;
2731
 
2732
        for (i=0; i<(1<<lpm_widthu); i=i+1)
2733
            mem_data[i] = 0;
2734
    end
2735
 
2736
 
2737
    //--------
2738
    // FIFOram
2739
    //--------
2740
 
2741
    always @(rdreq or i_rdempty)
2742
        i_rden = (underflow_checking == "OFF") ? rdreq
2743
                                               : rdreq && !i_rdempty;
2744
    always @(wrreq or i_wrfull)
2745
        i_wren = (overflow_checking == "OFF") ? wrreq
2746
                                              : wrreq && !i_wrfull;
2747
 
2748
    // FIFOram_sync
2749
    always @(i_data_reg or i_q_tmp or i_q_reg or i_aclr or
2750
             i_rdptr or i_wren_reg or i_wrptr_reg)
2751
    begin
2752
        if (i_aclr)
2753
        begin
2754
            i_wrptr_tmp <= 0;
2755
            i_rdptr_tmp <= 0;
2756
            i_wren_tmp <= 0;
2757
            i_data_tmp <= 0;
2758
            i_q <= (lpm_showahead == "ON") ? i_q_tmp : 0;
2759
        end
2760
        else
2761
        begin
2762
            i_wrptr_tmp <= i_wrptr_reg;
2763
            i_rdptr_tmp <= i_rdptr;
2764
            i_wren_tmp <= i_wren_reg;
2765
            i_data_tmp <= i_data_reg;
2766
            i_q <= (lpm_showahead == "ON") ? i_q_tmp : i_q_reg;
2767
        end
2768
    end
2769
 
2770
    // FIFOram_aclr
2771
    always @(i_aclr)
2772
    begin
2773
        if (i_aclr)
2774
        begin
2775
            i_data_reg <= 0;
2776
            i_wrptr_reg <= 0;
2777
            i_wren_reg <= 0;
2778
            i_q_reg <= 0;
2779
        end
2780
    end
2781
 
2782
    // FIFOram_wrclock
2783
    always @(posedge wrclock)
2784
    begin
2785
        if (!i_aclr && $time > 0)
2786
        begin
2787
            i_data_reg <= data;
2788
            i_wrptr_reg <= i_wrptr;
2789
            i_wren_reg <= i_wren;
2790
        end
2791
    end
2792
 
2793
    // FIFOram_rdclock
2794
    always @(posedge rdclock)
2795
    begin
2796
        if (!i_aclr && i_rden && $time > 0)
2797
            i_q_reg <= i_q_tmp;
2798
    end
2799
 
2800
    // FIFOram_memory_read
2801
    always @(i_rdptr_tmp)
2802
        i_q_tmp <= mem_data[i_rdptr_tmp];
2803
 
2804
    // FIFOram_memory_write_eab
2805
    always @(negedge wrclock)
2806
    begin
2807
        if (lpm_hint == "USE_EAB=ON")
2808
        begin
2809
            if (i_wren_tmp)
2810
                mem_data[i_wrptr_tmp] = i_data_tmp;
2811
            i_q_tmp = mem_data[i_rdptr_tmp];
2812
        end
2813
    end
2814
 
2815
    // FIFOram_memory_write_lcell
2816
    always @(posedge wrclock)
2817
    begin
2818
        if (lpm_hint != "USE_EAB=ON")
2819
        begin
2820
            if (i_wren_tmp)
2821
                mem_data[i_wrptr_tmp] = i_data_tmp;
2822
            i_q_tmp = mem_data[i_rdptr_tmp];
2823
        end
2824
    end
2825
 
2826
 
2827
    //---------
2828
    // Counters
2829
    //---------
2830
 
2831
    // rdptr
2832
    always @(i_aclr)
2833
        if (i_aclr)
2834
            i_rdptr <= 0;
2835
    always @(posedge rdclock)
2836
        if (!i_aclr && i_rden && $time > 0)
2837
            i_rdptr <= ((i_rdptr < (1<<lpm_widthu)-1) || (underflow_checking == "OFF"))
2838
                        ? i_rdptr+1 : 0;
2839
 
2840
    // wrptr
2841
    always @(i_aclr)
2842
        if (i_aclr)
2843
            i_wrptr <= 0;
2844
    always @(posedge wrclock)
2845
        if (!i_aclr && i_wren && $time > 0)
2846
            i_wrptr <= ((i_wrptr < (1<<lpm_widthu)-1) || (overflow_checking == "OFF"))
2847
                        ? i_wrptr+1 : 0;
2848
 
2849
    //-------------------
2850
    // Delays & DFF Pipes
2851
    //-------------------
2852
 
2853
    always @(negedge rdclock)  i_rdenclock <= 0;
2854
    always @(posedge rdclock)  if (i_rden) i_rdenclock <= 1;
2855
 
2856
    lpm_fifo_dc_dffpipe RDPTR_D ( .d (i_rdptr), .q (w_rdptrrg),
2857
                             .clock (i_rdenclock), .aclr (i_aclr) );
2858
    lpm_fifo_dc_dffpipe WRPTR_D ( .d (i_wrptr), .q (w_wrdelaycycle),
2859
                             .clock (wrclock), .aclr (i_aclr) );
2860
    defparam
2861
        RDPTR_D.lpm_delay = 0,
2862
        RDPTR_D.lpm_width = lpm_widthu,
2863
        WRPTR_D.lpm_delay = 1,
2864
        WRPTR_D.lpm_width = lpm_widthu;
2865
 
2866
    lpm_fifo_dc_dffpipe WS_NBRP ( .d (w_rdptrrg), .q (w_ws_nbrp),
2867
                             .clock (wrclock), .aclr (i_aclr) );
2868
    lpm_fifo_dc_dffpipe RS_NBWP ( .d (w_wrdelaycycle), .q (w_rs_nbwp),
2869
                             .clock (rdclock), .aclr (i_aclr) );
2870
    lpm_fifo_dc_dffpipe WS_DBRP ( .d (w_ws_nbrp), .q (w_ws_dbrp),
2871
                             .clock (wrclock), .aclr (i_aclr) );
2872
    lpm_fifo_dc_dffpipe RS_DBWP ( .d (w_rs_nbwp), .q (w_rs_dbwp),
2873
                             .clock (rdclock), .aclr (i_aclr) );
2874
    defparam
2875
        WS_NBRP.lpm_delay = wrsync_delaypipe,
2876
        WS_NBRP.lpm_width = lpm_widthu,
2877
        RS_NBWP.lpm_delay = rdsync_delaypipe,
2878
        RS_NBWP.lpm_width = lpm_widthu,
2879
        WS_DBRP.lpm_delay = 1,              // gray_delaypipe
2880
        WS_DBRP.lpm_width = lpm_widthu,
2881
        RS_DBWP.lpm_delay = 1,              // gray_delaypipe
2882
        RS_DBWP.lpm_width = lpm_widthu;
2883
 
2884
    always @(i_wrptr or w_ws_dbrp)
2885
        i_wr_udwn = i_wrptr - w_ws_dbrp;
2886
 
2887
    always @(i_rdptr or w_rs_dbwp)
2888
        i_rd_udwn = w_rs_dbwp - i_rdptr;
2889
 
2890
    lpm_fifo_dc_dffpipe WRUSEDW ( .d (i_wr_udwn), .q (w_wrusedw),
2891
                             .clock (wrclock), .aclr (i_aclr) );
2892
    lpm_fifo_dc_dffpipe RDUSEDW ( .d (i_rd_udwn), .q (w_rdusedw),
2893
                             .clock (rdclock), .aclr (i_aclr) );
2894
    lpm_fifo_dc_dffpipe WR_DBUW ( .d (i_wr_udwn), .q (w_wr_dbuw),
2895
                             .clock (wrclock), .aclr (i_aclr) );
2896
    lpm_fifo_dc_dffpipe RD_DBUW ( .d (i_rd_udwn), .q (w_rd_dbuw),
2897
                             .clock (rdclock), .aclr (i_aclr) );
2898
    defparam
2899
        WRUSEDW.lpm_delay = delay_wrusedw,
2900
        WRUSEDW.lpm_width = lpm_widthu,
2901
        RDUSEDW.lpm_delay = delay_rdusedw,
2902
        RDUSEDW.lpm_width = lpm_widthu,
2903
        WR_DBUW.lpm_delay = 1,              // wrusedw_delaypipe
2904
        WR_DBUW.lpm_width = lpm_widthu,
2905
        RD_DBUW.lpm_delay = 1,              // rdusedw_delaypipe
2906
        RD_DBUW.lpm_width = lpm_widthu;
2907
 
2908
 
2909
    //-----------
2910
    // Full/Empty
2911
    //-----------
2912
 
2913
    lpm_fifo_dc_fefifo WR_FE ( .usedw_in (w_wr_dbuw), .wreq (wrreq), .rreq (rdreq),
2914
                          .clock (wrclock), .aclr (i_aclr),
2915
                          .empty (w_wrempty), .full (w_wrfull) );
2916
    lpm_fifo_dc_fefifo RD_FE ( .usedw_in (w_rd_dbuw), .rreq (rdreq), .wreq(wrreq),
2917
                          .clock (rdclock), .aclr (i_aclr),
2918
                          .empty (w_rdempty), .full (w_rdfull) );
2919
 
2920
    defparam
2921
        WR_FE.lpm_widthad = lpm_widthu,
2922
        WR_FE.lpm_numwords = lpm_numwords,
2923
        WR_FE.underflow_checking = underflow_checking,
2924
        WR_FE.overflow_checking = overflow_checking,
2925
        WR_FE.lpm_mode = "WRITE",
2926
        RD_FE.lpm_widthad = lpm_widthu,
2927
        RD_FE.lpm_numwords = lpm_numwords,
2928
        RD_FE.underflow_checking = underflow_checking,
2929
        RD_FE.overflow_checking = overflow_checking,
2930
        RD_FE.lpm_mode = "READ";
2931
 
2932
    always @(w_wrfull)  i_wrfull = w_wrfull;
2933
    always @(w_rdfull)  i_rdfull = w_rdfull;
2934
    always @(w_wrempty)  i_wrempty = w_wrempty;
2935
    always @(w_rdempty)  i_rdempty = w_rdempty;
2936
 
2937
 
2938
    //--------
2939
    // Outputs
2940
    //--------
2941
 
2942
    assign q = i_q;
2943
    assign wrfull = i_wrfull;
2944
    assign rdfull = i_rdfull;
2945
    assign wrempty = i_wrempty;
2946
    assign rdempty = i_rdempty;
2947
    assign wrusedw = w_wrusedw;
2948
    assign rdusedw = w_rdusedw;
2949
 
2950
endmodule // lpm_fifo_dc
2951
 
2952
//------------------------------------------------------------------------
2953
 
2954
module lpm_inpad ( result, pad );
2955
 
2956
        parameter lpm_type = "lpm_inpad";
2957
        parameter lpm_width = 1;
2958
        parameter lpm_hint = "UNUSED";
2959
 
2960
        input  [lpm_width-1:0] pad;
2961
        output [lpm_width-1:0] result;
2962
 
2963
        reg    [lpm_width-1:0] result;
2964
 
2965
        always @(pad)
2966
        begin
2967
                result = pad;
2968
        end
2969
 
2970
endmodule // lpm_inpad
2971
 
2972
//------------------------------------------------------------------------
2973
 
2974
module lpm_outpad ( data, pad );
2975
 
2976
        parameter lpm_type = "lpm_outpad";
2977
        parameter lpm_width = 1;
2978
        parameter lpm_hint = "UNUSED";
2979
 
2980
    input  [lpm_width-1:0] data;
2981
    output [lpm_width-1:0] pad;
2982
 
2983
    reg    [lpm_width-1:0] pad;
2984
 
2985
        always @(data)
2986
        begin
2987
                pad = data;
2988
        end
2989
 
2990
endmodule // lpm_outpad
2991
 
2992
//------------------------------------------------------------------------
2993
 
2994
module lpm_bipad ( result, pad, data, enable );
2995
 
2996
        parameter lpm_type = "lpm_bipad";
2997
        parameter lpm_width = 1;
2998
        parameter lpm_hint = "UNUSED";
2999
 
3000
        input  [lpm_width-1:0] data;
3001
        input  enable;
3002
        inout  [lpm_width-1:0] pad;
3003
        output [lpm_width-1:0] result;
3004
 
3005
        reg    [lpm_width-1:0] tmp_pad;
3006
        reg    [lpm_width-1:0] result;
3007
 
3008
        always @(data or pad or enable)
3009
        begin
3010
                if (enable == 1)
3011
                begin
3012
                        tmp_pad = data;
3013
                        result = 'bz;
3014
                end
3015
                else if (enable == 0)
3016
                begin
3017
                        result = pad;
3018
                        tmp_pad = 'bz;
3019
                end
3020
        end
3021
 
3022
        assign pad = tmp_pad;
3023
 
3024
endmodule // lpm_bipad

powered by: WebSVN 2.1.0

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