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

Subversion Repositories cfi_ctrl

[/] [cfi_ctrl/] [trunk/] [bench/] [verilog/] [x28fxxxp30.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 julius
//          _/             _/_/
2
//        _/_/           _/_/_/
3
//      _/_/_/_/         _/_/_/
4
//      _/_/_/_/_/       _/_/_/              ____________________________________________ 
5
//      _/_/_/_/_/       _/_/_/             /                                           / 
6
//      _/_/_/_/_/       _/_/_/            /                                 28F256P30 / 
7
//      _/_/_/_/_/       _/_/_/           /                                           /  
8
//      _/_/_/_/_/_/     _/_/_/          /                                   256Mbit / 
9
//      _/_/_/_/_/_/     _/_/_/         /                                single die / 
10
//      _/_/_/ _/_/_/    _/_/_/        /                                           / 
11
//      _/_/_/  _/_/_/   _/_/_/       /                  Verilog Behavioral Model / 
12
//      _/_/_/   _/_/_/  _/_/_/      /                               Version 1.3 / 
13
//      _/_/_/    _/_/_/ _/_/_/     /                                           /
14
//      _/_/_/     _/_/_/_/_/_/    /           Copyright (c) 2010 Numonyx B.V. / 
15
//      _/_/_/      _/_/_/_/_/    /___________________________________________/ 
16
//      _/_/_/       _/_/_/_/      
17
//      _/_/          _/_/_/  
18
// 
19
//     
20
//             NUMONYX              
21
`include "def.h"
22
`include "CUIcommandData.h"
23
`include "data.h"
24
`include "UserData.h"
25
`include "BankLib.h"
26
`include "TimingData.h"
27
 
28
// **********************************
29
//
30
// Timing Lib Module :
31
// 
32
//      checks all timing constraints            
33
//
34
// **********************************
35
 
36
module TimingLibModule(A, DQ, W_N, G_N, E_N, L_N, WP_N, CK, VPP);
37
 
38
   input [`ADDRBUS_dim-1:0] A;           // Address Bus 
39
   input [`DATABUS_dim-1:0] DQ;          // Data I/0 Bus
40
 
41
   input                    W_N, G_N, E_N, L_N, WP_N, CK;
42
   input [`Voltage_range]   VPP;
43
 
44
   integer                  AddValid_time;
45
   integer                  AddNotValid_time;
46
   integer                  DataValid_time;
47
   integer                  DataXX_time;
48
 
49
   integer                  WriteEnableLow_time;
50
   integer                  WriteEnableHigh_time;
51
   integer                  OutputEnableLow_time;
52
   integer                  OutputEnableHigh_time;
53
   integer                  LatchEnableHigh_time;
54
   integer                  LatchEnableLow_time;
55
   integer                  ChipEnableLow_time;
56
   integer                  ChipEnableHigh_time;
57
   integer                  RisingEdge_time;
58
   integer                  FallingEdge_time;
59
 
60
   integer                  WaitValid_time;
61
 
62
   integer                  WriteProtectHigh_time;
63
   integer                  WriteProtectLow_time;
64
   integer                  VPPSupplyHigh_time;
65
   integer                  VPPSupplyLow_time;
66
 
67
   reg                      afterReset;
68
 
69
   reg                      isValid;
70
   reg                      dataValid;
71
   reg                      addressValid;
72
   reg                      reading;
73
   reg                      writing;
74
   reg                      dataXX;
75
   time                     temp;
76
 
77
 
78
initial begin
79
 
80
   AddValid_time         = 0;
81
   AddNotValid_time      = 0;
82
   DataValid_time        = 0;
83
   DataXX_time           = 0;
84
 
85
   WriteEnableLow_time   = 0;
86
   WriteEnableHigh_time  = 0;
87
   OutputEnableLow_time  = 0;
88
   OutputEnableHigh_time = 0;
89
   LatchEnableHigh_time  = 0;
90
   LatchEnableLow_time   = 0;
91
   ChipEnableLow_time    = 0;
92
   ChipEnableHigh_time   = 0;
93
 
94
   WaitValid_time        = 0;
95
 
96
   WriteProtectHigh_time = 0;
97
   WriteProtectLow_time  = 0;
98
 
99
   RisingEdge_time  = 0;
100
   FallingEdge_time = 0;
101
 
102
   dataValid = `FALSE;
103
   dataXX    = `FALSE;
104
   addressValid = `FALSE;
105
 
106
   reading = `FALSE;
107
   writing = `FALSE;
108
 
109
   afterReset = `FALSE;
110
 
111
end
112
 
113
 
114
// **************
115
//
116
// Change address
117
//
118
// **************
119
 
120
always @(A) begin : AddressCheck
121
 
122
   if (`TimingChecks == "off")
123
      disable AddressCheck;
124
 
125
   if ($time > `Reset_time)
126
   begin
127
      if (isAddValid(A))               // Address Valid
128
      begin
129
         temp = $time - AddValid_time;
130
         checkTiming("tAVAV", TimingData_man.tAVAV, temp, "min");
131
 
132
         temp = $time - WriteEnableHigh_time;
133
         checkTiming("tWHAV", TimingData_man.tWHAV, temp, "min");
134
 
135
         AddValid_time = $time;
136
         addressValid = `TRUE;
137
      end
138
 
139
      else
140
      begin
141
         if (isAddXX(A) || isAddZZ(A))             // Address XXXX o ZZZZ
142
         begin
143
 
144
            if (addressValid)
145
            begin
146
               temp = $time - LatchEnableHigh_time;
147
               checkTiming("tLHAX", TimingData_man.tLHAX, temp, "min");
148
 
149
               temp = $time - WriteEnableHigh_time;
150
               checkTiming("tWHAX", TimingData_man.tWHAX, temp, "min");
151
 
152
 
153
               AddNotValid_time = $time;
154
            end
155
            addressValid = `FALSE;
156
         end
157
      end
158
   end
159
end
160
 
161
 
162
// ***********
163
//
164
// Change data
165
//
166
// ***********
167
 
168
always @(DQ) begin : DataCheck
169
 
170
   if (`TimingChecks == "off")
171
      disable DataCheck;
172
 
173
   if ($time > `Reset_time)
174
   begin
175
 
176
      if (isDataValid(DQ))               // Data Valid
177
      begin
178
         if (ConfigReg_man.isSynchronous)               // Synchronous mode 
179
 
180
         begin
181
            if (reading)
182
               if (ConfigReg_man.isRisingClockEdge)
183
               begin
184
                  temp = $time - RisingEdge_time;
185
               end
186
               else
187
               begin
188
                  temp = $time - FallingEdge_time;
189
 
190
               end
191
         end
192
 
193
         else         // Asynchronous mode
194
         begin
195
 
196
            temp = $time - AddValid_time;
197
 
198
            temp = $time - LatchEnableLow_time;
199
 
200
            temp = $time - ChipEnableLow_time;
201
 
202
            if (reading)
203
            begin
204
               temp = $time - OutputEnableLow_time;
205
 
206
               temp = $time - WriteEnableHigh_time;
207
            end
208
 
209
            DataValid_time = $time;
210
            dataValid = `TRUE;
211
            dataXX = `FALSE;
212
         end
213
      end
214
 
215
      else
216
      begin
217
         if (isDataXX(DQ))                 // Data XXXX
218
         begin
219
            if (dataValid)
220
            begin
221
               temp = $time - AddNotValid_time;
222
 
223
               temp = $time - ChipEnableHigh_time;
224
               checkTiming("tEHQX", TimingData_man.tEHQX, temp, "min");
225
 
226
               temp = $time - OutputEnableHigh_time;
227
 
228
            end
229
 
230
            else
231
            begin
232
 
233
               temp = $time - ChipEnableLow_time;
234
               checkTiming("tELQX", TimingData_man.tELQX, temp, "min");
235
 
236
               if (reading)
237
               begin
238
                  temp = $time - OutputEnableLow_time;
239
                  checkTiming("tGLQX", TimingData_man.tGLQX, temp, "min");
240
               end
241
            end
242
 
243
 
244
            DataXX_time = $time;
245
            dataValid = `FALSE;
246
            dataXX = `TRUE;
247
 
248
         end
249
 
250
         else
251
            if (isDataZZ(DQ))
252
            begin
253
               if (dataXX)
254
               begin
255
                  temp = $time - ChipEnableHigh_time;
256
                  checkTiming("tEHQZ", TimingData_man.tEHQZ, temp, "max");
257
                  temp = $time - OutputEnableHigh_time;
258
                  checkTiming("tGHQZ", TimingData_man.tGHQZ, temp, "max");
259
               end
260
 
261
               if (dataValid)
262
               begin
263
                  temp = $time - WriteEnableHigh_time;
264
                  checkTiming("tWHDX", TimingData_man.tWHDX, temp, "min");
265
 
266
               end
267
 
268
               dataValid = `FALSE;
269
               dataXX  = `FALSE;
270
            end
271
      end
272
   end
273
end
274
 
275
// ******************
276
//
277
// Change Chip Enable
278
//
279
// ******************
280
 
281
always @(posedge E_N) begin : ChipHighCheck    // Chip Enable High
282
 
283
   if (`TimingChecks == "off")
284
      disable ChipHighCheck;
285
 
286
   if ($time > `Reset_time)
287
   begin
288
 
289
      temp = $time - WriteEnableHigh_time;
290
      checkTiming("tWHEH", TimingData_man.tWHEH, temp, "min");
291
 
292
      ChipEnableHigh_time = $time;
293
   end
294
end
295
 
296
always @(negedge E_N) begin : ChipLowCheck    // Chip Enable Low
297
 
298
   if (`TimingChecks == "off")
299
      disable ChipLowCheck;
300
 
301
   if ($time > `Reset_time)
302
   begin
303
 
304
      ChipEnableLow_time = $time;
305
   end
306
 
307
end
308
 
309
always @(posedge L_N) begin : LatchLowCheck    // Latch Enable High
310
 
311
   if (`TimingChecks == "off")
312
      disable LatchLowCheck;
313
 
314
   if ($time > `Reset_time)
315
   begin
316
 
317
      temp = $time - AddValid_time;
318
      checkTiming("tAVLH", TimingData_man.tAVLH, temp, "min");
319
 
320
      temp = $time - LatchEnableLow_time;
321
      checkTiming("tLLLH", TimingData_man.tLLLH, temp, "min");
322
 
323
      temp = $time - ChipEnableLow_time;
324
      checkTiming("tELLH", TimingData_man.tELLH, temp, "min");
325
 
326
      LatchEnableHigh_time = $time;
327
   end
328
end
329
 
330
always @(negedge L_N)  begin : LatchHighCheck  // Latch Enable Low
331
 
332
   if (`TimingChecks == "off")
333
      disable LatchHighCheck;
334
 
335
   if ($time > `Reset_time)
336
   begin
337
 
338
      temp = $time - WriteEnableHigh_time;
339
      checkTiming("tWHLL", TimingData_man.tWHLL, temp, "min");
340
 
341
      temp = $time - RisingEdge_time;
342
      checkTiming("tKHLL", TimingData_man.tKHLL, temp, "min");
343
 
344
      LatchEnableLow_time = $time;
345
   end
346
 
347
end
348
 
349
always  @(posedge G_N) begin : OutputHighCheck    // Output Enable High
350
 
351
   if (`TimingChecks == "off")
352
      disable OutputHighCheck;
353
 
354
   if ($time > `Reset_time)
355
   begin
356
 
357
      OutputEnableHigh_time = $time;
358
      reading = `FALSE;
359
   end
360
 
361
end
362
 
363
always @(negedge G_N) begin : OutputLowCheck    // Output Enable Low
364
 
365
   if (`TimingChecks == "off")
366
      disable OutputLowCheck;
367
 
368
   if ($time > `Reset_time)
369
   begin
370
 
371
 
372
      temp = $time - WriteEnableHigh_time;
373
      checkTiming("tWHGL", TimingData_man.tWHGL, temp, "min");
374
 
375
 
376
      OutputEnableLow_time = $time;
377
      reading = `TRUE;
378
   end
379
 
380
end
381
 
382
always @(posedge W_N) begin : WriteHighCheck    // Write Enable High
383
 
384
   if (`TimingChecks == "off")
385
      disable WriteHighCheck;
386
 
387
   if ($time > `Reset_time)
388
   begin
389
 
390
 
391
      temp = $time - AddValid_time;
392
      checkTiming("tAVWH", TimingData_man.tAVWH, temp, "min");
393
 
394
      if (writing)
395
      begin
396
         temp = $time - WriteEnableLow_time;
397
         checkTiming("tWLWH", TimingData_man.tWLWH, temp, "min");
398
      end
399
 
400
      temp = $time - DataValid_time;
401
      checkTiming("tDVWH", TimingData_man.tDVWH, temp, "min");
402
 
403
      temp = $time - WriteProtectHigh_time;
404
      checkTiming("tWPHWH", TimingData_man.tWPHWH, temp, "min");
405
 
406
      temp = $time - VPPSupplyHigh_time;
407
      checkTiming("tVPHWH", TimingData_man.tVPHWH, temp, "min");
408
 
409
      WriteEnableHigh_time = $time;
410
      writing = `FALSE;
411
   end
412
end
413
 
414
always @(negedge W_N) begin : WriteLowCheck    // Write Enable Low
415
 
416
   if (`TimingChecks == "off")
417
      disable WriteLowCheck;
418
 
419
   if ($time > `Reset_time)
420
   begin
421
 
422
      temp = $time - ChipEnableLow_time;
423
      checkTiming("tELWL", TimingData_man.tELWL, temp, "min");
424
 
425
      temp = $time - WriteEnableHigh_time;
426
      checkTiming("tWHWL", TimingData_man.tWHWL, temp, "min");
427
 
428
      WriteEnableLow_time = $time;
429
      writing = `TRUE;
430
   end
431
end
432
 
433
always  @(posedge WP_N) begin : WPHighCheck            // Write Protect High
434
 
435
   if (`TimingChecks == "off")
436
      disable WPHighCheck;
437
 
438
   if ($time > `Reset_time)
439
   begin
440
 
441
      WriteProtectHigh_time = $time;
442
   end
443
end
444
 
445
always  @(negedge WP_N) begin : WPLowCheck               // Write Protect Low
446
 
447
   if (`TimingChecks == "off")
448
      disable WPLowCheck;
449
 
450
   if ($time > `Reset_time)
451
   begin
452
 
453
      temp = $time - DataValid_time;
454
      checkTiming("tQVWPL", TimingData_man.tQVWPL, temp, "min");
455
 
456
      WriteProtectLow_time = $time;
457
   end
458
end
459
 
460
always @(posedge VPP) begin : VPPHighCheck            // Write Protect High
461
 
462
   if (`TimingChecks == "off")
463
      disable VPPHighCheck;
464
 
465
   if ($time > `Reset_time)
466
   begin
467
 
468
      VPPSupplyHigh_time = $time;
469
   end
470
end
471
 
472
always @(negedge VPP) begin : VPPLowCheck               // Write Protect Low
473
 
474
   if (`TimingChecks == "off")
475
      disable VPPLowCheck;
476
 
477
   if ($time > `Reset_time)
478
   begin
479
 
480
      temp = $time - DataValid_time;
481
      checkTiming("tQVVPL", TimingData_man.tQVVPL, temp, "min");
482
 
483
      VPPSupplyLow_time = $time;
484
 
485
   end
486
end
487
 
488
always @(posedge CK) begin : RisingCKCheck
489
 
490
   if (`TimingChecks == "off")
491
      disable RisingCKCheck;
492
 
493
   if ($time > `Reset_time)
494
   begin
495
      temp = $time - LatchEnableLow_time;
496
      checkTiming("tLLKH", TimingData_man.tLLKH, temp, "min");
497
 
498
 
499
      RisingEdge_time = $time;
500
   end
501
end
502
 
503
always @(negedge CK) begin : FallingCKCheck
504
 
505
   if (`TimingChecks == "off")
506
      disable FallingCKCheck;
507
 
508
   if ($time > `Reset_time)
509
   begin
510
      temp = $time - LatchEnableLow_time;
511
      checkTiming("tLLKL", TimingData_man.tLLKL, temp, "min");
512
 
513
      FallingEdge_time = $time;
514
 
515
   end
516
end
517
 
518
 
519
 
520
// **********************************************
521
//
522
// FUNCTION isAddValid :
523
//      return true if the input address is valid
524
//
525
// **********************************************
526
 
527
function isAddValid;
528
 
529
   input [`ADDRBUS_dim - 1 : 0] Add;
530
 
531
   reg [`ADDRBUS_dim - 1 : 0]    Add;
532
 
533
   reg                          valid;
534
   integer                      count;
535
 
536
   begin
537
 
538
      valid = `TRUE;
539
      begin : cycle
540
         for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
541
         begin
542
            if ((Add[count] !== 1'b0) && (Add[count] !== 1'b1))
543
            begin
544
               valid = `FALSE;
545
               disable cycle;
546
            end
547
         end
548
      end
549
 
550
      isAddValid = valid;
551
   end
552
endfunction
553
 
554
 
555
// *********************************************
556
//
557
// FUNCTION isAddXX :
558
//      return true if the input address is XXXX
559
//
560
// *********************************************
561
 
562
function isAddXX;
563
 
564
   input [`ADDRBUS_dim - 1 : 0] Add;
565
 
566
   reg [`ADDRBUS_dim - 1 : 0]    Add;
567
 
568
   reg                          allxx;
569
   integer                      count;
570
 
571
   begin
572
 
573
      allxx = `TRUE;
574
      begin : cycle
575
         for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
576
         begin
577
            if (Add[count] !== 1'bx)
578
            begin
579
               allxx = `FALSE;
580
               disable cycle;
581
            end
582
         end
583
      end
584
 
585
      isAddXX = allxx;
586
   end
587
endfunction
588
 
589
// *********************************************
590
//
591
// FUNCTION isAddZZ :
592
//      return true if the input address is ZZZZ
593
//
594
// *********************************************
595
 
596
function isAddZZ;
597
 
598
   input [`ADDRBUS_dim - 1 : 0] Add;
599
 
600
   reg [`ADDRBUS_dim - 1 : 0]    Add;
601
 
602
   reg                          allzz;
603
   integer                      count;
604
 
605
   begin
606
 
607
      allzz = `TRUE;
608
      begin : cycle
609
         for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
610
         begin
611
            if (Add[count] !== 1'bz)
612
            begin
613
               allzz = `FALSE;
614
               disable cycle;
615
            end
616
         end
617
      end
618
 
619
      isAddZZ = allzz;
620
   end
621
endfunction
622
 
623
// **********************************************
624
//
625
// FUNCTION isDataValid :
626
//      return true if the data is valid
627
//
628
// **********************************************
629
 
630
function isDataValid;
631
 
632
   input [`DATABUS_dim - 1 : 0] Data;
633
 
634
   reg [`DATABUS_dim - 1 : 0]    Data;
635
 
636
   reg                          valid;
637
   integer                      count;
638
 
639
   begin
640
 
641
      valid = `TRUE;
642
      begin : cycle
643
         for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
644
         begin
645
            if ((Data[count] !== 1'b0) && (Data[count] !== 1'b1))
646
            begin
647
               valid = `FALSE;
648
               disable cycle;
649
            end
650
         end
651
      end
652
 
653
      isDataValid = valid;
654
   end
655
endfunction
656
 
657
// ***************************************
658
//
659
// FUNCTION isDataXX :
660
//      return true if the data is unknown
661
//
662
// ***************************************
663
 
664
function isDataXX;
665
 
666
   input [`DATABUS_dim - 1 : 0] Data;
667
 
668
   reg [`DATABUS_dim - 1 : 0]    Data;
669
 
670
   reg                          allxx;
671
   integer                      count;
672
 
673
   begin
674
 
675
      allxx = `TRUE;
676
      begin : cycle
677
         for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
678
         begin
679
            if (Data[count] !== 1'bx)
680
            begin
681
               allxx = `FALSE;
682
               disable cycle;
683
            end
684
         end
685
      end
686
 
687
      isDataXX = allxx;
688
   end
689
endfunction
690
 
691
// ************************************
692
//
693
// FUNCTION isDataZZ :
694
//      return true if the data is Hi-Z
695
//
696
// ************************************
697
 
698
function isDataZZ;
699
 
700
   input [`DATABUS_dim - 1 : 0] Data;
701
 
702
   reg [`DATABUS_dim - 1 : 0]    Data;
703
 
704
   reg                          allzz;
705
   integer                      count;
706
 
707
   begin
708
 
709
      allzz = `TRUE;
710
      begin : cycle
711
         for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
712
         begin
713
            if (Data[count] !== 1'bz)
714
            begin
715
               allzz = `FALSE;
716
               disable cycle;
717
            end
718
         end
719
      end
720
 
721
      isDataZZ = allzz;
722
   end
723
endfunction
724
 
725
// *****************************
726
//
727
// Task Check Timing
728
//      check timing constraints
729
//
730
// *****************************
731
 
732
task checkTiming;
733
   input [8*6:1] tstr;
734
   input [31:0]  tOK, tcheck;
735
   input [8*3:1] check_str;
736
 
737
   begin
738
      if ((check_str == "min") && (tcheck < tOK)) begin
739
         $display ("[%t]  !ERROR: %0s timing constraint violation!! ", $time, tstr);
740
      end
741
 
742
      else
743
         if ((check_str == "max") && (tcheck > tOK))
744
            $display ("[%t]  !ERROR: %0s timing constraint violation!! ", $time, tstr);
745
   end
746
endtask
747
 
748
 
749
endmodule
750
 
751
 
752
// Protect Manager
753
// implements the architecture of the memory blocks
754
 
755
module BlockLockModule(address, WP_N, RP_N, Info);
756
   input [`ADDRBUS_range] address;
757
   input                  WP_N, RP_N;
758
   input                  Info;
759
 
760
   reg                    LockArray [`BLOCK_dim - 1 : 0];
761
   reg                    LockDownArray [`BLOCK_dim - 1 : 0];
762
 
763
   reg [`BYTE_range]      Status;
764
   integer                count;
765
initial begin              // constructor sequence         
766
 
767
   for (count = 0; count <= `BLOCK_dim - 1; count = count + 1)             // all blocks are locked at power-up
768
   begin
769
      LockDownArray[count] = `UNLOCKDOWN;
770
      if (`BLOCKPROTECT == "on") LockArray[count] = `LOCK;
771
      else LockArray[count] = `UNLOCK;
772
   end
773
end
774
 
775
always @(negedge RP_N) begin
776
   initLockArray;
777
end
778
 
779
task initLockArray;
780
   begin
781
 
782
      for (count = 0; count <= `BLOCK_dim - 1; count = count + 1)             // all blocks are locked at power-up
783
      begin
784
         LockDownArray[count] = `UNLOCKDOWN;
785
         LockArray[count] = `LOCK;
786
      end
787
   end
788
endtask
789
 
790
 
791
 
792
// ********************************************
793
//
794
// FUNCTION isLocked : return the status of the 
795
//                     specified block 
796
//
797
// ********************************************
798
 
799
function IsLocked;                     // boolean function primitive   
800
 
801
   input [`ADDRBUS_range] address;
802
 
803
   integer                n_block;
804
 
805
   begin
806
 
807
      n_block  = BankLib_man.getBlock(address);
808
      IsLocked = (LockArray[n_block] == `LOCK) ? `TRUE : `FALSE;
809
 
810
   end
811
endfunction
812
 
813
// ********************************************
814
//
815
// FUNCTION isLocked : return the status of the 
816
//                     specified block 
817
//
818
// ********************************************
819
 
820
function IsUnLocked;                     // boolean function primitive   
821
 
822
   input [`ADDRBUS_range] address;
823
   integer                n_block;
824
 
825
   begin
826
 
827
      n_block  = BankLib_man.getBlock(address);
828
      IsUnLocked = (LockArray[n_block] == `UNLOCK) ? `TRUE : `FALSE;
829
 
830
   end
831
endfunction
832
 
833
 
834
function getLockBit;                     // boolean function primitive   
835
 
836
   input [`ADDRBUS_range] address;
837
   integer                n_block;
838
 
839
   begin
840
 
841
      n_block  = BankLib_man.getBlock(address);
842
      getLockBit = LockArray[n_block];
843
 
844
   end
845
endfunction
846
 
847
function getLockDownBit;                     // boolean function primitive   
848
 
849
   input [`ADDRBUS_range] address;
850
   integer                n_block;
851
 
852
   begin
853
 
854
      n_block  = BankLib_man.getBlock(address);
855
      getLockDownBit = LockDownArray[n_block];
856
 
857
   end
858
endfunction
859
 
860
 
861
// ********************************
862
//
863
// Task UnLock :
864
//    implements Block UnLock Command
865
//
866
// ********************************
867
 
868
task UnLock;
869
 
870
   output [`BYTE_range] Status;
871
   reg [`BYTE_range]    Status;
872
 
873
   integer              n_block;
874
 
875
   begin
876
 
877
      n_block = BankLib_man.getBlock(address);
878
      Status = `NoError_msg;
879
      if (LockDownArray[n_block]==`LOCKDOWN && WP_N==`LOW) Status = `NoUnLock_msg;
880
      else  LockArray[n_block] = `UNLOCK;
881
   end
882
endtask
883
 
884
// ********************************
885
//
886
// Task Lock :
887
//    implements Block Lock Command
888
//
889
// ********************************
890
 
891
task Lock;
892
 
893
   output [`BYTE_range] Status;
894
   reg [`BYTE_range]    Status;
895
 
896
   integer              n_block;
897
 
898
   begin
899
 
900
      n_block = BankLib_man.getBlock(address);
901
      Status = `NoError_msg;
902
      LockArray[n_block] = `LOCK;
903
   end
904
endtask
905
 
906
// *****************************************
907
//
908
// Task LockDown :
909
//    implements the Block Lock-Down Command
910
//
911
// *****************************************
912
 
913
task LockDown;
914
 
915
   output [`BYTE_range] Status;
916
   reg [`BYTE_range]    Status;
917
 
918
   integer              n_block;
919
 
920
   begin
921
 
922
      n_block = BankLib_man.getBlock(address);
923
      Status = `NoError_msg;
924
      LockDownArray[n_block] = `LOCKDOWN;
925
 
926
   end
927
endtask
928
 
929
 
930
endmodule
931
 
932
 
933
// *************************
934
//
935
// CFI Query Module
936
// Implements the CFI memory
937
//
938
// *************************
939
 
940
module CFIqueryModule();   //, isCFI);
941
 
942
//input isCFI;
943
 
944
   reg [`BYTE_range] CFIarray [0:`CFI_dim];
945
   reg               error;
946
   reg [8*20:1]      CFI_file;
947
   integer           i;
948
 
949
initial begin
950
   if (`organization == "top") CFI_file = "CFImemory_top.vmf";
951
   else CFI_file= "CFImemory_bottom.vmf";
952
 
953
   for (i=0; i <= `CFI_dim; i = i + 1) CFIarray[i] = {8{`HIGH}};   // CFI Memory Init
954
   $readmemb(CFI_file,CFIarray);
955
end
956
 
957
always @(posedge error)  begin
958
   Kernel.SetWarning(`RCFI_cmd,16'h00,`CFIAddrRange_msg);
959
   error = `FALSE;
960
end
961
 
962
function [`WORD_range] Get;
963
 
964
   input [`ADDRBUS_range] address;
965
 
966
   begin
967
      if (address[`BYTE_range] >= 9'h10 && address[`BYTE_range] <= `CFI_dim )  //verificare se tener conto che il primo indirizzo accessibile e' 10h
968
      begin
969
         if (address[`BYTE_range] >= 9'h39 && address[`BYTE_range] <= 9'h109) begin
970
            Get = 8'hXX;
971
            error = `TRUE;
972
         end else begin
973
 
974
            Get[`LOW_range] = CFIarray[address[`BYTE_range]];
975
            Get[`HIGH_range] = 8'h00;
976
         end
977
 
978
      end else
979
      begin
980
         Get = 8'hXX;
981
         error = `TRUE;
982
      end
983
   end
984
endfunction
985
 
986
endmodule
987
 
988
// ********************************
989
//
990
// Data Error Module
991
// 
992
//      search for errors in data.h
993
//
994
// ********************************
995
 
996
module DataErrorModule;
997
 
998
   reg SevError;
999
 
1000
initial begin
1001
 
1002
   SevError = `FALSE;
1003
 
1004
   if ((`organization != "top") && (`organization != "bottom"))
1005
   begin
1006
      SevError = `TRUE;
1007
      $display("!Error: BLOCK ORGANIZATION INVALID: it must be top or bottom!!!");
1008
   end
1009
 
1010
   if ((`BLOCKPROTECT != "on") && (`BLOCKPROTECT != "off"))
1011
   begin
1012
      SevError = `TRUE;
1013
      $display("!Error: BLOCK PROTECT INVALID: it must be on or off!!!");
1014
   end
1015
 
1016
   if ((`TimingChecks != "on") && (`TimingChecks != "off"))
1017
   begin
1018
      SevError = `TRUE;
1019
      $display("!Error: TIMING CHECKS INVALID: it must be on or off!!!");
1020
   end
1021
 
1022
 
1023
   if ((`t_access != 100) && (`t_access != 110))
1024
   begin
1025
      SevError = `TRUE;
1026
      $display("!Error: Access time INVALID: it must be 100 ns or 110 ns!!!");
1027
   end
1028
 
1029
 
1030
   if (SevError) $finish;
1031
end
1032
 
1033
endmodule
1034
 
1035
// ******************************************
1036
//
1037
// Configuration Register module :
1038
//
1039
//      implements the configuration register
1040
//
1041
// ******************************************
1042
 
1043
module ConfigRegModule(address,Info);
1044
   input [`ADDRBUS_range] address;
1045
   input                  Info;
1046
 
1047
   reg [`ConfigurationReg_dim - 1 : 0] CR_reg;
1048
   reg [`BYTE_range]                   Status;
1049
 
1050
// **********************
1051
//
1052
// Setting default values
1053
//
1054
// **********************
1055
 
1056
`define ReadMode_bit         15
1057
`define ClockLatency_MSBbit  14
1058
`define ClockLatency_LSBbit  11
1059
`define WaitPolarity_bit     10
1060
`define WaitConfig_bit       8
1061
`define BurstType_bit        7
1062
`define ValidClockEdge_bit   6
1063
`define WrapBurst_bit        3
1064
`define BurstLength_MSBbit   2
1065
`define BurstLength_LSBbit   0
1066
 
1067
// Interpreter  Config Reg\\
1068
 
1069
   wire                                isASynchronous      = CR_reg[`ReadMode_bit] ? `TRUE : `FALSE;
1070
   wire                                isSynchronous       = CR_reg[`ReadMode_bit] ? `FALSE : `TRUE;
1071
   wire [3:0]                           Xlatency      = (CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]<2 &&
1072
                                                        CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]>15) ? 0 :
1073
                                       CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit];
1074
   wire                                isWaitPolActiveHigh = CR_reg[`WaitPolarity_bit] ? `TRUE : `FALSE;
1075
   wire                                isWaitBeforeActive    = CR_reg[`WaitConfig_bit] ? `TRUE : `FALSE;
1076
   wire                                isRisingClockEdge   = CR_reg[`ValidClockEdge_bit] ? `TRUE : `FALSE;
1077
   wire                                isWrapBurst         = CR_reg[`WrapBurst_bit] ? `FALSE : `TRUE;
1078
   wire                                isNoWrapBurst       = CR_reg[`WrapBurst_bit] ? `TRUE : `FALSE;
1079
 
1080
   wire [4:0]                           BurstLength   = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 4 :
1081
                                       CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 8 :
1082
                                       CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 16:
1083
                                       0; // continous Burst
1084
 
1085
 
1086
   wire [2:0]                           BurstLength_bit = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 2 :
1087
                                       CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 3 :
1088
                                       CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 4:
1089
                                       0; // continous Burst
1090
 
1091
initial begin
1092
   Status = `NoError_msg;
1093
   CR_reg = `ConfigReg_default;
1094
end
1095
 
1096
always @(isSynchronous) begin
1097
   if (Info)
1098
      if (isSynchronous)
1099
         $write("[%t]  Synchronous Read Mode\n",$time);
1100
      else
1101
         $write("[%t]  ASynchronous Read Mode\n",$time);
1102
end
1103
// **********************
1104
//
1105
// ReSet to default value
1106
//
1107
// **********************
1108
always @(Kernel.ResetEvent) begin
1109
   Status = `NoError_msg;
1110
   CR_reg = `ConfigReg_default;
1111
end
1112
 
1113
// **************************************
1114
//
1115
// FUNCTION getConfigReg :
1116
//
1117
//      return the Configuration Register
1118
//
1119
// **************************************
1120
 
1121
function [`ConfigurationReg_dim - 1 : 0] getConfigReg;
1122
   input required;
1123
   begin
1124
      getConfigReg = CR_reg;
1125
   end
1126
endfunction
1127
 
1128
// *************************************
1129
//
1130
// FUNCTION putConfigReg :
1131
//
1132
//      write the Configuration Register
1133
//
1134
// *************************************
1135
 
1136
task putConfigReg;
1137
   output [`BYTE_range] outStatus;
1138
 
1139
   reg [`BYTE_range]    outStatus;
1140
 
1141
   integer              count;
1142
 
1143
   begin
1144
 
1145
      CR_reg = address[`ConfigurationReg_dim - 1 : 0];
1146
 
1147
      outStatus = Status;
1148
 
1149
   end
1150
endtask
1151
 
1152
 
1153
endmodule
1154
 
1155
// ***************************
1156
//
1157
// Electronic Signature Module
1158
//
1159
// ***************************
1160
 
1161
module SignatureModule;
1162
 
1163
   reg error;
1164
   integer i;
1165
   integer n_block;
1166
 
1167
initial begin
1168
end
1169
 
1170
always @(posedge error)  begin
1171
   Kernel.SetWarning(`RSIG_cmd,16'h00,`SignAddrRange_msg);
1172
   error = `FALSE;
1173
end
1174
 
1175
function [`WORD_range] Get;
1176
 
1177
   input [`ADDRBUS_range] address;
1178
 
1179
   begin
1180
      if (address[`SignAddress_range] == 9'h00)
1181
      begin
1182
         Get[`LOW_range] = `ManufacturerCode;
1183
         Get[`HIGH_range] = 8'h00;
1184
      end
1185
      else if (address[`SignAddress_range] == 9'h01)
1186
      begin
1187
         if (`organization == "top") Get[`LOW_range] = `TopDeviceCode;
1188
         else  Get[`LOW_range] = `BottomDeviceCode;
1189
 
1190
         Get[`HIGH_range] = 8'h89;
1191
      end
1192
      else if (address[`SignAddress_range] == 9'h02)
1193
      begin
1194
         Get[`LOW_range] = { 6'b0, BlockLock_man.getLockDownBit(address), BlockLock_man.getLockBit(address) };
1195
         Get[`HIGH_range] =  8'h00;
1196
      end
1197
      else if (address[`SignAddress_range] == 9'h05)                       // Configuration Register
1198
         Get = ConfigReg_man.getConfigReg(0);
1199
      else if ((address[`SignAddress_range] >= `REGSTART_addr) && (address[`SignAddress_range] <= `REGEND_addr))
1200
      begin
1201
         Get = ProtectReg_man.RegisterMemory[address[`SignAddress_range] - `REGSTART_addr ];
1202
 
1203
      end
1204
      else begin
1205
         Get = 8'hXX;
1206
         error = `TRUE;
1207
      end
1208
   end
1209
endfunction
1210
 
1211
endmodule
1212
 
1213
// ********************
1214
//
1215
// CUI decoder module :
1216
//      decode commands
1217
//
1218
// ********************
1219
 
1220
module CUIdecoder1(DataBus,Name,Cmd,CmdAllowed,Info);
1221
   input [`BYTE_range] DataBus, Cmd;
1222
   input [8*35:1]      Name;
1223
   input               Info;
1224
   input               CmdAllowed;
1225
always @Kernel.CUIcommandEvent begin
1226
   #1;
1227
   if (DataBus == Cmd  && CmdAllowed) begin  // is a First Command ?
1228
      #1 -> Kernel.VerifyEvent;
1229
      Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
1230
      if (Info) $display("[%t]  Command Issued: %0s",$time,Name);
1231
   end
1232
   else begin
1233
      if (`FALSE) $display("[%t]  The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
1234
      @(Kernel.CompleteEvent or Kernel.ErrorEvent)
1235
         if (`FALSE) $display("[%t]  The %0s instruction decode unit is listening for next command.",$time,Name);
1236
   end
1237
end
1238
endmodule
1239
 
1240
 
1241
// ********************
1242
//
1243
// CUIdecoder manager :
1244
//      decode commands
1245
//
1246
// ********************
1247
 
1248
module CUIdecoder2(DataBus,Name,Cmd1,Cmd2,CmdAllowed,Info);
1249
   input [`BYTE_range] DataBus, Cmd1, Cmd2;
1250
   input [8*27:1]      Name;
1251
   input               Info;
1252
   input               CmdAllowed;
1253
 
1254
always @Kernel.CUIcommandEvent begin
1255
   if (DataBus == Cmd1 && CmdAllowed) begin
1256
      #1 -> Kernel.VerifyEvent;
1257
 
1258
      @Kernel.CUIcommandEvent
1259
 
1260
         if (DataBus == Cmd2 && CmdAllowed)  begin
1261
            #1  -> Kernel.VerifyEvent;
1262
 
1263
            Kernel.CommandDecode2[{Cmd1,Cmd2}] = !Kernel.CommandDecode2[{Cmd1,Cmd2}];
1264
            if (Info) $display("[%t]  Command Issued: %0s",$time,Name);
1265
         end
1266
   end
1267
   else begin
1268
      if (`FALSE) $display("%t  The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
1269
      @(Kernel.CompleteEvent or Kernel.ErrorEvent)
1270
         if (`FALSE) $display("%t  The %0s instruction decode unit is listening for next command",$time,Name);
1271
   end
1272
end
1273
 
1274
endmodule
1275
 
1276
 
1277
// ****************************
1278
//
1279
// CUI Decoder Manager :
1280
//      decode the cUI commands
1281
//
1282
// ****************************
1283
 
1284
module CUIdecoder_Busy1(DataBus,Name,Cmd,CmdAllowed,Info);
1285
   input [`BYTE_range] DataBus, Cmd;
1286
   input [8*8:1]       Name;
1287
   input               Info;
1288
   input               CmdAllowed;
1289
 
1290
always @Kernel.CUIcommandEvent begin
1291
   if ((DataBus == Cmd) && CmdAllowed) begin
1292
      -> Kernel.VerifyEvent;
1293
      Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
1294
      if (Info) $display("[%t]  Command Issued: %0s",$time,Name);
1295
   end
1296
 
1297
 
1298
 
1299
end
1300
 
1301
endmodule
1302
 
1303
 
1304
// Erase Manager
1305
// manage the erase functionality
1306
 
1307
module EraseModule(address, data, progVoltOK, progHighVoltOK,Info);
1308
   input [`ADDRBUS_range] address;
1309
   input [`WORD_range]    data;
1310
 
1311
   input                  progVoltOK, progHighVoltOK;
1312
 
1313
   input                  Info;
1314
   event                  ErrorCheckEvent, CompleteEvent;
1315
 
1316
   reg [`BYTE_range]      Status;
1317
   reg [`ADDRBUS_range]   hold_address;
1318
   reg [`BLOCKADDR_range] hold_block;
1319
 
1320
   reg                    Busy, Suspended, first_time;
1321
   integer                i;
1322
   time                   startTime, delayTime,Erase_time;
1323
 
1324
initial begin                   // constructor sequence             
1325
   Busy       = `FALSE;
1326
   Suspended  = `FALSE;
1327
   Erase_time = `MainBlockErase_time;
1328
   delayTime  =  Erase_time;
1329
 
1330
end
1331
 
1332
 
1333
function IsBusy;                // boolean function primitive       
1334
   input obbl;                     // all functions require a parameter
1335
   IsBusy = Busy;                // return Boolean value             
1336
endfunction
1337
 
1338
function IsSuspended;           // boolean function primitive       
1339
   input obbl;                     // all functions require a parameter
1340
   IsSuspended = Suspended;      // return Boolean value             
1341
endfunction
1342
 
1343
function IsAddrSuspended;       // boolean function primitive       
1344
   input [`ADDRBUS_range] addr;
1345
   IsAddrSuspended = (Suspended && (addr == hold_address));
1346
endfunction
1347
 
1348
function IsBlockSuspended;       // boolean function primitive       
1349
   input [`ADDRBUS_range] addr;
1350
   IsBlockSuspended = (Suspended && ((BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/))));
1351
endfunction
1352
 
1353
// *********************
1354
//
1355
// Task checkConfirm :
1356
//    check confirm code
1357
//
1358
// *********************
1359
 
1360
task checkConfirm;
1361
 
1362
   output  [`BYTE_range] outStatus;
1363
 
1364
   reg [`BYTE_range]     outStatus;
1365
 
1366
   begin
1367
 
1368
      if (data == `BLKEEconfirm_cmd) outStatus = `NoError_msg;
1369
      else outStatus = `WrongEraseConfirm_msg;
1370
 
1371
   end
1372
endtask
1373
 
1374
 
1375
task Suspend;
1376
   output [`BYTE_range] outStatus;
1377
   reg [`BYTE_range]    outStatus;
1378
   begin
1379
      delayTime = delayTime - ($time - startTime);
1380
      #`EraseSuspendLatency_time
1381
         outStatus = `NoError_msg;
1382
      Status = `Suspend_msg;
1383
      Suspended = `TRUE;
1384
      -> CompleteEvent;
1385
   end
1386
endtask
1387
 
1388
task Resume;
1389
   output [`BYTE_range] Status;
1390
   begin
1391
      Suspended = `FALSE;
1392
      BlockErase(Status);
1393
   end
1394
endtask
1395
 
1396
task BlockErase;
1397
   output [`BYTE_range] outStatus;
1398
   reg [`BYTE_range]    outStatus;
1399
   begin
1400
 
1401
 
1402
      if (progHighVoltOK)
1403
         if (BankLib_man.isMainBlock(address)) Erase_time = `FastMainBlockErase_time;
1404
         else  Erase_time = `FastParameterBlockErase_time;
1405
      else
1406
         if (BankLib_man.isMainBlock(address)) Erase_time   = `MainBlockErase_time;
1407
         else  Erase_time  = `ParameterBlockErase_time;
1408
 
1409
      delayTime                                               = Erase_time;
1410
      hold_address                                            = address;
1411
      hold_block                                              = BankLib_man.getBlock(address);
1412
 
1413
 
1414
 
1415
      fork
1416
         begin : Operation
1417
            Busy = `TRUE;
1418
            startTime = $time;
1419
            -> ErrorCheckEvent;
1420
            #delayTime Memory_man.EraseBlock(hold_block,Status);
1421
            delayTime = Erase_time;
1422
            -> CompleteEvent;
1423
         end
1424
         @CompleteEvent
1425
            disable Operation;
1426
      join
1427
      outStatus = Status;
1428
      Busy = `FALSE;
1429
   end
1430
endtask
1431
 
1432
always @(ErrorCheckEvent) begin
1433
   Status = `NoError_msg;
1434
   if (BlockLock_man.IsLocked(hold_address))
1435
      Status = `BlockLock_msg;
1436
   else if (Memory_man.IsBlockSuspended(hold_address))
1437
      Status = `SuspCmd_msg;
1438
   else if (!progVoltOK)
1439
      Status = `InvVDD_msg;
1440
 
1441
   if (Status != `NoError_msg)
1442
      ->CompleteEvent;
1443
   else
1444
      fork : ErrorCheck
1445
         @(negedge progVoltOK) Status = `InvVDD_msg;
1446
         @(Status) -> CompleteEvent;
1447
         @(CompleteEvent) disable ErrorCheck;
1448
      join
1449
end
1450
 
1451
endmodule  //end module Erase
1452
 
1453
 
1454
// *********************
1455
//
1456
// Memory Manager :
1457
//      the memory array
1458
// 
1459
// *********************
1460
 
1461
module MemoryModule(Info);
1462
   input Info;
1463
   reg [`WORD_range] memory [0:(`MEMORY_dim) - 1];     // the Memory: word organization
1464
 
1465
initial begin
1466
   LoadMemory;
1467
end
1468
 
1469
task LoadMemory;                                // Initialize and load the memory from a file
1470
   integer i;
1471
   begin
1472
      #0 if (Info) $display("[%t] Inizialize the Memory to default value",$time);
1473
/*
1474
 Don't need to preload this memory for these testbenches now -- Julius
1475
 
1476
      for (i = 0; i < `MEMORY_dim; i = i + 1)  memory[i] = {16{`HIGH}};    // Memory Init
1477
 
1478
      if (`FILENAME_mem !== "") begin
1479
         $readmemb(`FILENAME_mem, memory);
1480
 
1481
         if (Info) $display("[%t] Load Memory from file: %s",$time, `FILENAME_mem);
1482
         else if (Info) $display("[%t] Warning: File: %s not found",$time, `FILENAME_mem);
1483
      end
1484
 */
1485
   end
1486
endtask
1487
 
1488
 
1489
function [`WORD_range] Get;
1490
   input [`ADDRBUS_range] address;
1491
   Get = memory[address];
1492
endfunction
1493
 
1494
 
1495
function IsSuspended;
1496
   input [`ADDRBUS_range] address;
1497
   IsSuspended = Program_man.IsAddrSuspended(address) || Erase_man.IsAddrSuspended(address) || ProgramBuffer_man.IsAddrSuspended(address);
1498
endfunction
1499
 
1500
function IsBlockSuspended;
1501
   input [`ADDRBUS_range] address;
1502
   IsBlockSuspended = Program_man.IsBlockSuspended(address) || Erase_man.IsBlockSuspended(address);
1503
endfunction
1504
 
1505
 
1506
task Program;
1507
   input [`WORD_range] data;
1508
   input [`ADDRBUS_range] address;
1509
   output [`BYTE_range]   Status;
1510
begin
1511
   Status = `NoError_msg;
1512
   memory[address] = memory[address] & data;
1513
   if (memory[address] != data) Status = `PreProg_msg;
1514
end
1515
endtask
1516
 
1517
task EraseBlock;
1518
 
1519
   input [`INTEGER] block;
1520
 
1521
   output [`BYTE_range] ErrFlag;
1522
 
1523
   reg [`ADDRBUS_range] start_address;
1524
   reg [`ADDRBUS_range] end_address;
1525
   reg [`ADDRBUS_range] address;
1526
 
1527
 
1528
   begin
1529
      ErrFlag        = `NoError_msg;
1530
      start_address  = BankLib_man.getBlockAddress(block);
1531
      end_address    = BankLib_man.BlockBoundaryEndAddr[block];
1532
 
1533
      if (start_address > end_address)
1534
      begin
1535
         address = start_address;
1536
         start_address = end_address;
1537
         end_address = address;
1538
      end
1539
 
1540
 
1541
      for (address = start_address; address <= end_address; address = address + 1)
1542
         memory[address] = `WORDNP;
1543
 
1544
   end
1545
endtask
1546
 
1547
task BlockBlankCheck;
1548
 
1549
   input [`INTEGER] block;
1550
 
1551
   output [`BYTE_range] ErrFlag;
1552
 
1553
   reg [`ADDRBUS_range] start_address;
1554
   reg [`ADDRBUS_range] end_address;
1555
   reg [`ADDRBUS_range] address;
1556
 
1557
 
1558
   begin
1559
      ErrFlag = `NoError_msg;
1560
      start_address = BankLib_man.BlockBoundaryStartAddr[block];
1561
      end_address   = BankLib_man.BlockBoundaryEndAddr[block];
1562
 
1563
      if (start_address > end_address)
1564
      begin
1565
         address = start_address;
1566
         start_address = end_address;
1567
         end_address = address;
1568
      end
1569
 
1570
      ErrFlag = `NoError_msg;
1571
      address = start_address;
1572
      while (memory[address] == `WORDNP && address <= end_address )
1573
         address = address + 1;
1574
      if (memory[address] != `WORDNP)
1575
         ErrFlag = `BlankCheckFailed_msg;
1576
 
1577
   end
1578
endtask
1579
 
1580
 
1581
 
1582
endmodule //end MemoryModule 
1583
 
1584
 
1585
// ***************************************
1586
//
1587
// Output Buffer :
1588
//
1589
//      manage the communication between 
1590
//      the memory and the output data bus
1591
//
1592
// ***************************************
1593
 
1594
module OutputBufferModule(DataInput, DataInputBurst, DataOutput, OutputEnable);
1595
   input [`WORD_range] DataInput;
1596
   input [`WORD_range] DataInputBurst;
1597
   output [`WORD_range] DataOutput;
1598
   input                OutputEnable;
1599
   reg [`WORD_range]    DataOutput;
1600
   time                 timeDataV, timeDataX, timeDataZ;
1601
 
1602
initial begin
1603
   timeDataV=0;
1604
   timeDataX=0;
1605
   timeDataZ=0;
1606
   SetZ(0);
1607
end
1608
 
1609
task SetValid;
1610
   input [63:0] delayTime;
1611
   begin
1612
 
1613
      if ((delayTime+$time > timeDataV) || (timeDataV < $time)) begin
1614
         timeDataV = delayTime + $time;
1615
 
1616
 
1617
         disable waitValid;
1618
 
1619
 
1620
         disable goValid;
1621
 
1622
      end
1623
   end
1624
endtask
1625
 
1626
always
1627
   fork
1628
      begin:  goValid
1629
 
1630
         #(timeDataV - $time)
1631
         if (OutputEnable == 1'b0) begin
1632
 
1633
            if (ConfigReg_man.isASynchronous) DataOutput = DataInput;
1634
            else DataOutput = DataInputBurst;
1635
         end
1636
 
1637
      end // goValid
1638
      begin: waitValid
1639
         wait (`FALSE);
1640
      end
1641
   join
1642
 
1643
task SetX;
1644
   input [63:0] delayTime;
1645
   begin
1646
      if ((delayTime+$time < timeDataX) || (timeDataX < $time)) begin
1647
         timeDataX = delayTime + $time;
1648
         disable waitX;
1649
 
1650
 
1651
      end
1652
   end
1653
endtask
1654
 
1655
always fork
1656
   begin : goX
1657
      #(timeDataX - $time) if ((OutputEnable == `LOW) || (timeDataZ > timeDataX))
1658
         DataOutput = 16'hX;
1659
   end // goX
1660
   begin: waitX
1661
      wait (`FALSE);
1662
   end
1663
join
1664
 
1665
task SetZ;
1666
   input [63:0] delayTime;
1667
   begin
1668
      if ((delayTime+$time < timeDataZ) || (timeDataZ < $time)) begin
1669
         timeDataZ = delayTime + $time;
1670
         disable waitZ;
1671
         if (timeDataZ < timeDataV)
1672
            disable goValid;
1673
         if (timeDataZ < timeDataX)
1674
            disable goX;
1675
      end
1676
   end
1677
endtask
1678
 
1679
always begin: waitZ
1680
   #(timeDataZ - $time) DataOutput = 16'hZ;
1681
   wait (`FALSE);
1682
end
1683
 
1684
endmodule
1685
 
1686
 
1687
// *********************************
1688
//
1689
// Program module :
1690
//
1691
//      manage the program operation
1692
//
1693
// *********************************
1694
 
1695
module ProgramModule(address,data, progVoltOK, progHighVoltOK, Info);
1696
   input [`WORD_range] data;
1697
   input [`ADDRBUS_range] address;
1698
   input                  progVoltOK,progHighVoltOK;
1699
   input                  Info;
1700
   event                  ErrorCheckEvent, CompleteEvent;
1701
   reg [`BYTE_range]      Status;
1702
   reg [`WORD_range]      hold_data;
1703
   reg [`ADDRBUS_range]   hold_address;
1704
   reg                    Busy, Suspended;
1705
 
1706
   integer                i;
1707
   time                   startTime, delayTime, WordProgram_time;
1708
 
1709
initial begin                 // constructor sequence
1710
   Busy = `FALSE;
1711
   Suspended = `FALSE;
1712
   WordProgram_time = `WordProgram_time;
1713
   delayTime = WordProgram_time;
1714
end
1715
 
1716
always @(progHighVoltOK) begin
1717
   if (progHighVoltOK) WordProgram_time=`FastWordProgram_time;
1718
   else WordProgram_time=`WordProgram_time;
1719
end
1720
 
1721
function IsBusy;              // boolean function primitive
1722
   input obbl;                   // all functions require a parameter
1723
   IsBusy = Busy;              // return Boolean value
1724
endfunction
1725
 
1726
function IsSuspended;         // boolean function primitive
1727
   input obbl;                   // all functions require a parameter
1728
   IsSuspended = Suspended;    // return Boolean value 
1729
endfunction
1730
 
1731
function IsAddrSuspended;     // boolean function primitive       
1732
   input [`ADDRBUS_range] addr;
1733
   IsAddrSuspended = (Suspended && (addr == hold_address));
1734
endfunction
1735
 
1736
function IsBlockSuspended;    // return true if block is suspended
1737
   input [`ADDRBUS_range] addr; begin
1738
      IsBlockSuspended  = (Suspended && (BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/)));
1739
   end
1740
endfunction
1741
 
1742
 
1743
task Suspend;
1744
   output [`BYTE_range] suspErrFlag;
1745
   reg [`BYTE_range]    suspErrFlag;
1746
   begin
1747
      delayTime = delayTime - ($time - startTime);
1748
      #`ProgramSuspendLatency_time suspErrFlag = `NoError_msg;
1749
      Status = `Suspend_msg;
1750
      Suspended = `TRUE;
1751
      -> CompleteEvent;
1752
   end
1753
endtask
1754
 
1755
task Resume;
1756
   output [`BYTE_range] ErrFlag;
1757
   begin
1758
      Suspended = `FALSE;
1759
      Program(ErrFlag);
1760
end
1761
endtask
1762
 
1763
task Program;
1764
   output [`BYTE_range] outErrFlag;
1765
   reg [`BYTE_range]    outErrFlag;
1766
begin
1767
   if (delayTime == WordProgram_time) begin
1768
      hold_data = data;
1769
      hold_address = address;
1770
   end
1771
   fork
1772
      begin : Operation
1773
         Busy = `TRUE;
1774
         startTime = $time;
1775
         -> ErrorCheckEvent;
1776
         #delayTime Memory_man.Program(hold_data,hold_address,Status);
1777
delayTime = `WordProgram_time;
1778
-> CompleteEvent;
1779
end
1780
      @CompleteEvent disable Operation;
1781
   join
1782
   outErrFlag = Status;
1783
   Busy = `FALSE;
1784
end
1785
endtask
1786
 
1787
always @(ErrorCheckEvent) begin
1788
   Status = `NoError_msg;
1789
   if (BlockLock_man.IsLocked(hold_address))
1790
      Status = `BlockLock_msg;
1791
   else
1792
      if (Memory_man.IsSuspended(hold_address))
1793
         Status = `SuspAcc_msg;
1794
      else if (!progVoltOK)
1795
         Status = `InvVDD_msg;
1796
 
1797
   if (Status != `NoError_msg) ->CompleteEvent;
1798
   else
1799
      fork : ErrorCheck
1800
         @(negedge progVoltOK) Status = `InvVDD_msg;
1801
         @(Status) -> CompleteEvent;
1802
         @(CompleteEvent) disable ErrorCheck;
1803
      join
1804
end
1805
 
1806
endmodule // end PrograModule 
1807
 
1808
 
1809
// *********************************
1810
//
1811
// Buffer Ehnanced Program module :
1812
//
1813
//      program buffer functionality
1814
//
1815
// *********************************
1816
 
1817
module BuffEnhancedFactProgramModule(address, data, progVoltOK, progHighVoltOK, Info);
1818
   input [`ADDRBUS_range] address;
1819
   input [`WORD_range]    data;
1820
   input                  progVoltOK, progHighVoltOK, Info;
1821
 
1822
   event                  ErrorCheckEvent,ErrorCheckEvent_inVerify, CompleteEvent, WatchAddressEvent;
1823
   reg [`BYTE_range]      Status;
1824
   reg [`WORD_range]      hold_data, hold_StartBlock;
1825
   reg [`ADDRBUS_range]   hold_address, startAddress;
1826
   reg [`WORD_range]      bufferData [`BuffEnhProgramBuffer_range];
1827
 
1828
   reg                    Busy;
1829
   time                   Program_time;
1830
   integer                i,Len;
1831
 
1832
initial begin                 // constructor sequence             
1833
   Busy = `FALSE;
1834
   Status = `NoError_msg;
1835
   Program_time = `WordProgram_time;
1836
   EmptyBuffer;
1837
end
1838
 
1839
task EmptyBuffer;
1840
   begin
1841
      for (i = 0; i < `BuffEnhProgramBuffer_dim; i = i + 1)
1842
         bufferData[i] = 16'hFFFF;
1843
      Len=0;
1844
   end
1845
endtask
1846
 
1847
function IsBusy;              // boolean function primitive       
1848
   input obbl;               // all functions require a parameter
1849
   IsBusy = Busy;              // return Boolean value             
1850
endfunction
1851
 
1852
task Setup;
1853
   output [`BYTE_range] outStatus;
1854
   begin
1855
      Status           = `NoError_msg;
1856
      Len              =0;
1857
      startAddress     = address;
1858
      hold_address     = address;
1859
 
1860
      hold_StartBlock  = BankLib_man.getBlock(address);
1861
      -> ErrorCheckEvent;
1862
      #0 outStatus=Status;
1863
      if (Status == `NoError_msg) begin
1864
         if (Info) $display("[%t]  Enhanced Factory Program -> Setup Phase",$time);
1865
         if (Info) $display("[%t]  Enhanced Factory Program: Start address: %h",$time,startAddress);
1866
         #`EnhBuffProgramSetupPhase_time;
1867
         Busy = `TRUE;
1868
      end
1869
   end
1870
endtask
1871
 
1872
task Exit;
1873
   output [`BYTE_range] outStatus;
1874
   begin
1875
      Busy = `FALSE;
1876
      outStatus = Status;
1877
      if (Info) $display("[%t]  Enhanced Factory Program -> Exit Phase",$time);
1878
      if (Len != `BuffEnhProgramBuffer_dim)
1879
         $display("[%t] Warning --- The buffer must be completely filled for programming to occur",$time);
1880
   end
1881
endtask
1882
 
1883
task Load;
1884
   output [`BYTE_range] outStatus;
1885
   begin
1886
      if (BankLib_man.getBlock(address) != hold_StartBlock) Status = `ExitPHASE_BEFP_msg;
1887
      else begin
1888
         bufferData[Len] = data;
1889
         if (Info) $display("[%t]  Enhanced Factory Program -> Load: data[%d]=%h ",$time,Len,bufferData[Len]);
1890
         Len = Len + 1;
1891
         if (Len == `BuffEnhProgramBuffer_dim) Status = `ProgramPHASE_BEFP_msg;
1892
 
1893
      end
1894
      outStatus = Status;
1895
   end
1896
endtask
1897
 
1898
task Program;
1899
   output [`BYTE_range] outStatus;
1900
   reg [`BYTE_range]    outStatus;
1901
begin
1902
   fork
1903
      begin : Operation
1904
         if (Info) $display("[%t]  Enhanced Factory Program {Program Phase}",$time);
1905
         #`EnhBuffProgram_time
1906
 
1907
            if (Info) $display("[%t]  Enhanced Factory Program {End of Program Phase}",$time);
1908
         for (i = startAddress;i < (`BuffEnhProgramBuffer_dim + startAddress); i = i + 1) begin
1909
            Memory_man.Program(bufferData[i - startAddress],i,Status);
1910
end
1911
         -> CompleteEvent;      //end of program
1912
      end
1913
      @CompleteEvent begin
1914
         disable Operation;
1915
      end
1916
   join
1917
   if (Status == `ProgramPHASE_BEFP_msg) begin //prova
1918
      Status = `NoError_msg;
1919
   end
1920
   outStatus = Status;
1921
end
1922
endtask
1923
 
1924
always @(ErrorCheckEvent) begin
1925
   Status = `NoError_msg;
1926
   if (BlockLock_man.IsLocked(hold_address))
1927
      Status = `BlockLock_msg;
1928
   else if (!progVoltOK)
1929
      Status = `InvVDD_msg;
1930
   else if (!progHighVoltOK)
1931
      Status =  `InvVPP_msg;
1932
   if (Status != `NoError_msg)
1933
      ->CompleteEvent;
1934
   else
1935
      fork : ErrorCheck
1936
         @(negedge progVoltOK) Status = `InvVDD_msg;
1937
         @(negedge progHighVoltOK) Status = `InvVPP_msg;
1938
         @(CompleteEvent) disable ErrorCheck;
1939
      join
1940
end
1941
 
1942
 
1943
 
1944
endmodule
1945
 
1946
// ******************************************
1947
//
1948
// Protect Register module :
1949
//
1950
//      operations on the protection register
1951
//
1952
// ******************************************
1953
 
1954
module ProtectRegModule(address, data, voltOK, Info);
1955
   input [`ADDRBUS_range] address;
1956
   input [`DATABUS_range] data;
1957
   input                  voltOK, Info;
1958
   reg [`WORD_range]      RegisterMemory[`REG_dim - 1 :0];
1959
   reg [`BYTE_range]      Status;
1960
   reg                    Busy;
1961
   reg [`ADDRBUS_range]   AddressLatched;
1962
   event                  ErrorCheckEvent, CompleteEvent;
1963
   integer                i;
1964
   reg [`ADDRBUS_range]   hold_addr;
1965
   reg [`DATABUS_range]   hold_data;
1966
 
1967
 
1968
initial begin                         // constructor sequence             
1969
   Busy = `FALSE;
1970
   RegisterMemory[0] = `PRL_default;
1971
   for (i = 1; i < `REG_dim; i = i + 1) begin
1972
      RegisterMemory[i] = `WORDNP;
1973
   end
1974
end
1975
 
1976
 
1977
function IsBusy;              // boolean function primitive       
1978
   input required;               // all functions require a parameter
1979
   IsBusy = Busy;              // return Boolean value             
1980
endfunction
1981
 
1982
function UDNisLocked;            // boolean function primitive
1983
   input obbl;                           // input is required
1984
   if ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UDNprotect_bit) == `UDNprotect_bit)
1985
      UDNisLocked = `TRUE;
1986
   else
1987
      UDNisLocked = `FALSE;
1988
endfunction
1989
 
1990
function UPisLocked;            // boolean function primitive
1991
   input obbl;                   // input is required
1992
   UPisLocked = ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UPprotect_bit) == `UPprotect_bit) ? `TRUE : `FALSE;
1993
endfunction
1994
 
1995
function isUDNaddress;
1996
   input [`ADDRBUS_range] address;
1997
   if ((address >= `UDNREGSTART_addr) && ( address <= `UDNREGEND_addr)) // Check UDN register Address Bound 
1998
      isUDNaddress = `TRUE;
1999
   else isUDNaddress = `FALSE;
2000
endfunction
2001
 
2002
function isUPaddress;
2003
   input [`ADDRBUS_range] address;
2004
   if ((address >= `UPREGSTART_addr) && (address <= `UPREGEND_addr)) // Check UP register Address Bound 
2005
      isUPaddress = `TRUE;
2006
   else isUPaddress = `FALSE;
2007
endfunction
2008
 
2009
function [`BYTE_range] ExtIndexPRL;            // bit index of PRL register 
2010
   input [`ADDRBUS_range] addr;
2011
   ExtIndexPRL=(addr - `ExtREGSTART_regionaddr) / `ExtREG_regiondim;
2012
endfunction
2013
 
2014
function isExtLocked;            // boolean function primitive
2015
   input [`ADDRBUS_range] addr;                   // input is required
2016
   reg [`BYTE_range]      bitIndex;
2017
   begin
2018
      bitIndex = ExtIndexPRL(addr);  // protect bit index of Extended Protection Register Memory
2019
      isExtLocked = !(RegisterMemory[(`ExtPROTECTREGLOCK_addr - `REGSTART_addr)][bitIndex]);
2020
   end
2021
endfunction
2022
 
2023
function isExtValidAddress;
2024
   input [`ADDRBUS_range] address;
2025
   if ((address >= `ExtREGSTART_regionaddr) && (address <= `ExtREGEND_regionaddr) ) // Check ExtRegister Address Bound 
2026
      isExtValidAddress = `TRUE;
2027
   else isExtValidAddress = `FALSE;
2028
endfunction
2029
 
2030
task Program;
2031
   output [`BYTE_range] outStatus;
2032
   reg [`BYTE_range]    outStatus;
2033
begin
2034
   Busy = `TRUE;
2035
   hold_addr = address[`REG_addrbitRange];
2036
   hold_data = data;
2037
   if (Info) $write("[%t]  OTP Program Memory[%h]=%h\n",$time,hold_addr,data);
2038
   fork
2039
      begin : Operation
2040
         -> ErrorCheckEvent;
2041
         #`WordProgram_time RegisterMemory[hold_addr - `REGSTART_addr] = RegisterMemory[hold_addr - `REGSTART_addr] & hold_data;
2042
         -> CompleteEvent;
2043
      end
2044
      @CompleteEvent disable Operation;
2045
   join
2046
   outStatus = Status;
2047
   Busy = `FALSE;
2048
end
2049
endtask
2050
 
2051
always @(ErrorCheckEvent) begin
2052
   Status = `NoError_msg;
2053
   if (( address < `REGSTART_addr) || ( address > `REGEND_addr)) // Check Address Bound 
2054
      Status = `AddrRange_msg;
2055
   else if ( isUDNaddress(address) && UDNisLocked(1'bX) )
2056
      Status = `UDNlock_msg;
2057
   else if ((isUPaddress(address) && UPisLocked(1'bX)))
2058
      Status = `UPlock_msg;
2059
   else if ( isExtValidAddress(hold_addr) & isExtLocked(hold_addr) )
2060
      Status = `ExtREGLock_msg;
2061
 
2062
   else if (Kernel.Suspended)
2063
      Status = `SuspCmd_msg;
2064
   else if (!voltOK)
2065
      Status = `InvVDD_msg;
2066
 
2067
   if (Status != `NoError_msg)
2068
      ->CompleteEvent;
2069
   else
2070
      fork : ErrorCheck
2071
         @(negedge voltOK) Status = `InvVDD_msg;
2072
         @(Status) -> CompleteEvent;
2073
         @(CompleteEvent) disable ErrorCheck;
2074
      join
2075
end
2076
endmodule //end ProtectRegModule
2077
 
2078
 
2079
// Read Manager
2080
// Manage the read operation
2081
 
2082
module ReadModule(dataOutput,address,voltOK,Info);
2083
   output [`WORD_range] dataOutput;
2084
   input [`ADDRBUS_range] address;
2085
   input                  voltOK;
2086
   input                  Info;
2087
   reg [`WORD_range]      dataOutput, regRead;
2088
   reg [1:0]               Mode, oldMode;
2089
   reg [`BYTE_range]      Status;
2090
 
2091
   integer                i;
2092
 
2093
initial begin
2094
   regRead = 0;
2095
   Mode = `ReadArray_bus;
2096
   oldMode = `ReadArray_bus;
2097
   dataOutput = `DATABUS_dim'hzzzz;
2098
end
2099
 
2100
task SetMode;
2101
   input [1:0] newMode;
2102
   output [`BYTE_range] Status;
2103
   begin
2104
      Status = `NoError_msg;
2105
      if (Info && (newMode!=Mode)) begin
2106
         case (newMode)
2107
            `ReadArray_bus        : $display ("[%t]  Device now in Read Array mode ", $time);
2108
            `ReadCFI_bus          : $display ("[%t]  Device now in Read CFI mode ", $time);
2109
            `ReadSignature_bus    : $display ("[%t]  Device now in Read Electronic Signature Mode ", $time);
2110
            `ReadStatusReg_bus    : $display ("[%t]  Device now in Read Status Register Mode ", $time);
2111
            default               : $display ("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
2112
         endcase
2113
 
2114
         oldMode=Mode;
2115
         Mode = newMode;
2116
      end
2117
   end
2118
endtask
2119
 
2120
 
2121
always @Kernel.ResetEvent begin
2122
   Mode = `ReadArray_bus;
2123
end
2124
 
2125
always @(negedge Kernel.Ready) begin   // Configure according to status register
2126
   Mode = `ReadStatusReg_bus;
2127
end
2128
 
2129
always @Kernel.ReadEvent begin          // Main execution of a read is based on an event
2130
 
2131
 
2132
   case (Mode)
2133
      `ReadArray_bus       : begin
2134
         dataOutput = Memory_man.Get(address);
2135
         if (Info) $display("[%t]  Data Read result: memory[%h]=%h", $time,address,dataOutput);
2136
      end
2137
      `ReadCFI_bus         : begin
2138
         dataOutput = CFIquery_man.Get(address);
2139
         if (Info) $display("[%t]  Data Read result: CFI_memory[%h]=%h", $time,address,dataOutput);
2140
      end
2141
      `ReadSignature_bus   :  begin
2142
         dataOutput = Signature_man.Get(address);
2143
         if (Info) $display("[%t]  Read Device Identifier(addr=%h) :%h", $time,address,dataOutput);
2144
      end
2145
 
2146
      `ReadStatusReg_bus   : begin
2147
         dataOutput = SR_man.SR;
2148
         if (Info) $display("[%t]  Read Status Register: %b", $time,dataOutput[`BYTE_range]);
2149
      end
2150
 
2151
      default              : $display("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
2152
   endcase
2153
   if ((Mode == `ReadArray_bus) && (Memory_man.IsSuspended(address) == `TRUE)) begin
2154
      dataOutput = 16'hXX;
2155
      Kernel.SetWarning(`RD_cmd,8'hXX,`SuspAcc_msg);
2156
   end
2157
end
2158
 
2159
endmodule
2160
// end Module Read
2161
 
2162
 
2163
// *************************************************
2164
//
2165
// Status Register module :
2166
//
2167
//      implements the Status Register of the device
2168
//
2169
// *************************************************
2170
 
2171
module StatusRegModule(Info);
2172
   input Info;
2173
 
2174
 
2175
   reg   EraseStatus, ProgramStatus,
2176
         VpenStatus, BlockProtectionStatus, BW_status;
2177
 
2178
   reg [`BYTE_range] Status;
2179
 
2180
   wire [7:0]         SR = {Kernel.Ready,                        // bit 7 
2181
                           Erase_man.IsSuspended(1'bX),         // bit 6
2182
                           EraseStatus,                         // bit 5
2183
                           ProgramStatus,                       // bit 4
2184
                           VpenStatus,                          // bit 3
2185
                           Program_man.IsSuspended(1'bX) ||  ProgramBuffer_man.IsSuspended(1'bX),       // bit 2
2186
                           BlockProtectionStatus,               // bit 1
2187
                           BW_status};                          // bit 0
2188
   wire [7:0]         SR_Info =  SR;
2189
 
2190
 
2191
 
2192
//-----------------
2193
// Init
2194
//-----------------
2195
 
2196
initial begin
2197
   EraseStatus=1'b0;
2198
   ProgramStatus=1'b0;
2199
   VpenStatus=1'b0;
2200
   BlockProtectionStatus=1'b0;
2201
   BW_status=1'b0;
2202
end
2203
 
2204
 
2205
always @(SR_Info) if (Kernel.Ready!=1'bZ)
2206
   if (Info) $display("[%t]  Status Register Update: %b",$time, SR_Info);
2207
 
2208
always @(Kernel.ResetEvent) begin
2209
   Clear(Status);
2210
end
2211
 
2212
 
2213
always @(Kernel.Ready,ProtectReg_man.Busy, BuffEnhancedFactProgram_man.Busy)
2214
begin
2215
   if (Kernel.Ready)
2216
      BW_status = `FALSE;
2217
   else
2218
      if (BuffEnhancedFactProgram_man.Busy == `TRUE)
2219
         BW_status=`TRUE;
2220
 
2221
end
2222
 
2223
always @(Kernel.ErrorEvent) begin //Update status register bits upon specific errors
2224
   #0;
2225
   case(Kernel.GetError(1'bX))
2226
      `InvVDD_msg       : begin VpenStatus = `TRUE; end
2227
      `InvVPP_msg       : begin VpenStatus = `TRUE; end
2228
      `BlockLock_msg    : begin BlockProtectionStatus = `TRUE;  end
2229
      `UDNlock_msg      : begin ProgramStatus = `TRUE; end
2230
      `UPlock_msg       : begin ProgramStatus = `TRUE; end
2231
 
2232
      `ProtRegAddrRange_msg : begin
2233
         BlockProtectionStatus = `TRUE;
2234
      end
2235
      `ExtREGLock_msg   : begin
2236
         BlockProtectionStatus = `TRUE;
2237
      end
2238
 
2239
      `CmdSeq_msg       : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2240
      `AddrRange_msg    : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2241
      `AddrTog_msg      : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2242
      `PreProg_msg      : begin ProgramStatus = `TRUE; end
2243
      `WrongEraseConfirm_msg : begin ProgramStatus = `TRUE; EraseStatus   = `TRUE; end
2244
      `WrongBlankCheckConfirm_msg : begin
2245
         ProgramStatus = `TRUE; EraseStatus   = `TRUE;
2246
      end
2247
      `BlankCheckFailed_msg : begin
2248
         EraseStatus   = `TRUE;
2249
      end
2250
      `LeastAddr0:        begin
2251
         ProgramStatus = `TRUE;
2252
      end
2253
 
2254
 
2255
   endcase
2256
   case(Kernel.GetCmd(4'h1))
2257
      `PG_cmd           : begin ProgramStatus = `TRUE; end
2258
      `PRREG_cmd        : begin ProgramStatus = `TRUE; end
2259
      `PB_cmd           : begin ProgramStatus = `TRUE; end
2260
      `BLKEE_cmd        : begin EraseStatus = `TRUE; end
2261
      `BL_cmd           : if (Kernel.GetCmd(4'h2) == `BLconfirm_cmd) ProgramStatus = `TRUE;
2262
      `BUL_cmd          : if (Kernel.GetCmd(4'h2) ==`BULconfirm_cmd) EraseStatus   = `TRUE;
2263
      `BLD_cmd          : if (Kernel.GetCmd(4'h2) ==`BLDconfirm_cmd) ProgramStatus = `TRUE;
2264
      `BuffEnhProgram_cmd :
2265
         if (Kernel.GetCmd(4'h2) == `BuffEnhProgramCfrm_cmd)
2266
            ProgramStatus = `TRUE;
2267
 
2268
   endcase
2269
end
2270
 
2271
task Clear;
2272
   output [`BYTE_range] Status;
2273
   begin
2274
      Status = `NoError_msg;
2275
      EraseStatus = `FALSE;
2276
      ProgramStatus = `FALSE;
2277
      VpenStatus  = `FALSE;
2278
      BlockProtectionStatus   = `FALSE;
2279
      BW_status = `FALSE;
2280
   end
2281
endtask
2282
 
2283
endmodule  // end module status register
2284
 
2285
 
2286
// *************
2287
//
2288
// Kernel Module 
2289
//
2290
// *************
2291
 
2292
module KernelModule(VDD, VDDQ, VPP, Info);
2293
   input [`Voltage_range] VDD, VDDQ, VPP;
2294
   input                  Info;
2295
   event                  CUIcommandEvent, VerifyEvent, ErrorEvent, CompleteEvent, ResetEvent, ReadEvent, ProgramCompleteEvent, EraseCompleteEvent;
2296
 
2297
   reg                    voltOK, progVoltOK, eraseVoltOK, lockVoltOK, ioVoltOK, lockOverrideOK;
2298
   reg                    progHighVoltOK, eraseHighVoltOK;
2299
   reg [8'hFF:0]           CommandDecode1;
2300
   reg [16'hFFFF:0]        CommandDecode2;
2301
   reg [7:0]               lastStatus, lastCmd1, lastCmd2;
2302
 
2303
// Device Status
2304
 
2305
   wire                   Ready = (!Program_man.Busy && !ProgramBuffer_man.Busy  && !BuffEnhancedFactProgram_man.Busy
2306
                                   && !Erase_man.Busy && !ProtectReg_man.Busy && !BlankCheck_man.Busy);
2307
 
2308
 
2309
   wire                   Suspended = Program_man.Suspended || Erase_man.Suspended || ProgramBuffer_man.Suspended;
2310
 
2311
initial begin                 // constructor sequence
2312
   CommandDecode1 = 8'h00;         // initialize decode success status variables
2313
   CommandDecode2 = 16'h0000;
2314
end
2315
 
2316
 
2317
always @(voltOK) begin
2318
   if (!voltOK) begin
2319
      $display("[%t]  !ERROR: Invalid VDD Voltage.",$time);
2320
      -> ErrorEvent;
2321
   end
2322
   else
2323
      $display("[%t]  VDD Voltage is OK",$time);
2324
end
2325
 
2326
always @(ioVoltOK) begin
2327
   if (!ioVoltOK) begin
2328
      $display("[%t]  !ERROR: Invalid VDDQ I/O voltage.", $time);
2329
      -> ErrorEvent;
2330
   end
2331
   else
2332
      $display("[%t]  VDDQ Voltage is OK",$time);
2333
 
2334
end
2335
 
2336
always @(VDD) begin
2337
   if ((VDD < `VDDmin) | (VDD > `VDDmax))
2338
      voltOK = `FALSE;
2339
   else
2340
      voltOK = `TRUE;
2341
end
2342
 
2343
 
2344
always @(VDDQ) begin  // check i/o voltage constraints
2345
   if ((VDDQ >= `VDDQmin) && (VDDQ <= `VDDQmax))
2346
      ioVoltOK = `TRUE;
2347
   else
2348
      ioVoltOK = `FALSE;
2349
end
2350
 
2351
always @(VPP) begin // program/erase/lock
2352
   if ((VPP>=`VPPmin && VPP<=`VPPmax))  begin
2353
      progVoltOK  = `TRUE;
2354
      eraseVoltOK = `TRUE;
2355
      lockVoltOK  = `TRUE;
2356
      progHighVoltOK  = `FALSE;
2357
      eraseHighVoltOK = `FALSE;
2358
   end
2359
   else if ((VPP>=`VPPHmin) && (VPP<=`VPPHmax)) begin
2360
      progVoltOK  = `TRUE;
2361
      eraseVoltOK = `TRUE;
2362
      lockVoltOK  = `TRUE;
2363
      progHighVoltOK  = `TRUE;
2364
      eraseHighVoltOK = `TRUE;
2365
   end
2366
   else begin
2367
      progVoltOK  = `FALSE;
2368
      eraseVoltOK = `FALSE;
2369
      lockVoltOK  = `FALSE;
2370
      progHighVoltOK  = `FALSE;
2371
      eraseHighVoltOK = `FALSE;
2372
   end
2373
end
2374
 
2375
 
2376
function [7:0] GetError;
2377
   input required;
2378
   GetError = lastStatus;
2379
endfunction
2380
 
2381
function [7:0] GetCmd;
2382
   input commandNum;
2383
   GetCmd = (commandNum == 1) ? lastCmd1 : lastCmd2;
2384
endfunction
2385
 
2386
task SetWarning;
2387
   input [7:0] Cmd1, Cmd2;
2388
   input [7:0] Status;
2389
   begin
2390
      Report(Cmd1,Cmd2,Status);
2391
      lastStatus = Status;
2392
   end
2393
endtask
2394
 
2395
task SetError;
2396
   input [7:0] Cmd1, Cmd2;
2397
   input [7:0] ErrFlag;
2398
   begin
2399
      SetWarning(Cmd1,Cmd2,ErrFlag);
2400
      -> ErrorEvent; // Only errors set error event
2401
   end
2402
endtask
2403
 
2404
 
2405
task Report;
2406
   input [7:0] Cmd1, Cmd2;
2407
   input [7:0] Status;
2408
   begin
2409
      lastStatus = Status;
2410
      lastCmd1 = Cmd1;
2411
      lastCmd2 = Cmd2;
2412
      if ((lastStatus != `NoError_msg) || Info) begin //Display error .
2413
         $write("[%t] ",$time);
2414
         case(Status)
2415
            `NoError_msg         : begin $write(" Command Completion Successful "); end
2416
            `CmdSeq_msg         : begin $write(" !Error:   [Invalid Command]\n Sequence Command Unknown"); -> ErrorEvent; end
2417
            `SuspCmd_msg        : begin $write(" !Error:   [Invalid Command]\n Cannot execute this command during suspend"); -> ErrorEvent; end
2418
            `SuspAcc_msg        : begin $write(" !Error:   [Invalid Command]\n Cannot access this address due to suspend"); -> ErrorEvent; end
2419
            `SignAddrRange_msg  : begin $write(" !Error:   [Invalid Address]\n Signature Address out of range"); end
2420
            `CFIAddrRange_msg   : begin $write(" !Error:   [Invalid Address]\n CFI Address out of range"); end
2421
            `AddrRange_msg      : begin $write(" !Error:   [Invalid Address]\n Address out of range"); -> ErrorEvent; end
2422
            `AddrTog_msg        : begin $write(" !Error:   [Program Buffer]\n Cannot change block address during command sequence"); -> ErrorEvent; end
2423
            `BuffSize_msg       : begin $write(" !Error:   [Program Buffer]\n Buffer size is too large (Max Size is %d) ",`ProgramBuffer_dim); -> ErrorEvent; end
2424
            `InvVDD_msg         : begin $write(" !Error:   [Invalid Supply]\n Voltage Supply must be: VDD>VDDmin and VDD<VDDmax "); -> ErrorEvent; end
2425
            `InvVPP_msg         : begin $write(" !Error:   [Invalid Program Supply]\n Program Supply Voltage must be: VPP>VPPHmin and VPP<VPPHmax for this Operation"); -> ErrorEvent; end
2426
            `ByteToggle_msg     : begin $write(" !Error:   [BYTE_N Toggled]\n Cannot toggle BYTE_N while busy"); -> ErrorEvent; end
2427
            `PreProg_msg        : begin $write(" !Error:   [Program Failure]\n Program Failure due to cell failure"); -> ErrorEvent; end
2428
            `UDNlock_msg        : begin $write(" !Error:   [Program Failure]\n Unique Device Number Register is locked"); -> ErrorEvent; end
2429
            `UPlock_msg         : begin $write(" !Error:   [Program Failure]\n User Programmable Register is locked"); -> ErrorEvent; end
2430
            `ExtREGLock_msg     : begin $write(" !Error:   [Program Failure]\n Extended User Programmable OTP is locked"); -> ErrorEvent; end
2431
            `NoUnLock_msg       : begin $write(" #Warning: [Locked Down Warning]\n  Invalid UnLock Block command in Locked-Down Block"); end
2432
            `SuspAccWarn_msg    : begin $write(" #Warning: [Invalid Access]\n  It isn't possible access this address due to suspend"); end
2433
            `BlockLock_msg      : begin $write(" !Error:   [Locked Error]\n Cannot complete operation when the block is locked "); -> ErrorEvent; end
2434
            `BlkBuffer_msg      : begin $write(" !Error: [Program Buffer]  Program Buffer cannot cross block boundary"); end
2435
            `AddrCFI_msg        : begin $write(" #Warning: [Invalid CFI Address]\n CFI Address out of range"); end
2436
            `NoBusy_msg         : begin $write(" #Warning: [NO Busy]\n Device is not Busy"); end
2437
            `NoSusp_msg         : begin $write(" #Warning: [NO Suspend]\n Nothing previus suspend command"); end
2438
            `Suspend_msg        : begin $write("  Suspend of "); end
2439
            `WrongEraseConfirm_msg : begin
2440
               $write(" !Error: [Wrong Erase Confirm Code ");
2441
               -> ErrorEvent;
2442
            end
2443
            `LeastAddr0         : begin
2444
               $write(" !Error:   [Program Failure]\n Least Significative bit [%2d downto 0] of Start Address must be 0",`ProgramBuffer_addrDim-1);
2445
               -> ErrorEvent;
2446
            end
2447
 
2448
            `WrongBlankCheckConfirm_msg : begin
2449
               $write(" !Error: [Confirm Code] Wrong Blank Check Confirm Code ");
2450
               -> ErrorEvent;
2451
            end
2452
 
2453
            `WrongBlankCheckBlock:  begin
2454
               $write(" !Error:   [Blank Check Failure]\n The block must be a main block");
2455
               -> ErrorEvent;
2456
            end
2457
 
2458
            `BlankCheckFailed_msg : begin $write(" !Error:   [Blank Check]\n Blank Check Failed ");
2459
               -> ErrorEvent;
2460
            end
2461
 
2462
            default             : begin $write(" !ERROR: [Unknown error]\n Flag=%h, cmd1=%hh, cmd2=%hh",Status,Cmd1,Cmd2); -> ErrorEvent; end
2463
         endcase
2464
         case (Cmd1)
2465
            16'hXX              : $display(" !Error: [General Error}\n Error not defined");
2466
            `RD_cmd             : $display(" { Read Array }");
2467
            `RSR_cmd            : $display(" { Read Status Register }");
2468
            `RSIG_cmd           : $display(" { Read Electronic Signature }");
2469
            `RCFI_cmd           : $display(" { Read CFI }");
2470
            `PG_cmd             : $display(" { Program }");
2471
            `BuffEnhProgram_cmd : $display(" { Buffer Enhanced Factory Program }");
2472
 
2473
            `SCR_cmd | `BL_cmd | `BUL_cmd |  `BLD_cmd
2474
               : begin
2475
                  if (Cmd2 == `SCRconfirm_cmd) $display(" { Set Configuration Register }");
2476
                  if (Cmd2 == `BLconfirm_cmd)  $display(" { Block Lock }");
2477
                  if (Cmd2 == `BULconfirm_cmd) $display(" { Block UnLock }");
2478
                  if (Cmd2 == `BLDconfirm_cmd) $display(" { Block Lock-Down }");
2479
               end
2480
            `PER_cmd          : $display(" { Program/Erase Resume }");
2481
            `PRREG_cmd        : $display(" { Protection Register Command }");
2482
            `BLKEE_cmd        : $display(" { Block Erase }");
2483
            `BLNKCHK_cmd      : $display(" { Blank Check }");
2484
            `CLRSR_cmd        : $display(" { Clear Status Register }");
2485
            `PES_cmd          : $display(" { Program/Erase Suspend }");
2486
            `PB_cmd           : $display(" { Write to Buffer and Program }");
2487
            default           : $display(" {unknown command:  %hh}", Cmd1);
2488
         endcase
2489
      end
2490
   end
2491
endtask
2492
 
2493
task CheckTime;
2494
   input [8*6:1] tstr;
2495
   input [31:0]  tdiff, tprev;
2496
 
2497
   begin
2498
      if ($time - tprev < tdiff) begin
2499
         $display ("[%t]  !ERROR: %0s timing constraint violation:  %0d-%0d < %0dns ", $time, tstr, $time, tprev, tdiff);
2500
         -> ErrorEvent;
2501
      end
2502
   end
2503
endtask
2504
 
2505
endmodule // end module Kernel 
2506
 
2507
 
2508
 
2509
 
2510
 
2511
module x28fxxxp30(A, DQ, W_N, G_N, E_N, L_N, K, WAIT, WP_N, RP_N, VDD, VDDQ, VPP, Info);
2512
 
2513
// Signal Bus
2514
   input [`ADDRBUS_dim-1:0] A;           // Address Bus 
2515
   inout [`DATABUS_dim-1:0] DQ;          // Data I/0 Bus
2516
// Control Signal
2517
   input                    W_N;                           // Write Enable 
2518
   input                    G_N;                           // Output Enable
2519
   input                    E_N;                           // Chip Enable
2520
   input                    L_N;                           // Latch Enable
2521
   input                    K;                             // Clock
2522
   input                    WP_N;                          // Write Protect
2523
   input                    RP_N;                          // Reset/Power-Down
2524
 
2525
// Voltage signal rappresentad by integer Vector which correspond to millivolts
2526
   input [`Voltage_range]   VDD;           // Supply Voltage
2527
   input [`Voltage_range]   VDDQ;          // Input/Output Supply Voltage
2528
   input [`Voltage_range]   VPP;           // Optional Supply Voltage for fast Program & Erase
2529
 
2530
// Others Signal       
2531
   output                   WAIT;                          // Wait
2532
   reg                      wait_;
2533
assign WAIT = wait_;
2534
   input                    Info;                           // Enable/Disable Information of the operation in the memory 
2535
   wire                     CLK;
2536
assign CLK = (K ~^ ConfigReg_man.isRisingClockEdge);
2537
   reg                      CLOCK;
2538
// === Internal Signal ===
2539
// Chip Enable 
2540
   wire                     CE_N = E_N & Kernel.voltOK & RP_N;
2541
 
2542
// Output Enable 
2543
   wire                     OE_N = G_N | CE_N | !Kernel.ioVoltOK | !RP_N;
2544
// Write Enable 
2545
   wire                     WE_N = W_N | CE_N;
2546
 
2547
// Latch Enable
2548
 
2549
   wire                     LE_N = L_N | CE_N;
2550
// === Bus Latch ===
2551
// Data Bus
2552
   wire [`DATABUS_dim-1:0]  DataBusIn;
2553
   wire [`DATABUS_dim-1:0]  DataBurst;
2554
 
2555
// read burst is in wait state
2556
   wire                     isWait;
2557
 
2558
// Address Bus
2559
   reg [`ADDRBUS_dim - 1:0] AddrBusIn;
2560
 
2561
// Status
2562
//aggiunti stati buffenha...e blank....
2563
   reg [`BYTE_range]        KernelStatus, ReadStatus, EraseStatus, ProgramStatus, BuffEnhancedProgramStatus,
2564
                            LockStatus, ConfigStatus, BufferStatus,BlankCheckStatus,ProgramBufferStatus,
2565
                            SuspendStatus, ResumeStatus, ClearSRStatus, ProtectRegStatus;
2566
 
2567
 
2568
   reg [`BYTE_range]        status=`Free_pes;
2569
 
2570
//address latching in read operation
2571
always @(negedge LE_N) if (W_N==`HIGH)  begin
2572
   if (KernelStatus == `READY && ConfigReg_man.isASynchronous)
2573
      @(posedge LE_N) begin
2574
         if (L_N)
2575
 
2576
            AddrBusIn = A;                // AddressBus has been Latched
2577
 
2578
      end
2579
end
2580
 
2581
always @(negedge LE_N) if (W_N==`HIGH) begin :latching_a
2582
   if (KernelStatus == `READY) begin
2583
      if(ConfigReg_man.isSynchronous)
2584
         fork
2585
 
2586
            begin : L_Address
2587
 
2588
               @(posedge LE_N) if (L_N) begin
2589
 
2590
                  AddrBusIn = A;                // AddressBus has been Latched
2591
                  disable K_Address;
2592
 
2593
               end
2594
            end
2595
 
2596
            begin : K_Address
2597
 
2598
               @(posedge CLK) begin
2599
 
2600
                  AddrBusIn = A;                // AddressBus has been Latched
2601
                  disable L_Address;
2602
               end
2603
            end
2604
         join
2605
 
2606
   end
2607
end
2608
 
2609
 
2610
always @(negedge WE_N) begin
2611
   if (KernelStatus==`READY)
2612
      @(posedge WE_N) begin
2613
         if(OE_N==`HIGH)
2614
            AddrBusIn = A;                // AddressBus has been Latched
2615
 
2616
      end
2617
end
2618
 
2619
   integer i;
2620
   integer n_block;
2621
 
2622
// Wait Driver 
2623
   time    timeWaitDriver,timeWaitDriverZ;
2624
 
2625
   reg     PB_init=0;
2626
   reg     P_init=0;
2627
   reg     BP_init=0;
2628
   reg     Prog_init=0;
2629
 
2630
always @(PB_init,P_init,BP_init) begin
2631
   Prog_init=(PB_init ||P_init || BP_init);
2632
end
2633
 
2634
   wire [`BYTE_range] AccessTime;
2635
 
2636
// ****************
2637
// 
2638
// Modules Istances
2639
//
2640
// ****************
2641
 
2642
DataErrorModule   DataError_man();              // Check for errors on UserData.h
2643
 
2644
CUIdecoder1       ReadArray_Command  (DQ[`LOW_range], "Read Array                         ", `RD_cmd, (Kernel.Ready && !Prog_init),        Info),
2645
   ReadSR_Command     (DQ[`LOW_range], "Read Status Register               ", `RSR_cmd, !Prog_init,        Info),
2646
   ReadSign_Command   (DQ[`LOW_range], "Read Electronic Signature          ", `RSIG_cmd, (Kernel.Ready && !Prog_init),       Info),
2647
   ReadCFI_Command    (DQ[`LOW_range], "Read CFI                           ", `RCFI_cmd, (Kernel.Ready && !Prog_init),      Info),
2648
   Program_Command    (DQ[`LOW_range], "Program                            ", `PG_cmd,   (Kernel.Ready && !Prog_init),      Info),
2649
 
2650
   ProgramBuffer_Command    (DQ[`LOW_range], "Program Buffer                     ", `PB_cmd, (Kernel.Ready && !Prog_init),        Info),
2651
   ProgramReg_Command (DQ[`LOW_range], "Protection Register Program        ", `PRREG_cmd,  (Kernel.Ready && !Prog_init),    Info),
2652
   Resume_Command     (DQ[`LOW_range], "Resume                             ", `PER_cmd,  (Kernel.Ready && Kernel.Suspended),      Info),
2653
   BlockErase_Command  (DQ[`LOW_range], "Block Erase                        ", `BLKEE_cmd,(Kernel.Ready && !Prog_init),      Info),
2654
   ClearSR_Command    (DQ[`LOW_range], "Clear Status Register              ", `CLRSR_cmd, (Kernel.Ready && !Prog_init),     Info),
2655
 
2656
   BlankCheck_Command  (DQ[`LOW_range], "Blank Check                        ", `BLNKCHK_cmd, (Kernel.Ready && !Prog_init),   Info),
2657
   BuffEnhactoryProgram_Command (DQ[`LOW_range], "Buffer Enh.Factory Program  [Setup]", `BuffEnhProgram_cmd,(Kernel.Ready && !Prog_init), Info);
2658
 
2659
 
2660
CUIdecoder_Busy1  Suspend_Command    (DQ[`LOW_range], "Suspend ",   `PES_cmd, !Kernel.Ready, Info);
2661
 
2662
CUIdecoder2        BlockLock_Command (DQ[`LOW_range], "Block Lock                 ", `BL_cmd,       `BLconfirm_cmd, (Kernel.Ready && !Prog_init),    Info),
2663
   BlockUnlock_Command (DQ[`LOW_range], "Block UnLock               ", `BUL_cmd,      `BULconfirm_cmd, (Kernel.Ready && !Prog_init),   Info),
2664
   BlockLockDown_Command (DQ[`LOW_range], "Block Lock-Down            ", `BLD_cmd,      `BLDconfirm_cmd, (Kernel.Ready && !Prog_init),   Info),
2665
   SetConfigReg_Command (DQ[`LOW_range], "Set Configuration Register ", `SCR_cmd,      `SCRconfirm_cmd, (Kernel.Ready && !Prog_init),   Info);
2666
 
2667
KernelModule            Kernel            (VDD, VDDQ, VPP, Info);
2668
ReadModule              Read_man          (DataBusIn, AddrBusIn, Kernel.ioVoltOK, Info);
2669
OutputBufferModule      OutputBuffer_man  (DataBusIn, DataBurst, DQ, OE_N);
2670
StatusRegModule         SR_man            (Info);
2671
MemoryModule            Memory_man        (Info);
2672
ProgramModule           Program_man       (AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
2673
 
2674
BuffEnhancedFactProgramModule BuffEnhancedFactProgram_man(AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
2675
ProtectRegModule        ProtectReg_man    (AddrBusIn, DQ, Kernel.progVoltOK, Info);
2676
EraseModule             Erase_man         (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
2677
 
2678
 
2679
BlankCheckModule        BlankCheck_man    (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
2680
 
2681
BlockLockModule         BlockLock_man     (AddrBusIn, WP_N, RP_N, Info);
2682
ProgramBufferModule   ProgramBuffer_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
2683
SignatureModule         Signature_man     ();        // , `FALSE);
2684
CFIqueryModule          CFIquery_man      ();        // , `TRUE);
2685
ConfigRegModule         ConfigReg_man     (AddrBusIn,Info);                              // implements the Configuration Register
2686
BurstModule             Burst_man         (AddrBusIn, DataBurst, isWait, CLK, CLOCK, L_N, G_N,W_N, Info);
2687
 
2688
BankLib                 BankLib_man       ();
2689
TimingDataModule        TimingData_man    ();
2690
TimingLibModule         TimingLib_man     (A,DQ,W_N,G_N,E_N,L_N,WP_N,K,VPP);
2691
 
2692
initial begin
2693
 
2694
   $timeformat(-9, 0, " ns", 12);               // Format time displays to screen
2695
   -> Kernel.ResetEvent;                        // Reset Device 
2696
   KernelStatus = `BUSY;                        // Device is Busy
2697
   $display ("[%t]  --- Device is Busy  (start up time) --- ", $time);
2698
   #(TimingData_man.tVDHPH) KernelStatus = `READY;              // End of Start-Up Time
2699
   $display ("[%t]  --- Device is Ready (end of start-up time) --- ", $time);
2700
 
2701
   AddrBusIn = `ADDRBUS_dim'hZ;
2702
 
2703
   wait_ = 1'hZ;
2704
   CLOCK = 1'b0;
2705
end
2706
 
2707
// Recognize command input
2708
always @(negedge WE_N) begin
2709
   if (KernelStatus==`READY)
2710
      @(posedge WE_N) begin
2711
 
2712
         -> Kernel.CUIcommandEvent;               // new command has been written into Kernel.
2713
 
2714
      end
2715
end
2716
 
2717
// Check error
2718
always @(Kernel.CUIcommandEvent) begin : Timeout
2719
   #3
2720
      -> Kernel.ErrorEvent;
2721
   disable Verify;
2722
end
2723
 
2724
// Verify command issued 
2725
always @(Kernel.CUIcommandEvent) begin : Verify
2726
   @(Kernel.VerifyEvent)
2727
 
2728
      disable Timeout;
2729
end
2730
 
2731
// Default to Read Array command
2732
always @(negedge OE_N) begin
2733
   if (OE_N == `LOW && (ConfigReg_man.isASynchronous)) begin
2734
      if (L_N==0) AddrBusIn=A;
2735
      #1
2736
         -> Kernel.ReadEvent;
2737
   end
2738
end
2739
 
2740
// Page Read
2741
always @(A) begin
2742
 
2743
   if ((OE_N == `LOW) &&  (A !== `ADDRBUS_dim'hZ) && (A !== `ADDRBUS_dim'hx) && (ConfigReg_man.isASynchronous))  begin
2744
      AddrBusIn = A;
2745
      #0 -> Kernel.ReadEvent;
2746
 
2747
   end
2748
end
2749
 
2750
 
2751
// Reset the Kernel
2752
always @(negedge RP_N) begin
2753
   -> Kernel.ResetEvent;
2754
   if (Info) $display ("[%t]  Device has been reset ", $time);
2755
   KernelStatus = `BUSY;
2756
   @(posedge RP_N) KernelStatus = `READY;
2757
end
2758
 
2759
// ----- Recognize Command Input -----
2760
always @(Kernel.CommandDecode1[`RD_cmd]) if (KernelStatus==`READY)  begin                        // Read Array
2761
   Read_man.SetMode(`ReadArray_bus, ReadStatus);
2762
   Kernel.Report(`RD_cmd, 8'hXX, ReadStatus);
2763
   #1 -> Kernel.CompleteEvent;
2764
end
2765
 
2766
always @(Kernel.CommandDecode1[`RSR_cmd]) if (KernelStatus==`READY) begin                       // Read Status Register
2767
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2768
   Kernel.Report(`RSR_cmd, 8'hXX, ReadStatus);
2769
   #1 -> Kernel.CompleteEvent;
2770
end
2771
 
2772
 
2773
always @(Kernel.CommandDecode1[`RSIG_cmd]) if (KernelStatus==`READY )  begin                      // Read Electronic Signature
2774
   Read_man.SetMode(`ReadSignature_bus, ReadStatus);
2775
   Kernel.Report(`RSIG_cmd, 8'hXX, ReadStatus);
2776
   #1 -> Kernel.CompleteEvent;
2777
end
2778
 
2779
always @(Kernel.CommandDecode1[`RCFI_cmd]) if (KernelStatus==`READY)  begin                      // Read CFI 
2780
   Read_man.SetMode(`ReadCFI_bus, ReadStatus);
2781
   Kernel.Report(`RCFI_cmd, 8'hXX, ReadStatus);
2782
   #1 -> Kernel.CompleteEvent;
2783
end
2784
 
2785
always @(Kernel.CommandDecode1[`PG_cmd]) if (KernelStatus==`READY) begin                     // Program
2786
   P_init=1;
2787
   @Kernel.CUIcommandEvent
2788
          #1 -> Kernel.VerifyEvent;
2789
   Program_man.Program(ProgramStatus);
2790
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
2791
-> Kernel.CompleteEvent;
2792
P_init=0;
2793
end
2794
 
2795
 
2796
always @(Kernel.CommandDecode1[`PRREG_cmd]) if (KernelStatus==`READY)  begin                      // Protection Register Program
2797
   @Kernel.CUIcommandEvent
2798
      #1 -> Kernel.VerifyEvent;
2799
   ProtectReg_man.Program(ProtectRegStatus);
2800
Kernel.Report(`PRREG_cmd, 8'hXX, ProtectRegStatus);
2801
-> Kernel.CompleteEvent;
2802
end
2803
 
2804
always @(Kernel.CommandDecode1[`PES_cmd]) if (KernelStatus==`READY) begin                       // Suspend
2805
   if (Program_man.IsBusy(1'bX))
2806
      Program_man.Suspend(SuspendStatus);
2807
   else if (ProgramBuffer_man.IsBusy(1'bX))
2808
      ProgramBuffer_man.Suspend(SuspendStatus);
2809
   else if (Erase_man.IsBusy(1'bX))
2810
      Erase_man.Suspend(SuspendStatus);
2811
   -> Kernel.CompleteEvent;
2812
end
2813
 
2814
 
2815
always @(Kernel.CommandDecode1[`PER_cmd]) if (KernelStatus==`READY) begin                       // Program/Erase Resume
2816
   ResumeStatus = `NoError_msg;
2817
   if (Program_man.IsSuspended(1'bX)) begin
2818
      Program_man.Resume(ProgramStatus);
2819
      Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
2820
   end
2821
   else if (ProgramBuffer_man.IsSuspended(1'bX)) begin
2822
      ProgramBuffer_man.Resume(BufferStatus);
2823
      Kernel.Report(`PB_cmd, 8'hXX, BufferStatus);
2824
   end
2825
   else if (Erase_man.IsSuspended(1'bX)) begin
2826
      Erase_man.Resume(EraseStatus);
2827
      Kernel.Report(`BLKEE_cmd, 8'hXX, EraseStatus);
2828
   end
2829
   else
2830
      ResumeStatus = `NoSusp_msg;
2831
   Kernel.Report(`PER_cmd, 8'hXX, ResumeStatus);
2832
   -> Kernel.CompleteEvent;
2833
 
2834
end
2835
 
2836
always @(Kernel.CommandDecode1[`BLKEE_cmd]) if (KernelStatus==`READY) begin                    // Block Erase
2837
   Read_man.SetMode(`ReadStatusReg_bus,ReadStatus);
2838
   EraseStatus=`NoError_msg;
2839
   @Kernel.CUIcommandEvent
2840
               Erase_man.checkConfirm(EraseStatus);
2841
   #1 -> Kernel.VerifyEvent;
2842
   if (EraseStatus != `NoError_msg)
2843
      Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd, EraseStatus);
2844
   else
2845
   begin
2846
      Erase_man.BlockErase(EraseStatus);
2847
      Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd , EraseStatus);
2848
      -> Kernel.CompleteEvent;
2849
   end
2850
end
2851
 
2852
always @(Kernel.CommandDecode1[`CLRSR_cmd]) if (KernelStatus==`READY)  begin                    // Clear Status Register
2853
   SR_man.Clear(ClearSRStatus);
2854
   Kernel.Report(`CLRSR_cmd, 8'hXX, ClearSRStatus);
2855
   #1 -> Kernel.CompleteEvent;
2856
end
2857
 
2858
 
2859
//aggiunta ************************************************
2860
// PB Fast Program Commands
2861
always @(Kernel.CommandDecode1[`PB_cmd]) if (KernelStatus==`READY)  begin                       // Write to Program and Buffer 
2862
   ProgramBufferStatus = `NoError_msg;
2863
   PB_init=1;
2864
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2865
   @Kernel.CUIcommandEvent
2866
      ProgramBuffer_man.SetCount(ProgramBufferStatus);
2867
   #1 -> Kernel.VerifyEvent;
2868
 
2869
   if (ProgramBufferStatus == `NoError_msg) begin
2870
      for (i=1; i <= ProgramBuffer_man.GetCount(1'bX); i=i+1) begin : GetData
2871
         @Kernel.CUIcommandEvent
2872
             #1;
2873
 
2874
         ProgramBuffer_man.Load(ProgramBufferStatus);
2875
         #1 -> Kernel.VerifyEvent;
2876
         if (ProgramBufferStatus != `NoError_msg)
2877
            disable GetData;
2878
      end
2879
      @Kernel.CUIcommandEvent
2880
         if (DQ[`BYTE_range] != `PBcfm_cmd)
2881
            ProgramBufferStatus = `CmdSeq_msg;
2882
         else begin
2883
            #1 -> Kernel.VerifyEvent;
2884
            ProgramBuffer_man.Program(ProgramBufferStatus);
2885
end
2886
   end
2887
   Kernel.Report(`PB_cmd, 8'hXX, ProgramBufferStatus);
2888
   ->Kernel.CompleteEvent;
2889
   PB_init=0;
2890
end
2891
//*************************************************************************
2892
 
2893
always @(Kernel.CommandDecode2[{`BL_cmd,`BLconfirm_cmd}]) if (KernelStatus==`READY)  begin      // Block Lock
2894
   BlockLock_man.Lock(LockStatus);
2895
   Kernel.Report(`BL_cmd, `BLconfirm_cmd, LockStatus);
2896
   -> Kernel.CompleteEvent;
2897
end
2898
 
2899
always @(Kernel.CommandDecode2[{`BUL_cmd,`BULconfirm_cmd}]) if (KernelStatus==`READY) begin    // Block UnLock
2900
   BlockLock_man.UnLock(LockStatus);
2901
   Kernel.Report(`BUL_cmd,`BULconfirm_cmd, LockStatus);
2902
   -> Kernel.CompleteEvent;
2903
end
2904
 
2905
always @(Kernel.CommandDecode2[{`BLD_cmd,`BLDconfirm_cmd}]) if (KernelStatus==`READY)  begin    // Block Lock-Down
2906
   BlockLock_man.LockDown(LockStatus);
2907
   Kernel.Report(`BLD_cmd,`BLDconfirm_cmd, LockStatus);
2908
   -> Kernel.CompleteEvent;
2909
end
2910
 
2911
always @(Kernel.CommandDecode2[{`SCR_cmd,`SCRconfirm_cmd}]) if (KernelStatus==`READY) begin    // Set Configuration Register
2912
   ConfigReg_man.putConfigReg(ConfigStatus);
2913
   Kernel.Report(`SCR_cmd,`SCRconfirm_cmd, ConfigStatus);
2914
   -> Kernel.CompleteEvent;
2915
end
2916
 
2917
 
2918
// BC
2919
always @(Kernel.CommandDecode1[`BLNKCHK_cmd]) if (KernelStatus==`READY)  begin                    // Blank Check
2920
   BlankCheckStatus=`NoError_msg;
2921
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2922
   @Kernel.CUIcommandEvent
2923
      BlankCheck_man.checkConfirm(BlankCheckStatus);
2924
   #1 -> Kernel.VerifyEvent;
2925
 
2926
   if (BlankCheckStatus != `NoError_msg) begin
2927
 
2928
      Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
2929
   end else
2930
   begin
2931
      BlankCheck_man.BlankCheck(BlankCheckStatus);
2932
      Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
2933
   end
2934
   -> Kernel.CompleteEvent;
2935
 
2936
end
2937
// BEFP 
2938
always @(Kernel.CommandDecode1[`BuffEnhProgram_cmd]) if (KernelStatus==`READY)  begin    // Buffer Enhanced Factory Program: Setup Phase
2939
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2940
   BP_init=1;
2941
   @Kernel.CUIcommandEvent
2942
           #1 -> Kernel.VerifyEvent;
2943
   if (Kernel.Suspended | !Kernel.Ready)
2944
      BuffEnhancedProgramStatus = `SuspCmd_msg;
2945
   else begin
2946
      if (DQ[`LOW_range]!=`BuffEnhProgramCfrm_cmd)
2947
         BuffEnhancedProgramStatus=`CmdSeq_msg;
2948
      else begin
2949
         if (Info) $display("[%t]  Command Issued: Buffer Enh.Factory Program  [Confirm]",$time);
2950
 
2951
         BuffEnhancedFactProgram_man.Setup(BuffEnhancedProgramStatus);
2952
         if (BuffEnhancedProgramStatus == `NoError_msg) begin
2953
            while (BuffEnhancedProgramStatus == `NoError_msg)  begin               // Loop Program - Enhanced Factory Program: Program Phase
2954
               if (Info) $display("[%t]  Enhanced Factory Program -> Load Phase",$time);
2955
 
2956
               while (BuffEnhancedProgramStatus == `NoError_msg ) begin               // Loop Load - Enhanced Factory Program: Load Phase
2957
                  @Kernel.CUIcommandEvent
2958
                                                 #1 -> Kernel.VerifyEvent;
2959
                  BuffEnhancedFactProgram_man.Load(BuffEnhancedProgramStatus);
2960
               end
2961
               if (BuffEnhancedProgramStatus==`ProgramPHASE_BEFP_msg) begin
2962
                  BuffEnhancedFactProgram_man.Program(BuffEnhancedProgramStatus);
2963
end
2964
            end
2965
            BuffEnhancedFactProgram_man.Exit(BuffEnhancedProgramStatus);
2966
         end
2967
      end
2968
      if (BuffEnhancedProgramStatus == `ExitPHASE_BEFP_msg)
2969
         BuffEnhancedProgramStatus = `NoError_msg;
2970
   end
2971
   Kernel.Report(`BuffEnhProgram_cmd,`BuffEnhProgramCfrm_cmd, BuffEnhancedProgramStatus);
2972
   -> Kernel.CompleteEvent;
2973
   BP_init=0;
2974
end
2975
 
2976
 
2977
 
2978
//***********************************************************
2979
 
2980
// Decode Delays for Page Mode Reads
2981
 
2982
//******************************************************
2983
 
2984
// Page mode
2985
always
2986
begin :nopage
2987
   @(A[`ADDRBUS_dim - 1:4])
2988
      disable page;
2989
 
2990
   OutputBuffer_man.SetValid(TimingData_man.tAVQV);
2991
end
2992
 
2993
// Page mode
2994
always
2995
begin :page
2996
   @(A[3:0]) //pagina di 16 words
2997
      OutputBuffer_man.SetValid(TimingData_man.tAVQV1);
2998
end
2999
 
3000
 
3001
// Output Buffer delays 
3002
 
3003
always @(negedge E_N) begin
3004
   OutputBuffer_man.SetX(TimingData_man.tELQX);
3005
   OutputBuffer_man.SetValid(TimingData_man.tELQV);
3006
 
3007
end
3008
 
3009
always @(negedge G_N) begin
3010
   #0;
3011
   OutputBuffer_man.SetX(TimingData_man.tGLQX);
3012
   OutputBuffer_man.SetValid(TimingData_man.tGLQV);
3013
 
3014
end
3015
 
3016
always @(posedge CLK) begin
3017
   CLOCK = !CLOCK;
3018
end
3019
 
3020
always @(negedge CLK) begin
3021
   CLOCK = !CLOCK;
3022
end
3023
 
3024
 
3025
 
3026
   reg waiting=1;
3027
 
3028
always @(posedge G_N) begin
3029
 
3030
   waiting=1;
3031
 
3032
end
3033
 
3034
 
3035
 
3036
always @(CLK) begin
3037
 
3038
   if ((!G_N) && (CE_N == `LOW) && (ConfigReg_man.isSynchronous) && (CLK)) begin
3039
 
3040
      if (ConfigReg_man.isWaitBeforeActive && Burst_man.firstEOWL && waiting) begin
3041
         OutputBuffer_man.SetX(TimingData_man.tKHQX);
3042
         @(posedge (CLK))
3043
            OutputBuffer_man.SetX(TimingData_man.tKHQX);
3044
         OutputBuffer_man.SetValid(TimingData_man.tKHQV);
3045
         waiting=0;
3046
 
3047
      end else begin
3048
 
3049
         OutputBuffer_man.SetX(TimingData_man.tKHQX);
3050
         OutputBuffer_man.SetValid(TimingData_man.tKHQV);
3051
 
3052
      end
3053
 
3054
   end
3055
end
3056
 
3057
always @(negedge L_N) if(W_N==`HIGH)begin
3058
   if (ConfigReg_man.isSynchronous && CE_N==`LOW) begin
3059
      OutputBuffer_man.SetValid(TimingData_man.tLLQV);
3060
 
3061
 
3062
   end
3063
end
3064
 
3065
 
3066
always @(RP_N) begin
3067
   if (RP_N == `HIGH)
3068
      OutputBuffer_man.SetValid(TimingData_man.tPHWL);
3069
end
3070
 
3071
always @(posedge CE_N) begin
3072
   OutputBuffer_man.SetZ(TimingData_man.tEHQZ);
3073
end
3074
 
3075
always @(posedge G_N) begin
3076
   OutputBuffer_man.SetZ(TimingData_man.tGHQZ);
3077
   OutputBuffer_man.SetZ(TimingData_man.tGHTZ);
3078
 
3079
end
3080
 
3081
 
3082
 
3083
////////////////////////////////
3084
always @(CE_N) begin
3085
   if (CE_N == `LOW && W_N==`HIGH && G_N == `LOW) begin
3086
      if (ConfigReg_man.isSynchronous)
3087
         wait_ = #(TimingData_man.tELTV) ConfigReg_man.isWaitPolActiveHigh;
3088
      else wait_ = #(TimingData_man.tELTV) !ConfigReg_man.isWaitPolActiveHigh;
3089
   end
3090
   else
3091
      wait_ = #(TimingData_man.tEHTZ) 1'hZ;
3092
end
3093
 
3094
always @(G_N) begin
3095
   if (G_N == `LOW && CE_N == `LOW && W_N==`HIGH) begin
3096
      if (ConfigReg_man.isSynchronous) begin
3097
         wait_ = #(TimingData_man.tGLTV) ConfigReg_man.isWaitPolActiveHigh;
3098
      end else begin
3099
         wait_ = #(TimingData_man.tGLTV) !ConfigReg_man.isWaitPolActiveHigh;
3100
      end
3101
   end
3102
   else begin if (G_N == `HIGH )
3103
      wait_ = #(TimingData_man.tGHTZ) 1'hZ;
3104
 
3105
      disable Burst_man.pollingBurst;
3106
   end
3107
end
3108
 
3109
 
3110
 
3111
 
3112
always @(isWait) begin
3113
 
3114
   if ((CE_N == `LOW) && (G_N == `LOW) && ConfigReg_man.isSynchronous ) begin
3115
 
3116
      if (CLK) begin
3117
         if (isWait == `LOW ) begin
3118
            if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3119
            else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3120
         end else begin
3121
            if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3122
            else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3123
         end
3124
 
3125
      end else
3126
 
3127
         fork
3128
 
3129
            begin
3130
               @(posedge(CLK))
3131
 
3132
                  if (isWait == `LOW) begin
3133
                     if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3134
                     else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3135
                  end else begin
3136
                     if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3137
                     else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3138
                  end
3139
            end
3140
 
3141
 
3142
            begin
3143
 
3144
               @(isWait)
3145
 
3146
                  if (CLK) begin
3147
                     if (isWait == `LOW) begin
3148
                        if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3149
                        else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3150
                     end else begin
3151
                        if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3152
                        else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3153
                     end
3154
 
3155
                  end
3156
            end
3157
 
3158
         join
3159
 
3160
 
3161
   end else if  (G_N == `HIGH && isWait == `HIGH && W_N==`HIGH)
3162
      $display("%t --- WARNING --- WAIT should be deasserted but OE# is not yet LOW. Please check the timings!",$time);
3163
end
3164
 
3165
 
3166
endmodule
3167
 
3168
 
3169
 
3170
// *********************************
3171
//
3172
// Burst module :
3173
//
3174
//      manage the Read Burst operation
3175
//
3176
// *********************************
3177
 
3178
module BurstModule(address, data, ISWAIT, CLK, CLOCK, L_N, G_N, W_N, Info);
3179
   input [`ADDRBUS_range] address;
3180
   output [`WORD_range]   data;
3181
   reg [`WORD_range]      data;
3182
 
3183
   input                  CLK;
3184
   input                  CLOCK;
3185
   input                  L_N;
3186
   input                  G_N;
3187
   input                  W_N;
3188
   output                 ISWAIT;
3189
   input                  Info;
3190
 
3191
   reg [`ADDRBUS_range]   Start_address, Sync_address,new_address;
3192
   reg                    EnableBurst, isValidData, IsNowWait, endSingleSynchronous;
3193
   reg [2:0]               incLSBaddress, incMSBaddress, temp_address;
3194
 
3195
   wire                   isSingleSynchronous = (Read_man.Mode != `ReadArray_bus) ? `TRUE : `FALSE;
3196
 
3197
   integer                WaitState,nWait,nRead,xLatency;
3198
//aggiunta per il calcolo degli nwait
3199
   integer                boundary,offset;
3200
   reg                    firstEOWL;
3201
 
3202
initial begin                 // constructor sequence
3203
   Start_address = `ADDRBUS_dim'h000000;
3204
   EnableBurst = `FALSE;
3205
   endSingleSynchronous = `FALSE;
3206
   data = 16'hZZ;
3207
   nWait = 0;
3208
   IsNowWait = `FALSE;
3209
   isValidData = `FALSE;
3210
   xLatency=0;
3211
   nRead=0;
3212
   WaitState=0;
3213
   firstEOWL=0;
3214
end
3215
 
3216
always @(G_N) if (G_N==`TRUE) begin
3217
   IsNowWait = `FALSE;
3218
   isValidData = `FALSE;
3219
   EnableBurst = `FALSE;
3220
   endSingleSynchronous = `FALSE;
3221
   data = 16'hZZ;
3222
   nWait = 0;
3223
   xLatency=0;
3224
   nRead=0;
3225
   WaitState=0;
3226
   firstEOWL=0;
3227
end
3228
 
3229
 
3230
always @(isValidData) begin
3231
   case (isValidData)
3232
 
3233
      1: if (!ConfigReg_man.isWaitBeforeActive) begin
3234
 
3235
         IsNowWait = `TRUE;
3236
      end
3237
 
3238
      0: begin if (!ConfigReg_man.isWaitBeforeActive)
3239
         IsNowWait = `FALSE;
3240
 
3241
 
3242
      end
3243
 
3244
   endcase
3245
end
3246
 
3247
 
3248
assign ISWAIT = (IsNowWait) ? `TRUE : `FALSE;
3249
 
3250
 
3251
always @(negedge L_N) if(W_N==`HIGH) begin  : pollingBurst
3252
   fork  : pollingBurst
3253
 
3254
      begin: L_lacthing
3255
         @(posedge L_N) if (ConfigReg_man.isSynchronous) begin
3256
            #1;
3257
            Start_address = address;
3258
            Sync_address =  address;
3259
            firstEOWL=0;
3260
            disable K_lacthing;
3261
 
3262
            @(posedge CLK) begin
3263
 
3264
               case(ConfigReg_man.BurstLength)
3265
 
3266
                  0: begin
3267
                     boundary =16;
3268
                     offset = address[3:0];
3269
                  end
3270
 
3271
                  16:begin
3272
                     boundary =16;
3273
                     offset = address[3:0];
3274
                  end
3275
 
3276
                  8: begin
3277
                     boundary =8;
3278
                     offset = address[2:0];
3279
                  end
3280
 
3281
 
3282
                  4:begin
3283
                     boundary =4;
3284
                     offset = address[1:0];
3285
                  end
3286
               endcase
3287
 
3288
               xLatency = ConfigReg_man.Xlatency;
3289
               WaitState = xLatency - (boundary - offset);
3290
 
3291
               if (WaitState < 0) WaitState =0;
3292
               nWait = 0;
3293
               EnableBurst = `TRUE;
3294
               data = 16'hXX;
3295
               nRead = 0;
3296
               isValidData = `FALSE;
3297
               endSingleSynchronous=`FALSE;
3298
               disable pollingBurst;
3299
            end
3300
         end
3301
         else EnableBurst = `FALSE;
3302
      end
3303
 
3304
      begin: K_lacthing
3305
         @(posedge CLK) if (ConfigReg_man.isSynchronous && L_N==`LOW) begin
3306
            #1;
3307
            Start_address = address;
3308
            Sync_address =  address;
3309
            firstEOWL=0;
3310
            disable L_lacthing;
3311
 
3312
            @(posedge CLK) begin
3313
 
3314
               case(ConfigReg_man.BurstLength)
3315
 
3316
                  0: begin
3317
                     boundary =16;
3318
                     offset = address[3:0];
3319
                  end
3320
 
3321
                  16:begin
3322
                     boundary =16;
3323
                     offset = address[3:0];
3324
                  end
3325
 
3326
                  8: begin
3327
                     boundary =8;
3328
                     offset = address[2:0];
3329
                  end
3330
 
3331
 
3332
                  4:begin
3333
                     boundary =4;
3334
                     offset = address[1:0];
3335
                  end
3336
               endcase
3337
 
3338
               xLatency = ConfigReg_man.Xlatency;
3339
               WaitState = xLatency - (boundary - offset); //
3340
               if (WaitState < 0) WaitState =0;
3341
               nWait = 0;
3342
               EnableBurst = `TRUE;
3343
               data = 16'hXX;
3344
               nRead = 0;
3345
               isValidData = `FALSE;
3346
               endSingleSynchronous=`FALSE;
3347
               disable pollingBurst;
3348
            end
3349
         end
3350
         else EnableBurst = `FALSE;
3351
      end
3352
   join
3353
   $display("  %t address=%h",$time,Start_address);
3354
end
3355
 
3356
 
3357
always @(posedge (CLK)) if(G_N==`LOW) begin
3358
   if (EnableBurst) begin
3359
      if (xLatency == 2 && ConfigReg_man.isWaitBeforeActive)
3360
         IsNowWait = `TRUE;
3361
 
3362
      if (xLatency == 1) begin
3363
         isValidData = `TRUE;
3364
         if (offset == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
3365
            IsNowWait = `FALSE;
3366
 
3367
         end
3368
 
3369
 
3370
      end
3371
      if (xLatency) xLatency = xLatency - 1; //vuol dire se xLatency e' >1 o diverso da zero????
3372
   end
3373
end
3374
 
3375
always @(nRead) begin
3376
   if (isSingleSynchronous && nRead>=1) begin //End of SingleBurstRead???
3377
      endSingleSynchronous=`TRUE;
3378
      isValidData = `FALSE;
3379
   end
3380
   if((offset + nRead) == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
3381
      IsNowWait = `FALSE;
3382
 
3383
   end
3384
 
3385
end
3386
 
3387
 
3388
always @(CLK) begin
3389
 
3390
   if (EnableBurst) begin
3391
 
3392
      if (!xLatency) begin // burst is ongoing(after xLatency)
3393
 
3394
         if (!G_N) begin
3395
 
3396
            if (nWait || endSingleSynchronous) data = `DATABUS_dim'hXXXX; //Wait State;
3397
 
3398
            else begin  // Read is Possible!
3399
               // -- \\ 
3400
               case (Read_man.Mode)
3401
                  `ReadArray_bus       : begin
3402
                     data = Memory_man.Get(Sync_address);
3403
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: Memory[%h]=%h\n",$time,Sync_address,data);
3404
                  end
3405
                  `ReadCFI_bus         : begin
3406
                     data = CFIquery_man.Get(Sync_address);
3407
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: CFIMemory[%h]=%h\n",$time,Sync_address,data);
3408
                  end
3409
                  `ReadSignature_bus   : begin
3410
                     data = Signature_man.Get(Sync_address);
3411
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: Electronic Signature[%h]=%h\n",$time,Sync_address,data);
3412
                  end
3413
                  `ReadStatusReg_bus   : begin
3414
                     data = SR_man.SR;
3415
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: StatusRegister: %b\n",$time,data[`BYTE_range]);
3416
                  end
3417
                  default             : $display("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
3418
               endcase
3419
               // -- \\     
3420
            end
3421
            if((CLK)) begin
3422
 
3423
               if (!nWait) // Wait State??? if no calculate next address
3424
               begin
3425
 
3426
                  new_address = Sync_address + 1;
3427
                  nRead = nRead + 1;
3428
 
3429
               end
3430
               if (!isSingleSynchronous) begin
3431
 
3432
                  // Calcultate Address for Sequential and Wrap Burst 
3433
                  if ((ConfigReg_man.BurstLength != 5'd00) && ConfigReg_man.isWrapBurst)  begin
3434
                     case (ConfigReg_man.BurstLength_bit)
3435
                        3'd2: new_address = {Sync_address[`ADDRBUS_dim - 1 : 2], new_address[1:0] };
3436
                        3'd3: new_address = {Sync_address[`ADDRBUS_dim - 1 : 3], new_address[2:0] };
3437
                        3'd4: new_address = {Sync_address[`ADDRBUS_dim - 1 : 4], new_address[3:0] };
3438
                     endcase
3439
                  end
3440
 
3441
                  // Calculate Next Wait State
3442
                  if (ConfigReg_man.isNoWrapBurst || (ConfigReg_man.BurstLength == 5'd00) )  //Calculate WAIT STATE
3443
                     if ((new_address[3:0]==4'd0) && (Sync_address[3:0] == 4'd15)) begin
3444
 
3445
                        if(!ConfigReg_man.isWaitBeforeActive)  begin
3446
 
3447
                           if (nWait<WaitState && !firstEOWL) begin
3448
                              nWait = nWait+1; // Another Wait State???
3449
                              isValidData = `FALSE;
3450
                           end else begin
3451
                              nWait = 0;       // end of wait state
3452
                              Sync_address = new_address;
3453
                              isValidData = `TRUE;
3454
                              firstEOWL =1;
3455
 
3456
                           end
3457
 
3458
                        end else begin
3459
                           if (nWait<WaitState-1 && !firstEOWL ) begin
3460
                              nWait = nWait+1; // Another Wait State???
3461
                              IsNowWait = `FALSE;
3462
                           end else begin
3463
                              nWait = 0;       // end of wait state
3464
                              Sync_address = new_address;
3465
                              IsNowWait = `TRUE;
3466
                              firstEOWL =1;
3467
 
3468
                           end
3469
                        end
3470
 
3471
                     end
3472
                  if (!nWait)
3473
                     if ((nRead<ConfigReg_man.BurstLength) || (ConfigReg_man.BurstLength==5'd00) // Read Data is Over Burst Lenght???
3474
                         && !endSingleSynchronous) // end of SingleSinchronous Burst Read ???
3475
                        Sync_address = new_address;
3476
               end  // !isSyn
3477
 
3478
            end //aggiunta
3479
 
3480
         end //G_N
3481
      end // XLatency
3482
   end //Enable Burst
3483
end
3484
 
3485
 
3486
endmodule // end Burst Module 
3487
 
3488
 
3489
// Erase Manager
3490
// manage the erase functionality
3491
 
3492
module BlankCheckModule(address, data, progVoltOK, progHighVoltOK,Info);
3493
 
3494
   input [`WORD_range] data;
3495
   input [`ADDRBUS_range] address;
3496
   input                  progVoltOK, progHighVoltOK;
3497
   input                  Info;
3498
 
3499
   event                  ErrorCheckEvent, CompleteEvent;
3500
 
3501
   reg [`BYTE_range]      Status;
3502
   reg [`ADDRBUS_range]   hold_address;
3503
   reg [`BLOCKADDR_range] hold_block;
3504
 
3505
 
3506
   reg                    Busy;
3507
   integer                i;
3508
   time                   startTime, delayTime, Erase_time;
3509
 
3510
initial begin                   // constructor sequence             
3511
   Busy       = `FALSE;
3512
   Erase_time = `MainBlockErase_time; //modificato
3513
   delayTime  =  Erase_time;
3514
end
3515
 
3516
always @(progVoltOK,progHighVoltOK,address) begin
3517
   if (progHighVoltOK)
3518
      if (BankLib_man.isMainBlock(address)) Erase_time=`FastMainBlockErase_time;
3519
      else  Erase_time=`FastParameterBlockErase_time;
3520
   else
3521
      if (BankLib_man.isMainBlock(address)) Erase_time=`MainBlockErase_time;
3522
      else  Erase_time=`ParameterBlockErase_time;
3523
end
3524
 
3525
 
3526
function IsBusy;                // boolean function primitive       
3527
   input obbl;                     // all functions require a parameter
3528
   IsBusy = Busy;                // return Boolean value             
3529
endfunction
3530
 
3531
 
3532
 
3533
// *********************
3534
//
3535
// Task checkConfirm :
3536
//    check confirm code
3537
//
3538
// *********************
3539
 
3540
task checkConfirm;
3541
 
3542
   output  [`BYTE_range] outStatus;
3543
 
3544
   reg [`BYTE_range]     outStatus;
3545
 
3546
   begin
3547
 
3548
      if (data == `BLNKCHKconfirm_cmd) outStatus = `NoError_msg;
3549
 
3550
      else outStatus = `WrongBlankCheckConfirm_msg;
3551
   end
3552
endtask
3553
 
3554
 
3555
 
3556
 
3557
 
3558
// ****************
3559
//
3560
// Task Blank Check
3561
// 
3562
// ****************
3563
 
3564
task BlankCheck;
3565
 
3566
   output  [`BYTE_range] outStatus;
3567
 
3568
   reg [`BYTE_range]     outStatus;
3569
 
3570
   integer               hold_block;
3571
   reg [`ADDRBUS_range]  hold_address;
3572
 
3573
   begin
3574
      hold_address = address;
3575
      hold_block = BankLib_man.getBlock(hold_address);
3576
 
3577
      if (BankLib_man.isMainBlock(address)) begin
3578
         // Main Block
3579
         delayTime = `MainBlankCheck_time;
3580
      end else  // Parameter Block
3581
         -> ErrorCheckEvent;
3582
      disable Operation;
3583
 
3584
      fork
3585
         begin: Operation
3586
            Busy = `TRUE;
3587
            startTime = $time;
3588
            -> ErrorCheckEvent;
3589
            #delayTime
3590
               Memory_man.BlockBlankCheck(hold_block, Status);
3591
            -> CompleteEvent;
3592
         end
3593
         @CompleteEvent
3594
            disable Operation;
3595
      join
3596
      outStatus = Status;
3597
      Busy = `FALSE;
3598
   end
3599
endtask
3600
 
3601
 
3602
 
3603
always @(ErrorCheckEvent) begin
3604
   Status = `NoError_msg;
3605
   if (!progVoltOK)
3606
      Status = `InvVDD_msg;
3607
   if (BankLib_man.isParameterBlock(address)) begin
3608
 
3609
      Status = `WrongBlankCheckBlock;
3610
      $display("parameter block");
3611
   end
3612
   if (Status != `NoError_msg) begin
3613
      ->CompleteEvent;
3614
      disable ErrorCheck;
3615
   end
3616
   else
3617
      fork : ErrorCheck
3618
         @(negedge progVoltOK) Status = `InvVDD_msg;
3619
         @(Status) -> CompleteEvent;
3620
         @(CompleteEvent) disable ErrorCheck;
3621
      join
3622
end
3623
 
3624
endmodule  //end module Erase
3625
 
3626
 
3627
// *********************************
3628
//
3629
// Program Buffer module :
3630
//
3631
//      program buffer functionality
3632
//
3633
// *********************************
3634
 
3635
module ProgramBufferModule(address,data,voltOK,Info);
3636
   input [`ADDRBUS_range] address;
3637
   input [`WORD_range]    data;
3638
   input                  voltOK, Info;
3639
   event                  ErrorCheckEvent, CompleteEvent, WatchAddressEvent;
3640
   reg [`BYTE_range]      Status;
3641
   reg [`DATABUS_dim-1:0] Count;
3642
 
3643
   reg [`WORD_range]      bufferData [`ProgramBuffer_range];
3644
 
3645
   reg [`ADDRBUS_range]   AddressLatched, startAddress,newAddress;
3646
   reg                    Busy, Suspended, Empty;
3647
   time                   startTime, delayTime;
3648
   integer                i;
3649
 
3650
initial begin                 // constructor sequence             
3651
   Busy = `FALSE;
3652
   Suspended = `FALSE;
3653
   Empty = `TRUE;
3654
   delayTime = `ProgramBuffer_time;
3655
end
3656
 
3657
function IsBusy;              // boolean function primitive       
3658
   input obbl;               // all functions require a parameter
3659
   IsBusy = Busy;              // return Boolean value             
3660
endfunction
3661
 
3662
function IsSuspended;         // boolean function primitive       
3663
   input obbl;               // all functions require a parameter
3664
   IsSuspended = Suspended;    // return Boolean value             
3665
endfunction
3666
 
3667
function IsAddrSuspended;     // boolean function primitive       
3668
   input [`ADDRBUS_range] addr;
3669
   IsAddrSuspended = (Suspended && ((addr >= startAddress) && (addr < (startAddress + Count))));
3670
endfunction
3671
 
3672
 
3673
function [`DATABUS_dim-1:0] GetCount;
3674
   input                  required;
3675
   GetCount = Count;
3676
endfunction
3677
 
3678
task SetCount;                // sets the number of writes
3679
   output [`BYTE_range] outStatus;
3680
   reg [`BYTE_range]    outStatus;
3681
   begin
3682
      outStatus = `NoError_msg;
3683
      AddressLatched = address;
3684
      Count = data + 1;
3685
 
3686
 
3687
      if (Count > `ProgramBuffer_dim)
3688
         outStatus = `BuffSize_msg;
3689
      else if (BankLib_man.getBlock(AddressLatched) != BankLib_man.getBlock(AddressLatched + Count - 1))
3690
 
3691
         outStatus = `BlkBuffer_msg;
3692
      else
3693
         -> WatchAddressEvent;
3694
   end
3695
endtask
3696
 
3697
task Suspend;
3698
   output [`BYTE_range] outStatus;
3699
   reg [`BYTE_range]    outStatus;
3700
   begin
3701
      delayTime = delayTime - ($time - startTime);
3702
      #`ProgramSuspendLatency_time;
3703
      outStatus = `NoError_msg;
3704
      Status = `Suspend_msg;
3705
      Suspended = `TRUE;
3706
      -> CompleteEvent;
3707
   end
3708
endtask
3709
 
3710
task Resume;
3711
   output [`BYTE_range] Status;
3712
   begin
3713
      Suspended = `FALSE;
3714
      Program(Status);
3715
end
3716
endtask
3717
 
3718
task Load;
3719
   output [`BYTE_range] Status;
3720
   begin
3721
      if (Empty) begin
3722
         startAddress = address;
3723
         if (Info) $display("[%t]  Buffer start address: %h",$time,startAddress);
3724
         Empty = `FALSE;
3725
 
3726
      end
3727
      bufferData[address[`ProgramBuffer_addrRange]] = data;
3728
 
3729
   end
3730
endtask
3731
 
3732
task Program;
3733
   output [`BYTE_range] outStatus;
3734
   reg [`BYTE_range]    outStatus;
3735
begin
3736
 
3737
   fork
3738
      begin : Operation
3739
         Busy = `TRUE;
3740
 
3741
         startTime = $time;
3742
         -> ErrorCheckEvent;
3743
         -> WatchAddressEvent; // disable address watch
3744
         #delayTime
3745
            for (i = startAddress;i < ( Count + startAddress); i = i + 1) begin
3746
               Memory_man.Program(bufferData[i[`ProgramBuffer_addrRange]],i,Status);
3747
 
3748
end
3749
         delayTime = `ProgramBuffer_time;
3750
         -> CompleteEvent;
3751
      end
3752
      @CompleteEvent
3753
         disable Operation;
3754
 
3755
   join
3756
   if(!Suspended)
3757
      for (i = 0; i < `ProgramBuffer_dim; i = i + 1) begin
3758
         bufferData[i] =16'hFFFF;
3759
      end
3760
   Empty = `TRUE;
3761
   outStatus = Status;
3762
   Busy = `FALSE;
3763
end
3764
endtask
3765
 
3766
always @(ErrorCheckEvent) begin
3767
   Status = `NoError_msg;
3768
   if (BlockLock_man.IsLocked(AddressLatched))
3769
      Status = `BlockLock_msg;
3770
   else if (Suspended)
3771
      Status = `SuspAcc_msg;
3772
   else if (!voltOK)
3773
      Status = `InvVDD_msg;
3774
 
3775
   if (Status != `NoError_msg)
3776
      ->CompleteEvent;
3777
   else
3778
      fork : ErrorCheck
3779
         @(negedge voltOK) Status = `InvVDD_msg;
3780
         @(Status) -> CompleteEvent;
3781
         @(CompleteEvent) disable ErrorCheck;
3782
      join
3783
end
3784
 
3785
always @(WatchAddressEvent) fork : AddressWatch
3786
   while (`TRUE)
3787
      @address
3788
         if (BankLib_man.getBlock(address) != BankLib_man.getBlock(AddressLatched)) begin
3789
            Status = `AddrTog_msg;
3790
            -> CompleteEvent;
3791
         end
3792
   @WatchAddressEvent
3793
      disable AddressWatch;
3794
join
3795
 
3796
endmodule

powered by: WebSVN 2.1.0

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