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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [x28fxxxp30.v] - Blame information for rev 867

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

Line No. Rev Author Line
1 655 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 "cfi_flash_def.h"
22
`include "cfi_flash_CUIcommandData.h"
23
`include "cfi_flash_data.h"
24
`include "cfi_flash_UserData.h"
25
`include "cfi_flash_BankLib.h"
26
`include "cfi_flash_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
      for (i = 0; i < `MEMORY_dim; i = i + 1)  memory[i] = {16{`HIGH}};    // Memory Init
1475
 
1476
      if (`FILENAME_mem !== "") begin
1477
         $readmemh(`FILENAME_mem, memory);
1478
 
1479
         if (Info) $display("[%t] Load Memory from file: %s",$time, `FILENAME_mem);
1480
         else if (Info) $display("[%t] Warning: File: %s not found",$time, `FILENAME_mem);
1481
      end
1482
   end
1483
endtask
1484
 
1485
 
1486
function [`WORD_range] Get;
1487
   input [`ADDRBUS_range] address;
1488
   Get = memory[address];
1489
endfunction
1490
 
1491
 
1492
function IsSuspended;
1493
   input [`ADDRBUS_range] address;
1494
   IsSuspended = Program_man.IsAddrSuspended(address) || Erase_man.IsAddrSuspended(address) || ProgramBuffer_man.IsAddrSuspended(address);
1495
endfunction
1496
 
1497
function IsBlockSuspended;
1498
   input [`ADDRBUS_range] address;
1499
   IsBlockSuspended = Program_man.IsBlockSuspended(address) || Erase_man.IsBlockSuspended(address);
1500
endfunction
1501
 
1502
 
1503
task Program;
1504
   input [`WORD_range] data;
1505
   input [`ADDRBUS_range] address;
1506
   output [`BYTE_range]   Status;
1507
begin
1508
   Status = `NoError_msg;
1509
   memory[address] = memory[address] & data;
1510
   if (memory[address] != data) Status = `PreProg_msg;
1511
end
1512
endtask
1513
 
1514
task EraseBlock;
1515
 
1516
   input [`INTEGER] block;
1517
 
1518
   output [`BYTE_range] ErrFlag;
1519
 
1520
   reg [`ADDRBUS_range] start_address;
1521
   reg [`ADDRBUS_range] end_address;
1522
   reg [`ADDRBUS_range] address;
1523
 
1524
 
1525
   begin
1526
      ErrFlag        = `NoError_msg;
1527
      start_address  = BankLib_man.getBlockAddress(block);
1528
      end_address    = BankLib_man.BlockBoundaryEndAddr[block];
1529
 
1530
      if (start_address > end_address)
1531
      begin
1532
         address = start_address;
1533
         start_address = end_address;
1534
         end_address = address;
1535
      end
1536
 
1537
 
1538
      for (address = start_address; address <= end_address; address = address + 1)
1539
         memory[address] = `WORDNP;
1540
 
1541
   end
1542
endtask
1543
 
1544
task BlockBlankCheck;
1545
 
1546
   input [`INTEGER] block;
1547
 
1548
   output [`BYTE_range] ErrFlag;
1549
 
1550
   reg [`ADDRBUS_range] start_address;
1551
   reg [`ADDRBUS_range] end_address;
1552
   reg [`ADDRBUS_range] address;
1553
 
1554
 
1555
   begin
1556
      ErrFlag = `NoError_msg;
1557
      start_address = BankLib_man.BlockBoundaryStartAddr[block];
1558
      end_address   = BankLib_man.BlockBoundaryEndAddr[block];
1559
 
1560
      if (start_address > end_address)
1561
      begin
1562
         address = start_address;
1563
         start_address = end_address;
1564
         end_address = address;
1565
      end
1566
 
1567
      ErrFlag = `NoError_msg;
1568
      address = start_address;
1569
      while (memory[address] == `WORDNP && address <= end_address )
1570
         address = address + 1;
1571
      if (memory[address] != `WORDNP)
1572
         ErrFlag = `BlankCheckFailed_msg;
1573
 
1574
   end
1575
endtask
1576
 
1577
 
1578
 
1579
endmodule //end MemoryModule 
1580
 
1581
 
1582
// ***************************************
1583
//
1584
// Output Buffer :
1585
//
1586
//      manage the communication between 
1587
//      the memory and the output data bus
1588
//
1589
// ***************************************
1590
 
1591
module OutputBufferModule(DataInput, DataInputBurst, DataOutput, OutputEnable);
1592
   input [`WORD_range] DataInput;
1593
   input [`WORD_range] DataInputBurst;
1594
   output [`WORD_range] DataOutput;
1595
   input                OutputEnable;
1596
   reg [`WORD_range]    DataOutput;
1597
   time                 timeDataV, timeDataX, timeDataZ;
1598
 
1599
initial begin
1600
   timeDataV=0;
1601
   timeDataX=0;
1602
   timeDataZ=0;
1603
   SetZ(0);
1604
end
1605
 
1606
task SetValid;
1607
   input [63:0] delayTime;
1608
   begin
1609
 
1610
      if ((delayTime+$time > timeDataV) || (timeDataV < $time)) begin
1611
         timeDataV = delayTime + $time;
1612
 
1613
 
1614
         disable waitValid;
1615
 
1616
 
1617
         disable goValid;
1618
 
1619
      end
1620
   end
1621
endtask
1622
 
1623
always
1624
   fork
1625
      begin:  goValid
1626
 
1627
         #(timeDataV - $time)
1628
         if (OutputEnable == 1'b0) begin
1629
 
1630
            if (ConfigReg_man.isASynchronous) DataOutput = DataInput;
1631
            else DataOutput = DataInputBurst;
1632
         end
1633
 
1634
      end // goValid
1635
      begin: waitValid
1636
         wait (`FALSE);
1637
      end
1638
   join
1639
 
1640
task SetX;
1641
   input [63:0] delayTime;
1642
   begin
1643
      if ((delayTime+$time < timeDataX) || (timeDataX < $time)) begin
1644
         timeDataX = delayTime + $time;
1645
         disable waitX;
1646
 
1647
 
1648
      end
1649
   end
1650
endtask
1651
 
1652
always fork
1653
   begin : goX
1654
      #(timeDataX - $time) if ((OutputEnable == `LOW) || (timeDataZ > timeDataX))
1655
         DataOutput = 16'hX;
1656
   end // goX
1657
   begin: waitX
1658
      wait (`FALSE);
1659
   end
1660
join
1661
 
1662
task SetZ;
1663
   input [63:0] delayTime;
1664
   begin
1665
      if ((delayTime+$time < timeDataZ) || (timeDataZ < $time)) begin
1666
         timeDataZ = delayTime + $time;
1667
         disable waitZ;
1668
         if (timeDataZ < timeDataV)
1669
            disable goValid;
1670
         if (timeDataZ < timeDataX)
1671
            disable goX;
1672
      end
1673
   end
1674
endtask
1675
 
1676
always begin: waitZ
1677
   #(timeDataZ - $time) DataOutput = 16'hZ;
1678
   wait (`FALSE);
1679
end
1680
 
1681
endmodule
1682
 
1683
 
1684
// *********************************
1685
//
1686
// Program module :
1687
//
1688
//      manage the program operation
1689
//
1690
// *********************************
1691
 
1692
module ProgramModule(address,data, progVoltOK, progHighVoltOK, Info);
1693
   input [`WORD_range] data;
1694
   input [`ADDRBUS_range] address;
1695
   input                  progVoltOK,progHighVoltOK;
1696
   input                  Info;
1697
   event                  ErrorCheckEvent, CompleteEvent;
1698
   reg [`BYTE_range]      Status;
1699
   reg [`WORD_range]      hold_data;
1700
   reg [`ADDRBUS_range]   hold_address;
1701
   reg                    Busy, Suspended;
1702
 
1703
   integer                i;
1704
   time                   startTime, delayTime, WordProgram_time;
1705
 
1706
initial begin                 // constructor sequence
1707
   Busy = `FALSE;
1708
   Suspended = `FALSE;
1709
   WordProgram_time = `WordProgram_time;
1710
   delayTime = WordProgram_time;
1711
end
1712
 
1713
always @(progHighVoltOK) begin
1714
   if (progHighVoltOK) WordProgram_time=`FastWordProgram_time;
1715
   else WordProgram_time=`WordProgram_time;
1716
end
1717
 
1718
function IsBusy;              // boolean function primitive
1719
   input obbl;                   // all functions require a parameter
1720
   IsBusy = Busy;              // return Boolean value
1721
endfunction
1722
 
1723
function IsSuspended;         // boolean function primitive
1724
   input obbl;                   // all functions require a parameter
1725
   IsSuspended = Suspended;    // return Boolean value 
1726
endfunction
1727
 
1728
function IsAddrSuspended;     // boolean function primitive       
1729
   input [`ADDRBUS_range] addr;
1730
   IsAddrSuspended = (Suspended && (addr == hold_address));
1731
endfunction
1732
 
1733
function IsBlockSuspended;    // return true if block is suspended
1734
   input [`ADDRBUS_range] addr; begin
1735
      IsBlockSuspended  = (Suspended && (BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/)));
1736
   end
1737
endfunction
1738
 
1739
 
1740
task Suspend;
1741
   output [`BYTE_range] suspErrFlag;
1742
   reg [`BYTE_range]    suspErrFlag;
1743
   begin
1744
      delayTime = delayTime - ($time - startTime);
1745
      #`ProgramSuspendLatency_time suspErrFlag = `NoError_msg;
1746
      Status = `Suspend_msg;
1747
      Suspended = `TRUE;
1748
      -> CompleteEvent;
1749
   end
1750
endtask
1751
 
1752
task Resume;
1753
   output [`BYTE_range] ErrFlag;
1754
   begin
1755
      Suspended = `FALSE;
1756
      Program(ErrFlag);
1757
end
1758
endtask
1759
 
1760
task Program;
1761
   output [`BYTE_range] outErrFlag;
1762
   reg [`BYTE_range]    outErrFlag;
1763
begin
1764
   if (delayTime == WordProgram_time) begin
1765
      hold_data = data;
1766
      hold_address = address;
1767
   end
1768
   fork
1769
      begin : Operation
1770
         Busy = `TRUE;
1771
         startTime = $time;
1772
         -> ErrorCheckEvent;
1773
         #delayTime Memory_man.Program(hold_data,hold_address,Status);
1774
delayTime = `WordProgram_time;
1775
-> CompleteEvent;
1776
end
1777
      @CompleteEvent disable Operation;
1778
   join
1779
   outErrFlag = Status;
1780
   Busy = `FALSE;
1781
end
1782
endtask
1783
 
1784
always @(ErrorCheckEvent) begin
1785
   Status = `NoError_msg;
1786
   if (BlockLock_man.IsLocked(hold_address))
1787
      Status = `BlockLock_msg;
1788
   else
1789
      if (Memory_man.IsSuspended(hold_address))
1790
         Status = `SuspAcc_msg;
1791
      else if (!progVoltOK)
1792
         Status = `InvVDD_msg;
1793
 
1794
   if (Status != `NoError_msg) ->CompleteEvent;
1795
   else
1796
      fork : ErrorCheck
1797
         @(negedge progVoltOK) Status = `InvVDD_msg;
1798
         @(Status) -> CompleteEvent;
1799
         @(CompleteEvent) disable ErrorCheck;
1800
      join
1801
end
1802
 
1803
endmodule // end PrograModule 
1804
 
1805
 
1806
// *********************************
1807
//
1808
// Buffer Ehnanced Program module :
1809
//
1810
//      program buffer functionality
1811
//
1812
// *********************************
1813
 
1814
module BuffEnhancedFactProgramModule(address, data, progVoltOK, progHighVoltOK, Info);
1815
   input [`ADDRBUS_range] address;
1816
   input [`WORD_range]    data;
1817
   input                  progVoltOK, progHighVoltOK, Info;
1818
 
1819
   event                  ErrorCheckEvent,ErrorCheckEvent_inVerify, CompleteEvent, WatchAddressEvent;
1820
   reg [`BYTE_range]      Status;
1821
   reg [`WORD_range]      hold_data, hold_StartBlock;
1822
   reg [`ADDRBUS_range]   hold_address, startAddress;
1823
   reg [`WORD_range]      bufferData [`BuffEnhProgramBuffer_range];
1824
 
1825
   reg                    Busy;
1826
   time                   Program_time;
1827
   integer                i,Len;
1828
 
1829
initial begin                 // constructor sequence             
1830
   Busy = `FALSE;
1831
   Status = `NoError_msg;
1832
   Program_time = `WordProgram_time;
1833
   EmptyBuffer;
1834
end
1835
 
1836
task EmptyBuffer;
1837
   begin
1838
      for (i = 0; i < `BuffEnhProgramBuffer_dim; i = i + 1)
1839
         bufferData[i] = 16'hFFFF;
1840
      Len=0;
1841
   end
1842
endtask
1843
 
1844
function IsBusy;              // boolean function primitive       
1845
   input obbl;               // all functions require a parameter
1846
   IsBusy = Busy;              // return Boolean value             
1847
endfunction
1848
 
1849
task Setup;
1850
   output [`BYTE_range] outStatus;
1851
   begin
1852
      Status           = `NoError_msg;
1853
      Len              =0;
1854
      startAddress     = address;
1855
      hold_address     = address;
1856
 
1857
      hold_StartBlock  = BankLib_man.getBlock(address);
1858
      -> ErrorCheckEvent;
1859
      #0 outStatus=Status;
1860
      if (Status == `NoError_msg) begin
1861
         if (Info) $display("[%t]  Enhanced Factory Program -> Setup Phase",$time);
1862
         if (Info) $display("[%t]  Enhanced Factory Program: Start address: %h",$time,startAddress);
1863
         #`EnhBuffProgramSetupPhase_time;
1864
         Busy = `TRUE;
1865
      end
1866
   end
1867
endtask
1868
 
1869
task Exit;
1870
   output [`BYTE_range] outStatus;
1871
   begin
1872
      Busy = `FALSE;
1873
      outStatus = Status;
1874
      if (Info) $display("[%t]  Enhanced Factory Program -> Exit Phase",$time);
1875
      if (Len != `BuffEnhProgramBuffer_dim)
1876
         $display("[%t] Warning --- The buffer must be completely filled for programming to occur",$time);
1877
   end
1878
endtask
1879
 
1880
task Load;
1881
   output [`BYTE_range] outStatus;
1882
   begin
1883
      if (BankLib_man.getBlock(address) != hold_StartBlock) Status = `ExitPHASE_BEFP_msg;
1884
      else begin
1885
         bufferData[Len] = data;
1886
         if (Info) $display("[%t]  Enhanced Factory Program -> Load: data[%d]=%h ",$time,Len,bufferData[Len]);
1887
         Len = Len + 1;
1888
         if (Len == `BuffEnhProgramBuffer_dim) Status = `ProgramPHASE_BEFP_msg;
1889
 
1890
      end
1891
      outStatus = Status;
1892
   end
1893
endtask
1894
 
1895
task Program;
1896
   output [`BYTE_range] outStatus;
1897
   reg [`BYTE_range]    outStatus;
1898
begin
1899
   fork
1900
      begin : Operation
1901
         if (Info) $display("[%t]  Enhanced Factory Program {Program Phase}",$time);
1902
         #`EnhBuffProgram_time
1903
 
1904
            if (Info) $display("[%t]  Enhanced Factory Program {End of Program Phase}",$time);
1905
         for (i = startAddress;i < (`BuffEnhProgramBuffer_dim + startAddress); i = i + 1) begin
1906
            Memory_man.Program(bufferData[i - startAddress],i,Status);
1907
end
1908
         -> CompleteEvent;      //end of program
1909
      end
1910
      @CompleteEvent begin
1911
         disable Operation;
1912
      end
1913
   join
1914
   if (Status == `ProgramPHASE_BEFP_msg) begin //prova
1915
      Status = `NoError_msg;
1916
   end
1917
   outStatus = Status;
1918
end
1919
endtask
1920
 
1921
always @(ErrorCheckEvent) begin
1922
   Status = `NoError_msg;
1923
   if (BlockLock_man.IsLocked(hold_address))
1924
      Status = `BlockLock_msg;
1925
   else if (!progVoltOK)
1926
      Status = `InvVDD_msg;
1927
   else if (!progHighVoltOK)
1928
      Status =  `InvVPP_msg;
1929
   if (Status != `NoError_msg)
1930
      ->CompleteEvent;
1931
   else
1932
      fork : ErrorCheck
1933
         @(negedge progVoltOK) Status = `InvVDD_msg;
1934
         @(negedge progHighVoltOK) Status = `InvVPP_msg;
1935
         @(CompleteEvent) disable ErrorCheck;
1936
      join
1937
end
1938
 
1939
 
1940
 
1941
endmodule
1942
 
1943
// ******************************************
1944
//
1945
// Protect Register module :
1946
//
1947
//      operations on the protection register
1948
//
1949
// ******************************************
1950
 
1951
module ProtectRegModule(address, data, voltOK, Info);
1952
   input [`ADDRBUS_range] address;
1953
   input [`DATABUS_range] data;
1954
   input                  voltOK, Info;
1955
   reg [`WORD_range]      RegisterMemory[`REG_dim - 1 :0];
1956
   reg [`BYTE_range]      Status;
1957
   reg                    Busy;
1958
   reg [`ADDRBUS_range]   AddressLatched;
1959
   event                  ErrorCheckEvent, CompleteEvent;
1960
   integer                i;
1961
   reg [`ADDRBUS_range]   hold_addr;
1962
   reg [`DATABUS_range]   hold_data;
1963
 
1964
 
1965
initial begin                         // constructor sequence             
1966
   Busy = `FALSE;
1967
   RegisterMemory[0] = `PRL_default;
1968
   for (i = 1; i < `REG_dim; i = i + 1) begin
1969
      RegisterMemory[i] = `WORDNP;
1970
   end
1971
end
1972
 
1973
 
1974
function IsBusy;              // boolean function primitive       
1975
   input required;               // all functions require a parameter
1976
   IsBusy = Busy;              // return Boolean value             
1977
endfunction
1978
 
1979
function UDNisLocked;            // boolean function primitive
1980
   input obbl;                           // input is required
1981
   if ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UDNprotect_bit) == `UDNprotect_bit)
1982
      UDNisLocked = `TRUE;
1983
   else
1984
      UDNisLocked = `FALSE;
1985
endfunction
1986
 
1987
function UPisLocked;            // boolean function primitive
1988
   input obbl;                   // input is required
1989
   UPisLocked = ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UPprotect_bit) == `UPprotect_bit) ? `TRUE : `FALSE;
1990
endfunction
1991
 
1992
function isUDNaddress;
1993
   input [`ADDRBUS_range] address;
1994
   if ((address >= `UDNREGSTART_addr) && ( address <= `UDNREGEND_addr)) // Check UDN register Address Bound 
1995
      isUDNaddress = `TRUE;
1996
   else isUDNaddress = `FALSE;
1997
endfunction
1998
 
1999
function isUPaddress;
2000
   input [`ADDRBUS_range] address;
2001
   if ((address >= `UPREGSTART_addr) && (address <= `UPREGEND_addr)) // Check UP register Address Bound 
2002
      isUPaddress = `TRUE;
2003
   else isUPaddress = `FALSE;
2004
endfunction
2005
 
2006
function [`BYTE_range] ExtIndexPRL;            // bit index of PRL register 
2007
   input [`ADDRBUS_range] addr;
2008
   ExtIndexPRL=(addr - `ExtREGSTART_regionaddr) / `ExtREG_regiondim;
2009
endfunction
2010
 
2011
function isExtLocked;            // boolean function primitive
2012
   input [`ADDRBUS_range] addr;                   // input is required
2013
   reg [`BYTE_range]      bitIndex;
2014
   begin
2015
      bitIndex = ExtIndexPRL(addr);  // protect bit index of Extended Protection Register Memory
2016
      isExtLocked = !(RegisterMemory[(`ExtPROTECTREGLOCK_addr - `REGSTART_addr)][bitIndex]);
2017
   end
2018
endfunction
2019
 
2020
function isExtValidAddress;
2021
   input [`ADDRBUS_range] address;
2022
   if ((address >= `ExtREGSTART_regionaddr) && (address <= `ExtREGEND_regionaddr) ) // Check ExtRegister Address Bound 
2023
      isExtValidAddress = `TRUE;
2024
   else isExtValidAddress = `FALSE;
2025
endfunction
2026
 
2027
task Program;
2028
   output [`BYTE_range] outStatus;
2029
   reg [`BYTE_range]    outStatus;
2030
begin
2031
   Busy = `TRUE;
2032
   hold_addr = address[`REG_addrbitRange];
2033
   hold_data = data;
2034
   if (Info) $write("[%t]  OTP Program Memory[%h]=%h\n",$time,hold_addr,data);
2035
   fork
2036
      begin : Operation
2037
         -> ErrorCheckEvent;
2038
         #`WordProgram_time RegisterMemory[hold_addr - `REGSTART_addr] = RegisterMemory[hold_addr - `REGSTART_addr] & hold_data;
2039
         -> CompleteEvent;
2040
      end
2041
      @CompleteEvent disable Operation;
2042
   join
2043
   outStatus = Status;
2044
   Busy = `FALSE;
2045
end
2046
endtask
2047
 
2048
always @(ErrorCheckEvent) begin
2049
   Status = `NoError_msg;
2050
   if (( address < `REGSTART_addr) || ( address > `REGEND_addr)) // Check Address Bound 
2051
      Status = `AddrRange_msg;
2052
   else if ( isUDNaddress(address) && UDNisLocked(1'bX) )
2053
      Status = `UDNlock_msg;
2054
   else if ((isUPaddress(address) && UPisLocked(1'bX)))
2055
      Status = `UPlock_msg;
2056
   else if ( isExtValidAddress(hold_addr) & isExtLocked(hold_addr) )
2057
      Status = `ExtREGLock_msg;
2058
 
2059
   else if (Kernel.Suspended)
2060
      Status = `SuspCmd_msg;
2061
   else if (!voltOK)
2062
      Status = `InvVDD_msg;
2063
 
2064
   if (Status != `NoError_msg)
2065
      ->CompleteEvent;
2066
   else
2067
      fork : ErrorCheck
2068
         @(negedge voltOK) Status = `InvVDD_msg;
2069
         @(Status) -> CompleteEvent;
2070
         @(CompleteEvent) disable ErrorCheck;
2071
      join
2072
end
2073
endmodule //end ProtectRegModule
2074
 
2075
 
2076
// Read Manager
2077
// Manage the read operation
2078
 
2079
module ReadModule(dataOutput,address,voltOK,Info);
2080
   output [`WORD_range] dataOutput;
2081
   input [`ADDRBUS_range] address;
2082
   input                  voltOK;
2083
   input                  Info;
2084
   reg [`WORD_range]      dataOutput, regRead;
2085
   reg [1:0]               Mode, oldMode;
2086
   reg [`BYTE_range]      Status;
2087
 
2088
   integer                i;
2089
 
2090
initial begin
2091
   regRead = 0;
2092
   Mode = `ReadArray_bus;
2093
   oldMode = `ReadArray_bus;
2094
   dataOutput = `DATABUS_dim'hzzzz;
2095
end
2096
 
2097
task SetMode;
2098
   input [1:0] newMode;
2099
   output [`BYTE_range] Status;
2100
   begin
2101
      Status = `NoError_msg;
2102
      if (Info && (newMode!=Mode)) begin
2103
         case (newMode)
2104
            `ReadArray_bus        : $display ("[%t]  Device now in Read Array mode ", $time);
2105
            `ReadCFI_bus          : $display ("[%t]  Device now in Read CFI mode ", $time);
2106
            `ReadSignature_bus    : $display ("[%t]  Device now in Read Electronic Signature Mode ", $time);
2107
            `ReadStatusReg_bus    : $display ("[%t]  Device now in Read Status Register Mode ", $time);
2108
            default               : $display ("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
2109
         endcase
2110
 
2111
         oldMode=Mode;
2112
         Mode = newMode;
2113
      end
2114
   end
2115
endtask
2116
 
2117
 
2118
always @Kernel.ResetEvent begin
2119
   Mode = `ReadArray_bus;
2120
end
2121
 
2122
always @(negedge Kernel.Ready) begin   // Configure according to status register
2123
   Mode = `ReadStatusReg_bus;
2124
end
2125
 
2126
always @Kernel.ReadEvent begin          // Main execution of a read is based on an event
2127
 
2128
 
2129
   case (Mode)
2130
      `ReadArray_bus       : begin
2131
         dataOutput = Memory_man.Get(address);
2132
         if (Info) $display("[%t]  Data Read result: memory[%h]=%h", $time,address,dataOutput);
2133
      end
2134
      `ReadCFI_bus         : begin
2135
         dataOutput = CFIquery_man.Get(address);
2136
         if (Info) $display("[%t]  Data Read result: CFI_memory[%h]=%h", $time,address,dataOutput);
2137
      end
2138
      `ReadSignature_bus   :  begin
2139
         dataOutput = Signature_man.Get(address);
2140
         if (Info) $display("[%t]  Read Device Identifier(addr=%h) :%h", $time,address,dataOutput);
2141
      end
2142
 
2143
      `ReadStatusReg_bus   : begin
2144
         dataOutput = SR_man.SR;
2145
         if (Info) $display("[%t]  Read Status Register: %b", $time,dataOutput[`BYTE_range]);
2146
      end
2147
 
2148
      default              : $display("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
2149
   endcase
2150
   if ((Mode == `ReadArray_bus) && (Memory_man.IsSuspended(address) == `TRUE)) begin
2151
      dataOutput = 16'hXX;
2152
      Kernel.SetWarning(`RD_cmd,8'hXX,`SuspAcc_msg);
2153
   end
2154
end
2155
 
2156
endmodule
2157
// end Module Read
2158
 
2159
 
2160
// *************************************************
2161
//
2162
// Status Register module :
2163
//
2164
//      implements the Status Register of the device
2165
//
2166
// *************************************************
2167
 
2168
module StatusRegModule(Info);
2169
   input Info;
2170
 
2171
 
2172
   reg   EraseStatus, ProgramStatus,
2173
         VpenStatus, BlockProtectionStatus, BW_status;
2174
 
2175
   reg [`BYTE_range] Status;
2176
 
2177
   wire [7:0]         SR = {Kernel.Ready,                        // bit 7 
2178
                           Erase_man.IsSuspended(1'bX),         // bit 6
2179
                           EraseStatus,                         // bit 5
2180
                           ProgramStatus,                       // bit 4
2181
                           VpenStatus,                          // bit 3
2182
                           Program_man.IsSuspended(1'bX) ||  ProgramBuffer_man.IsSuspended(1'bX),       // bit 2
2183
                           BlockProtectionStatus,               // bit 1
2184
                           BW_status};                          // bit 0
2185
   wire [7:0]         SR_Info =  SR;
2186
 
2187
 
2188
 
2189
//-----------------
2190
// Init
2191
//-----------------
2192
 
2193
initial begin
2194
   EraseStatus=1'b0;
2195
   ProgramStatus=1'b0;
2196
   VpenStatus=1'b0;
2197
   BlockProtectionStatus=1'b0;
2198
   BW_status=1'b0;
2199
end
2200
 
2201
 
2202
always @(SR_Info) if (Kernel.Ready!=1'bZ)
2203
   if (Info) $display("[%t]  Status Register Update: %b",$time, SR_Info);
2204
 
2205
always @(Kernel.ResetEvent) begin
2206
   Clear(Status);
2207
end
2208
 
2209
 
2210
always @(Kernel.Ready,ProtectReg_man.Busy, BuffEnhancedFactProgram_man.Busy)
2211
begin
2212
   if (Kernel.Ready)
2213
      BW_status = `FALSE;
2214
   else
2215
      if (BuffEnhancedFactProgram_man.Busy == `TRUE)
2216
         BW_status=`TRUE;
2217
 
2218
end
2219
 
2220
always @(Kernel.ErrorEvent) begin //Update status register bits upon specific errors
2221
   #0;
2222
   case(Kernel.GetError(1'bX))
2223
      `InvVDD_msg       : begin VpenStatus = `TRUE; end
2224
      `InvVPP_msg       : begin VpenStatus = `TRUE; end
2225
      `BlockLock_msg    : begin BlockProtectionStatus = `TRUE;  end
2226
      `UDNlock_msg      : begin ProgramStatus = `TRUE; end
2227
      `UPlock_msg       : begin ProgramStatus = `TRUE; end
2228
 
2229
      `ProtRegAddrRange_msg : begin
2230
         BlockProtectionStatus = `TRUE;
2231
      end
2232
      `ExtREGLock_msg   : begin
2233
         BlockProtectionStatus = `TRUE;
2234
      end
2235
 
2236
      `CmdSeq_msg       : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2237
      `AddrRange_msg    : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2238
      `AddrTog_msg      : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
2239
      `PreProg_msg      : begin ProgramStatus = `TRUE; end
2240
      `WrongEraseConfirm_msg : begin ProgramStatus = `TRUE; EraseStatus   = `TRUE; end
2241
      `WrongBlankCheckConfirm_msg : begin
2242
         ProgramStatus = `TRUE; EraseStatus   = `TRUE;
2243
      end
2244
      `BlankCheckFailed_msg : begin
2245
         EraseStatus   = `TRUE;
2246
      end
2247
      `LeastAddr0:        begin
2248
         ProgramStatus = `TRUE;
2249
      end
2250
 
2251
 
2252
   endcase
2253
   case(Kernel.GetCmd(4'h1))
2254
      `PG_cmd           : begin ProgramStatus = `TRUE; end
2255
      `PRREG_cmd        : begin ProgramStatus = `TRUE; end
2256
      `PB_cmd           : begin ProgramStatus = `TRUE; end
2257
      `BLKEE_cmd        : begin EraseStatus = `TRUE; end
2258
      `BL_cmd           : if (Kernel.GetCmd(4'h2) == `BLconfirm_cmd) ProgramStatus = `TRUE;
2259
      `BUL_cmd          : if (Kernel.GetCmd(4'h2) ==`BULconfirm_cmd) EraseStatus   = `TRUE;
2260
      `BLD_cmd          : if (Kernel.GetCmd(4'h2) ==`BLDconfirm_cmd) ProgramStatus = `TRUE;
2261
      `BuffEnhProgram_cmd :
2262
         if (Kernel.GetCmd(4'h2) == `BuffEnhProgramCfrm_cmd)
2263
            ProgramStatus = `TRUE;
2264
 
2265
   endcase
2266
end
2267
 
2268
task Clear;
2269
   output [`BYTE_range] Status;
2270
   begin
2271
      Status = `NoError_msg;
2272
      EraseStatus = `FALSE;
2273
      ProgramStatus = `FALSE;
2274
      VpenStatus  = `FALSE;
2275
      BlockProtectionStatus   = `FALSE;
2276
      BW_status = `FALSE;
2277
   end
2278
endtask
2279
 
2280
endmodule  // end module status register
2281
 
2282
 
2283
// *************
2284
//
2285
// Kernel Module 
2286
//
2287
// *************
2288
 
2289
module KernelModule(VDD, VDDQ, VPP, Info);
2290
   input [`Voltage_range] VDD, VDDQ, VPP;
2291
   input                  Info;
2292
   event                  CUIcommandEvent, VerifyEvent, ErrorEvent, CompleteEvent, ResetEvent, ReadEvent, ProgramCompleteEvent, EraseCompleteEvent;
2293
 
2294
   reg                    voltOK, progVoltOK, eraseVoltOK, lockVoltOK, ioVoltOK, lockOverrideOK;
2295
   reg                    progHighVoltOK, eraseHighVoltOK;
2296
   reg [8'hFF:0]           CommandDecode1;
2297
   reg [16'hFFFF:0]        CommandDecode2;
2298
   reg [7:0]               lastStatus, lastCmd1, lastCmd2;
2299
 
2300
// Device Status
2301
 
2302
   wire                   Ready = (!Program_man.Busy && !ProgramBuffer_man.Busy  && !BuffEnhancedFactProgram_man.Busy
2303
                                   && !Erase_man.Busy && !ProtectReg_man.Busy && !BlankCheck_man.Busy);
2304
 
2305
 
2306
   wire                   Suspended = Program_man.Suspended || Erase_man.Suspended || ProgramBuffer_man.Suspended;
2307
 
2308
initial begin                 // constructor sequence
2309
   CommandDecode1 = 8'h00;         // initialize decode success status variables
2310
   CommandDecode2 = 16'h0000;
2311
end
2312
 
2313
 
2314
always @(voltOK) begin
2315
   if (!voltOK) begin
2316
      $display("[%t]  !ERROR: Invalid VDD Voltage.",$time);
2317
      -> ErrorEvent;
2318
   end
2319
   else
2320
      $display("[%t]  VDD Voltage is OK",$time);
2321
end
2322
 
2323
always @(ioVoltOK) begin
2324
   if (!ioVoltOK) begin
2325
      $display("[%t]  !ERROR: Invalid VDDQ I/O voltage.", $time);
2326
      -> ErrorEvent;
2327
   end
2328
   else
2329
      $display("[%t]  VDDQ Voltage is OK",$time);
2330
 
2331
end
2332
 
2333
always @(VDD) begin
2334
   if ((VDD < `VDDmin) | (VDD > `VDDmax))
2335
      voltOK = `FALSE;
2336
   else
2337
      voltOK = `TRUE;
2338
end
2339
 
2340
 
2341
always @(VDDQ) begin  // check i/o voltage constraints
2342
   if ((VDDQ >= `VDDQmin) && (VDDQ <= `VDDQmax))
2343
      ioVoltOK = `TRUE;
2344
   else
2345
      ioVoltOK = `FALSE;
2346
end
2347
 
2348
always @(VPP) begin // program/erase/lock
2349
   if ((VPP>=`VPPmin && VPP<=`VPPmax))  begin
2350
      progVoltOK  = `TRUE;
2351
      eraseVoltOK = `TRUE;
2352
      lockVoltOK  = `TRUE;
2353
      progHighVoltOK  = `FALSE;
2354
      eraseHighVoltOK = `FALSE;
2355
   end
2356
   else if ((VPP>=`VPPHmin) && (VPP<=`VPPHmax)) begin
2357
      progVoltOK  = `TRUE;
2358
      eraseVoltOK = `TRUE;
2359
      lockVoltOK  = `TRUE;
2360
      progHighVoltOK  = `TRUE;
2361
      eraseHighVoltOK = `TRUE;
2362
   end
2363
   else begin
2364
      progVoltOK  = `FALSE;
2365
      eraseVoltOK = `FALSE;
2366
      lockVoltOK  = `FALSE;
2367
      progHighVoltOK  = `FALSE;
2368
      eraseHighVoltOK = `FALSE;
2369
   end
2370
end
2371
 
2372
 
2373
function [7:0] GetError;
2374
   input required;
2375
   GetError = lastStatus;
2376
endfunction
2377
 
2378
function [7:0] GetCmd;
2379
   input commandNum;
2380
   GetCmd = (commandNum == 1) ? lastCmd1 : lastCmd2;
2381
endfunction
2382
 
2383
task SetWarning;
2384
   input [7:0] Cmd1, Cmd2;
2385
   input [7:0] Status;
2386
   begin
2387
      Report(Cmd1,Cmd2,Status);
2388
      lastStatus = Status;
2389
   end
2390
endtask
2391
 
2392
task SetError;
2393
   input [7:0] Cmd1, Cmd2;
2394
   input [7:0] ErrFlag;
2395
   begin
2396
      SetWarning(Cmd1,Cmd2,ErrFlag);
2397
      -> ErrorEvent; // Only errors set error event
2398
   end
2399
endtask
2400
 
2401
 
2402
task Report;
2403
   input [7:0] Cmd1, Cmd2;
2404
   input [7:0] Status;
2405
   begin
2406
      lastStatus = Status;
2407
      lastCmd1 = Cmd1;
2408
      lastCmd2 = Cmd2;
2409
      if ((lastStatus != `NoError_msg) || Info) begin //Display error .
2410
         $write("[%t] ",$time);
2411
         case(Status)
2412
            `NoError_msg         : begin $write(" Command Completion Successful "); end
2413
            `CmdSeq_msg         : begin $write(" !Error:   [Invalid Command]\n Sequence Command Unknown"); -> ErrorEvent; end
2414
            `SuspCmd_msg        : begin $write(" !Error:   [Invalid Command]\n Cannot execute this command during suspend"); -> ErrorEvent; end
2415
            `SuspAcc_msg        : begin $write(" !Error:   [Invalid Command]\n Cannot access this address due to suspend"); -> ErrorEvent; end
2416
            `SignAddrRange_msg  : begin $write(" !Error:   [Invalid Address]\n Signature Address out of range"); end
2417
            `CFIAddrRange_msg   : begin $write(" !Error:   [Invalid Address]\n CFI Address out of range"); end
2418
            `AddrRange_msg      : begin $write(" !Error:   [Invalid Address]\n Address out of range"); -> ErrorEvent; end
2419
            `AddrTog_msg        : begin $write(" !Error:   [Program Buffer]\n Cannot change block address during command sequence"); -> ErrorEvent; end
2420
            `BuffSize_msg       : begin $write(" !Error:   [Program Buffer]\n Buffer size is too large (Max Size is %d) ",`ProgramBuffer_dim); -> ErrorEvent; end
2421
            `InvVDD_msg         : begin $write(" !Error:   [Invalid Supply]\n Voltage Supply must be: VDD>VDDmin and VDD<VDDmax "); -> ErrorEvent; end
2422
            `InvVPP_msg         : begin $write(" !Error:   [Invalid Program Supply]\n Program Supply Voltage must be: VPP>VPPHmin and VPP<VPPHmax for this Operation"); -> ErrorEvent; end
2423
            `ByteToggle_msg     : begin $write(" !Error:   [BYTE_N Toggled]\n Cannot toggle BYTE_N while busy"); -> ErrorEvent; end
2424
            `PreProg_msg        : begin $write(" !Error:   [Program Failure]\n Program Failure due to cell failure"); -> ErrorEvent; end
2425
            `UDNlock_msg        : begin $write(" !Error:   [Program Failure]\n Unique Device Number Register is locked"); -> ErrorEvent; end
2426
            `UPlock_msg         : begin $write(" !Error:   [Program Failure]\n User Programmable Register is locked"); -> ErrorEvent; end
2427
            `ExtREGLock_msg     : begin $write(" !Error:   [Program Failure]\n Extended User Programmable OTP is locked"); -> ErrorEvent; end
2428
            `NoUnLock_msg       : begin $write(" #Warning: [Locked Down Warning]\n  Invalid UnLock Block command in Locked-Down Block"); end
2429
            `SuspAccWarn_msg    : begin $write(" #Warning: [Invalid Access]\n  It isn't possible access this address due to suspend"); end
2430
            `BlockLock_msg      : begin $write(" !Error:   [Locked Error]\n Cannot complete operation when the block is locked "); -> ErrorEvent; end
2431
            `BlkBuffer_msg      : begin $write(" !Error: [Program Buffer]  Program Buffer cannot cross block boundary"); end
2432
            `AddrCFI_msg        : begin $write(" #Warning: [Invalid CFI Address]\n CFI Address out of range"); end
2433
            `NoBusy_msg         : begin $write(" #Warning: [NO Busy]\n Device is not Busy"); end
2434
            `NoSusp_msg         : begin $write(" #Warning: [NO Suspend]\n Nothing previus suspend command"); end
2435
            `Suspend_msg        : begin $write("  Suspend of "); end
2436
            `WrongEraseConfirm_msg : begin
2437
               $write(" !Error: [Wrong Erase Confirm Code ");
2438
               -> ErrorEvent;
2439
            end
2440
            `LeastAddr0         : begin
2441
               $write(" !Error:   [Program Failure]\n Least Significative bit [%2d downto 0] of Start Address must be 0",`ProgramBuffer_addrDim-1);
2442
               -> ErrorEvent;
2443
            end
2444
 
2445
            `WrongBlankCheckConfirm_msg : begin
2446
               $write(" !Error: [Confirm Code] Wrong Blank Check Confirm Code ");
2447
               -> ErrorEvent;
2448
            end
2449
 
2450
            `WrongBlankCheckBlock:  begin
2451
               $write(" !Error:   [Blank Check Failure]\n The block must be a main block");
2452
               -> ErrorEvent;
2453
            end
2454
 
2455
            `BlankCheckFailed_msg : begin $write(" !Error:   [Blank Check]\n Blank Check Failed ");
2456
               -> ErrorEvent;
2457
            end
2458
 
2459
            default             : begin $write(" !ERROR: [Unknown error]\n Flag=%h, cmd1=%hh, cmd2=%hh",Status,Cmd1,Cmd2); -> ErrorEvent; end
2460
         endcase
2461
         case (Cmd1)
2462
            16'hXX              : $display(" !Error: [General Error}\n Error not defined");
2463
            `RD_cmd             : $display(" { Read Array }");
2464
            `RSR_cmd            : $display(" { Read Status Register }");
2465
            `RSIG_cmd           : $display(" { Read Electronic Signature }");
2466
            `RCFI_cmd           : $display(" { Read CFI }");
2467
            `PG_cmd             : $display(" { Program }");
2468
            `BuffEnhProgram_cmd : $display(" { Buffer Enhanced Factory Program }");
2469
 
2470
            `SCR_cmd | `BL_cmd | `BUL_cmd |  `BLD_cmd
2471
               : begin
2472
                  if (Cmd2 == `SCRconfirm_cmd) $display(" { Set Configuration Register }");
2473
                  if (Cmd2 == `BLconfirm_cmd)  $display(" { Block Lock }");
2474
                  if (Cmd2 == `BULconfirm_cmd) $display(" { Block UnLock }");
2475
                  if (Cmd2 == `BLDconfirm_cmd) $display(" { Block Lock-Down }");
2476
               end
2477
            `PER_cmd          : $display(" { Program/Erase Resume }");
2478
            `PRREG_cmd        : $display(" { Protection Register Command }");
2479
            `BLKEE_cmd        : $display(" { Block Erase }");
2480
            `BLNKCHK_cmd      : $display(" { Blank Check }");
2481
            `CLRSR_cmd        : $display(" { Clear Status Register }");
2482
            `PES_cmd          : $display(" { Program/Erase Suspend }");
2483
            `PB_cmd           : $display(" { Write to Buffer and Program }");
2484
            default           : $display(" {unknown command:  %hh}", Cmd1);
2485
         endcase
2486
      end
2487
   end
2488
endtask
2489
 
2490
task CheckTime;
2491
   input [8*6:1] tstr;
2492
   input [31:0]  tdiff, tprev;
2493
 
2494
   begin
2495
      if ($time - tprev < tdiff) begin
2496
         $display ("[%t]  !ERROR: %0s timing constraint violation:  %0d-%0d < %0dns ", $time, tstr, $time, tprev, tdiff);
2497
         -> ErrorEvent;
2498
      end
2499
   end
2500
endtask
2501
 
2502
endmodule // end module Kernel 
2503
 
2504
 
2505
 
2506
 
2507
 
2508
module x28fxxxp30(A, DQ, W_N, G_N, E_N, L_N, K, WAIT, WP_N, RP_N, VDD, VDDQ, VPP, Info);
2509
 
2510
// Signal Bus
2511
   input [`ADDRBUS_dim-1:0] A;           // Address Bus 
2512
   inout [`DATABUS_dim-1:0] DQ;          // Data I/0 Bus
2513
// Control Signal
2514
   input                    W_N;                           // Write Enable 
2515
   input                    G_N;                           // Output Enable
2516
   input                    E_N;                           // Chip Enable
2517
   input                    L_N;                           // Latch Enable
2518
   input                    K;                             // Clock
2519
   input                    WP_N;                          // Write Protect
2520
   input                    RP_N;                          // Reset/Power-Down
2521
 
2522
// Voltage signal rappresentad by integer Vector which correspond to millivolts
2523
   input [`Voltage_range]   VDD;           // Supply Voltage
2524
   input [`Voltage_range]   VDDQ;          // Input/Output Supply Voltage
2525
   input [`Voltage_range]   VPP;           // Optional Supply Voltage for fast Program & Erase
2526
 
2527
// Others Signal       
2528
   output                   WAIT;                          // Wait
2529
   reg                      wait_;
2530
assign WAIT = wait_;
2531
   input                    Info;                           // Enable/Disable Information of the operation in the memory 
2532
   wire                     CLK;
2533
assign CLK = (K ~^ ConfigReg_man.isRisingClockEdge);
2534
   reg                      CLOCK;
2535
// === Internal Signal ===
2536
// Chip Enable 
2537
   wire                     CE_N = E_N & Kernel.voltOK & RP_N;
2538
 
2539
// Output Enable 
2540
   wire                     OE_N = G_N | CE_N | !Kernel.ioVoltOK | !RP_N;
2541
// Write Enable 
2542
   wire                     WE_N = W_N | CE_N;
2543
 
2544
// Latch Enable
2545
 
2546
   wire                     LE_N = L_N | CE_N;
2547
// === Bus Latch ===
2548
// Data Bus
2549
   wire [`DATABUS_dim-1:0]  DataBusIn;
2550
   wire [`DATABUS_dim-1:0]  DataBurst;
2551
 
2552
// read burst is in wait state
2553
   wire                     isWait;
2554
 
2555
// Address Bus
2556
   reg [`ADDRBUS_dim - 1:0] AddrBusIn;
2557
 
2558
// Status
2559
//aggiunti stati buffenha...e blank....
2560
   reg [`BYTE_range]        KernelStatus, ReadStatus, EraseStatus, ProgramStatus, BuffEnhancedProgramStatus,
2561
                            LockStatus, ConfigStatus, BufferStatus,BlankCheckStatus,ProgramBufferStatus,
2562
                            SuspendStatus, ResumeStatus, ClearSRStatus, ProtectRegStatus;
2563
 
2564
 
2565
   reg [`BYTE_range]        status=`Free_pes;
2566
 
2567
//address latching in read operation
2568
always @(negedge LE_N) if (W_N==`HIGH)  begin
2569
   if (KernelStatus == `READY && ConfigReg_man.isASynchronous)
2570
      @(posedge LE_N) begin
2571
         if (L_N)
2572
 
2573
            AddrBusIn = A;                // AddressBus has been Latched
2574
 
2575
      end
2576
end
2577
 
2578
always @(negedge LE_N) if (W_N==`HIGH) begin :latching_a
2579
   if (KernelStatus == `READY) begin
2580
      if(ConfigReg_man.isSynchronous)
2581
         fork
2582
 
2583
            begin : L_Address
2584
 
2585
               @(posedge LE_N) if (L_N) begin
2586
 
2587
                  AddrBusIn = A;                // AddressBus has been Latched
2588
                  disable K_Address;
2589
 
2590
               end
2591
            end
2592
 
2593
            begin : K_Address
2594
 
2595
               @(posedge CLK) begin
2596
 
2597
                  AddrBusIn = A;                // AddressBus has been Latched
2598
                  disable L_Address;
2599
               end
2600
            end
2601
         join
2602
 
2603
   end
2604
end
2605
 
2606
 
2607
always @(negedge WE_N) begin
2608
   if (KernelStatus==`READY)
2609
      @(posedge WE_N) begin
2610
         if(OE_N==`HIGH)
2611
            AddrBusIn = A;                // AddressBus has been Latched
2612
 
2613
      end
2614
end
2615
 
2616
   integer i;
2617
   integer n_block;
2618
 
2619
// Wait Driver 
2620
   time    timeWaitDriver,timeWaitDriverZ;
2621
 
2622
   reg     PB_init=0;
2623
   reg     P_init=0;
2624
   reg     BP_init=0;
2625
   reg     Prog_init=0;
2626
 
2627
always @(PB_init,P_init,BP_init) begin
2628
   Prog_init=(PB_init ||P_init || BP_init);
2629
end
2630
 
2631
   wire [`BYTE_range] AccessTime;
2632
 
2633
// ****************
2634
// 
2635
// Modules Istances
2636
//
2637
// ****************
2638
 
2639
DataErrorModule   DataError_man();              // Check for errors on UserData.h
2640
 
2641
CUIdecoder1       ReadArray_Command  (DQ[`LOW_range], "Read Array                         ", `RD_cmd, (Kernel.Ready && !Prog_init),        Info),
2642
   ReadSR_Command     (DQ[`LOW_range], "Read Status Register               ", `RSR_cmd, !Prog_init,        Info),
2643
   ReadSign_Command   (DQ[`LOW_range], "Read Electronic Signature          ", `RSIG_cmd, (Kernel.Ready && !Prog_init),       Info),
2644
   ReadCFI_Command    (DQ[`LOW_range], "Read CFI                           ", `RCFI_cmd, (Kernel.Ready && !Prog_init),      Info),
2645
   Program_Command    (DQ[`LOW_range], "Program                            ", `PG_cmd,   (Kernel.Ready && !Prog_init),      Info),
2646
 
2647
   ProgramBuffer_Command    (DQ[`LOW_range], "Program Buffer                     ", `PB_cmd, (Kernel.Ready && !Prog_init),        Info),
2648
   ProgramReg_Command (DQ[`LOW_range], "Protection Register Program        ", `PRREG_cmd,  (Kernel.Ready && !Prog_init),    Info),
2649
   Resume_Command     (DQ[`LOW_range], "Resume                             ", `PER_cmd,  (Kernel.Ready && Kernel.Suspended),      Info),
2650
   BlockErase_Command  (DQ[`LOW_range], "Block Erase                        ", `BLKEE_cmd,(Kernel.Ready && !Prog_init),      Info),
2651
   ClearSR_Command    (DQ[`LOW_range], "Clear Status Register              ", `CLRSR_cmd, (Kernel.Ready && !Prog_init),     Info),
2652
 
2653
   BlankCheck_Command  (DQ[`LOW_range], "Blank Check                        ", `BLNKCHK_cmd, (Kernel.Ready && !Prog_init),   Info),
2654
   BuffEnhactoryProgram_Command (DQ[`LOW_range], "Buffer Enh.Factory Program  [Setup]", `BuffEnhProgram_cmd,(Kernel.Ready && !Prog_init), Info);
2655
 
2656
 
2657
CUIdecoder_Busy1  Suspend_Command    (DQ[`LOW_range], "Suspend ",   `PES_cmd, !Kernel.Ready, Info);
2658
 
2659
CUIdecoder2        BlockLock_Command (DQ[`LOW_range], "Block Lock                 ", `BL_cmd,       `BLconfirm_cmd, (Kernel.Ready && !Prog_init),    Info),
2660
   BlockUnlock_Command (DQ[`LOW_range], "Block UnLock               ", `BUL_cmd,      `BULconfirm_cmd, (Kernel.Ready && !Prog_init),   Info),
2661
   BlockLockDown_Command (DQ[`LOW_range], "Block Lock-Down            ", `BLD_cmd,      `BLDconfirm_cmd, (Kernel.Ready && !Prog_init),   Info),
2662
   SetConfigReg_Command (DQ[`LOW_range], "Set Configuration Register ", `SCR_cmd,      `SCRconfirm_cmd, (Kernel.Ready && !Prog_init),   Info);
2663
 
2664
KernelModule            Kernel            (VDD, VDDQ, VPP, Info);
2665
ReadModule              Read_man          (DataBusIn, AddrBusIn, Kernel.ioVoltOK, Info);
2666
OutputBufferModule      OutputBuffer_man  (DataBusIn, DataBurst, DQ, OE_N);
2667
StatusRegModule         SR_man            (Info);
2668
MemoryModule            Memory_man        (Info);
2669
ProgramModule           Program_man       (AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
2670
 
2671
BuffEnhancedFactProgramModule BuffEnhancedFactProgram_man(AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
2672
ProtectRegModule        ProtectReg_man    (AddrBusIn, DQ, Kernel.progVoltOK, Info);
2673
EraseModule             Erase_man         (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
2674
 
2675
 
2676
BlankCheckModule        BlankCheck_man    (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
2677
 
2678
BlockLockModule         BlockLock_man     (AddrBusIn, WP_N, RP_N, Info);
2679
ProgramBufferModule   ProgramBuffer_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
2680
SignatureModule         Signature_man     ();        // , `FALSE);
2681
CFIqueryModule          CFIquery_man      ();        // , `TRUE);
2682
ConfigRegModule         ConfigReg_man     (AddrBusIn,Info);                              // implements the Configuration Register
2683
BurstModule             Burst_man         (AddrBusIn, DataBurst, isWait, CLK, CLOCK, L_N, G_N,W_N, Info);
2684
 
2685
BankLib                 BankLib_man       ();
2686
TimingDataModule        TimingData_man    ();
2687
TimingLibModule         TimingLib_man     (A,DQ,W_N,G_N,E_N,L_N,WP_N,K,VPP);
2688
 
2689
initial begin
2690
 
2691
   $timeformat(-9, 0, " ns", 12);               // Format time displays to screen
2692
   -> Kernel.ResetEvent;                        // Reset Device 
2693
   KernelStatus = `BUSY;                        // Device is Busy
2694
   $display ("[%t]  --- Device is Busy  (start up time) --- ", $time);
2695
   #(TimingData_man.tVDHPH) KernelStatus = `READY;              // End of Start-Up Time
2696
   $display ("[%t]  --- Device is Ready (end of start-up time) --- ", $time);
2697
 
2698
   AddrBusIn = `ADDRBUS_dim'hZ;
2699
 
2700
   wait_ = 1'hZ;
2701
   CLOCK = 1'b0;
2702
end
2703
 
2704
// Recognize command input
2705
always @(negedge WE_N) begin
2706
   if (KernelStatus==`READY)
2707
      @(posedge WE_N) begin
2708
 
2709
         -> Kernel.CUIcommandEvent;               // new command has been written into Kernel.
2710
 
2711
      end
2712
end
2713
 
2714
// Check error
2715
always @(Kernel.CUIcommandEvent) begin : Timeout
2716
   #3
2717
      -> Kernel.ErrorEvent;
2718
   disable Verify;
2719
end
2720
 
2721
// Verify command issued 
2722
always @(Kernel.CUIcommandEvent) begin : Verify
2723
   @(Kernel.VerifyEvent)
2724
 
2725
      disable Timeout;
2726
end
2727
 
2728
// Default to Read Array command
2729
always @(negedge OE_N) begin
2730
   if (OE_N == `LOW && (ConfigReg_man.isASynchronous)) begin
2731
      if (L_N==0) AddrBusIn=A;
2732
      #1
2733
         -> Kernel.ReadEvent;
2734
   end
2735
end
2736
 
2737
// Page Read
2738
always @(A) begin
2739
 
2740
   if ((OE_N == `LOW) &&  (A !== `ADDRBUS_dim'hZ) && (A !== `ADDRBUS_dim'hx) && (ConfigReg_man.isASynchronous))  begin
2741
      AddrBusIn = A;
2742
      #0 -> Kernel.ReadEvent;
2743
 
2744
   end
2745
end
2746
 
2747
 
2748
// Reset the Kernel
2749
always @(negedge RP_N) begin
2750
   -> Kernel.ResetEvent;
2751
   if (Info) $display ("[%t]  Device has been reset ", $time);
2752
   KernelStatus = `BUSY;
2753
   @(posedge RP_N) KernelStatus = `READY;
2754
end
2755
 
2756
// ----- Recognize Command Input -----
2757
always @(Kernel.CommandDecode1[`RD_cmd]) if (KernelStatus==`READY)  begin                        // Read Array
2758
   Read_man.SetMode(`ReadArray_bus, ReadStatus);
2759
   Kernel.Report(`RD_cmd, 8'hXX, ReadStatus);
2760
   #1 -> Kernel.CompleteEvent;
2761
end
2762
 
2763
always @(Kernel.CommandDecode1[`RSR_cmd]) if (KernelStatus==`READY) begin                       // Read Status Register
2764
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2765
   Kernel.Report(`RSR_cmd, 8'hXX, ReadStatus);
2766
   #1 -> Kernel.CompleteEvent;
2767
end
2768
 
2769
 
2770
always @(Kernel.CommandDecode1[`RSIG_cmd]) if (KernelStatus==`READY )  begin                      // Read Electronic Signature
2771
   Read_man.SetMode(`ReadSignature_bus, ReadStatus);
2772
   Kernel.Report(`RSIG_cmd, 8'hXX, ReadStatus);
2773
   #1 -> Kernel.CompleteEvent;
2774
end
2775
 
2776
always @(Kernel.CommandDecode1[`RCFI_cmd]) if (KernelStatus==`READY)  begin                      // Read CFI 
2777
   Read_man.SetMode(`ReadCFI_bus, ReadStatus);
2778
   Kernel.Report(`RCFI_cmd, 8'hXX, ReadStatus);
2779
   #1 -> Kernel.CompleteEvent;
2780
end
2781
 
2782
always @(Kernel.CommandDecode1[`PG_cmd]) if (KernelStatus==`READY) begin                     // Program
2783
   P_init=1;
2784
   @Kernel.CUIcommandEvent
2785
          #1 -> Kernel.VerifyEvent;
2786
   Program_man.Program(ProgramStatus);
2787
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
2788
-> Kernel.CompleteEvent;
2789
P_init=0;
2790
end
2791
 
2792
 
2793
always @(Kernel.CommandDecode1[`PRREG_cmd]) if (KernelStatus==`READY)  begin                      // Protection Register Program
2794
   @Kernel.CUIcommandEvent
2795
      #1 -> Kernel.VerifyEvent;
2796
   ProtectReg_man.Program(ProtectRegStatus);
2797
Kernel.Report(`PRREG_cmd, 8'hXX, ProtectRegStatus);
2798
-> Kernel.CompleteEvent;
2799
end
2800
 
2801
always @(Kernel.CommandDecode1[`PES_cmd]) if (KernelStatus==`READY) begin                       // Suspend
2802
   if (Program_man.IsBusy(1'bX))
2803
      Program_man.Suspend(SuspendStatus);
2804
   else if (ProgramBuffer_man.IsBusy(1'bX))
2805
      ProgramBuffer_man.Suspend(SuspendStatus);
2806
   else if (Erase_man.IsBusy(1'bX))
2807
      Erase_man.Suspend(SuspendStatus);
2808
   -> Kernel.CompleteEvent;
2809
end
2810
 
2811
 
2812
always @(Kernel.CommandDecode1[`PER_cmd]) if (KernelStatus==`READY) begin                       // Program/Erase Resume
2813
   ResumeStatus = `NoError_msg;
2814
   if (Program_man.IsSuspended(1'bX)) begin
2815
      Program_man.Resume(ProgramStatus);
2816
      Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
2817
   end
2818
   else if (ProgramBuffer_man.IsSuspended(1'bX)) begin
2819
      ProgramBuffer_man.Resume(BufferStatus);
2820
      Kernel.Report(`PB_cmd, 8'hXX, BufferStatus);
2821
   end
2822
   else if (Erase_man.IsSuspended(1'bX)) begin
2823
      Erase_man.Resume(EraseStatus);
2824
      Kernel.Report(`BLKEE_cmd, 8'hXX, EraseStatus);
2825
   end
2826
   else
2827
      ResumeStatus = `NoSusp_msg;
2828
   Kernel.Report(`PER_cmd, 8'hXX, ResumeStatus);
2829
   -> Kernel.CompleteEvent;
2830
 
2831
end
2832
 
2833
always @(Kernel.CommandDecode1[`BLKEE_cmd]) if (KernelStatus==`READY) begin                    // Block Erase
2834
   Read_man.SetMode(`ReadStatusReg_bus,ReadStatus);
2835
   EraseStatus=`NoError_msg;
2836
   @Kernel.CUIcommandEvent
2837
               Erase_man.checkConfirm(EraseStatus);
2838
   #1 -> Kernel.VerifyEvent;
2839
   if (EraseStatus != `NoError_msg)
2840
      Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd, EraseStatus);
2841
   else
2842
   begin
2843
      Erase_man.BlockErase(EraseStatus);
2844
      Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd , EraseStatus);
2845
      -> Kernel.CompleteEvent;
2846
   end
2847
end
2848
 
2849
always @(Kernel.CommandDecode1[`CLRSR_cmd]) if (KernelStatus==`READY)  begin                    // Clear Status Register
2850
   SR_man.Clear(ClearSRStatus);
2851
   Kernel.Report(`CLRSR_cmd, 8'hXX, ClearSRStatus);
2852
   #1 -> Kernel.CompleteEvent;
2853
end
2854
 
2855
 
2856
//aggiunta ************************************************
2857
// PB Fast Program Commands
2858
always @(Kernel.CommandDecode1[`PB_cmd]) if (KernelStatus==`READY)  begin                       // Write to Program and Buffer 
2859
   ProgramBufferStatus = `NoError_msg;
2860
   PB_init=1;
2861
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2862
   @Kernel.CUIcommandEvent
2863
      ProgramBuffer_man.SetCount(ProgramBufferStatus);
2864
   #1 -> Kernel.VerifyEvent;
2865
 
2866
   if (ProgramBufferStatus == `NoError_msg) begin
2867
      for (i=1; i <= ProgramBuffer_man.GetCount(1'bX); i=i+1) begin : GetData
2868
         @Kernel.CUIcommandEvent
2869
             #1;
2870
 
2871
         ProgramBuffer_man.Load(ProgramBufferStatus);
2872
         #1 -> Kernel.VerifyEvent;
2873
         if (ProgramBufferStatus != `NoError_msg)
2874
            disable GetData;
2875
      end
2876
      @Kernel.CUIcommandEvent
2877
         if (DQ[`BYTE_range] != `PBcfm_cmd)
2878
            ProgramBufferStatus = `CmdSeq_msg;
2879
         else begin
2880
            #1 -> Kernel.VerifyEvent;
2881
            ProgramBuffer_man.Program(ProgramBufferStatus);
2882
end
2883
   end
2884
   Kernel.Report(`PB_cmd, 8'hXX, ProgramBufferStatus);
2885
   ->Kernel.CompleteEvent;
2886
   PB_init=0;
2887
end
2888
//*************************************************************************
2889
 
2890
always @(Kernel.CommandDecode2[{`BL_cmd,`BLconfirm_cmd}]) if (KernelStatus==`READY)  begin      // Block Lock
2891
   BlockLock_man.Lock(LockStatus);
2892
   Kernel.Report(`BL_cmd, `BLconfirm_cmd, LockStatus);
2893
   -> Kernel.CompleteEvent;
2894
end
2895
 
2896
always @(Kernel.CommandDecode2[{`BUL_cmd,`BULconfirm_cmd}]) if (KernelStatus==`READY) begin    // Block UnLock
2897
   BlockLock_man.UnLock(LockStatus);
2898
   Kernel.Report(`BUL_cmd,`BULconfirm_cmd, LockStatus);
2899
   -> Kernel.CompleteEvent;
2900
end
2901
 
2902
always @(Kernel.CommandDecode2[{`BLD_cmd,`BLDconfirm_cmd}]) if (KernelStatus==`READY)  begin    // Block Lock-Down
2903
   BlockLock_man.LockDown(LockStatus);
2904
   Kernel.Report(`BLD_cmd,`BLDconfirm_cmd, LockStatus);
2905
   -> Kernel.CompleteEvent;
2906
end
2907
 
2908
always @(Kernel.CommandDecode2[{`SCR_cmd,`SCRconfirm_cmd}]) if (KernelStatus==`READY) begin    // Set Configuration Register
2909
   ConfigReg_man.putConfigReg(ConfigStatus);
2910
   Kernel.Report(`SCR_cmd,`SCRconfirm_cmd, ConfigStatus);
2911
   -> Kernel.CompleteEvent;
2912
end
2913
 
2914
 
2915
// BC
2916
always @(Kernel.CommandDecode1[`BLNKCHK_cmd]) if (KernelStatus==`READY)  begin                    // Blank Check
2917
   BlankCheckStatus=`NoError_msg;
2918
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2919
   @Kernel.CUIcommandEvent
2920
      BlankCheck_man.checkConfirm(BlankCheckStatus);
2921
   #1 -> Kernel.VerifyEvent;
2922
 
2923
   if (BlankCheckStatus != `NoError_msg) begin
2924
 
2925
      Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
2926
   end else
2927
   begin
2928
      BlankCheck_man.BlankCheck(BlankCheckStatus);
2929
      Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
2930
   end
2931
   -> Kernel.CompleteEvent;
2932
 
2933
end
2934
// BEFP 
2935
always @(Kernel.CommandDecode1[`BuffEnhProgram_cmd]) if (KernelStatus==`READY)  begin    // Buffer Enhanced Factory Program: Setup Phase
2936
   Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
2937
   BP_init=1;
2938
   @Kernel.CUIcommandEvent
2939
           #1 -> Kernel.VerifyEvent;
2940
   if (Kernel.Suspended | !Kernel.Ready)
2941
      BuffEnhancedProgramStatus = `SuspCmd_msg;
2942
   else begin
2943
      if (DQ[`LOW_range]!=`BuffEnhProgramCfrm_cmd)
2944
         BuffEnhancedProgramStatus=`CmdSeq_msg;
2945
      else begin
2946
         if (Info) $display("[%t]  Command Issued: Buffer Enh.Factory Program  [Confirm]",$time);
2947
 
2948
         BuffEnhancedFactProgram_man.Setup(BuffEnhancedProgramStatus);
2949
         if (BuffEnhancedProgramStatus == `NoError_msg) begin
2950
            while (BuffEnhancedProgramStatus == `NoError_msg)  begin               // Loop Program - Enhanced Factory Program: Program Phase
2951
               if (Info) $display("[%t]  Enhanced Factory Program -> Load Phase",$time);
2952
 
2953
               while (BuffEnhancedProgramStatus == `NoError_msg ) begin               // Loop Load - Enhanced Factory Program: Load Phase
2954
                  @Kernel.CUIcommandEvent
2955
                                                 #1 -> Kernel.VerifyEvent;
2956
                  BuffEnhancedFactProgram_man.Load(BuffEnhancedProgramStatus);
2957
               end
2958
               if (BuffEnhancedProgramStatus==`ProgramPHASE_BEFP_msg) begin
2959
                  BuffEnhancedFactProgram_man.Program(BuffEnhancedProgramStatus);
2960
end
2961
            end
2962
            BuffEnhancedFactProgram_man.Exit(BuffEnhancedProgramStatus);
2963
         end
2964
      end
2965
      if (BuffEnhancedProgramStatus == `ExitPHASE_BEFP_msg)
2966
         BuffEnhancedProgramStatus = `NoError_msg;
2967
   end
2968
   Kernel.Report(`BuffEnhProgram_cmd,`BuffEnhProgramCfrm_cmd, BuffEnhancedProgramStatus);
2969
   -> Kernel.CompleteEvent;
2970
   BP_init=0;
2971
end
2972
 
2973
 
2974
 
2975
//***********************************************************
2976
 
2977
// Decode Delays for Page Mode Reads
2978
 
2979
//******************************************************
2980
 
2981
// Page mode
2982
always
2983
begin :nopage
2984
   @(A[`ADDRBUS_dim - 1:4])
2985
      disable page;
2986
 
2987
   OutputBuffer_man.SetValid(TimingData_man.tAVQV);
2988
end
2989
 
2990
// Page mode
2991
always
2992
begin :page
2993
   @(A[3:0]) //pagina di 16 words
2994
      OutputBuffer_man.SetValid(TimingData_man.tAVQV1);
2995
end
2996
 
2997
 
2998
// Output Buffer delays 
2999
 
3000
always @(negedge E_N) begin
3001
   OutputBuffer_man.SetX(TimingData_man.tELQX);
3002
   OutputBuffer_man.SetValid(TimingData_man.tELQV);
3003
 
3004
end
3005
 
3006
always @(negedge G_N) begin
3007
   #0;
3008
   OutputBuffer_man.SetX(TimingData_man.tGLQX);
3009
   OutputBuffer_man.SetValid(TimingData_man.tGLQV);
3010
 
3011
end
3012
 
3013
always @(posedge CLK) begin
3014
   CLOCK = !CLOCK;
3015
end
3016
 
3017
always @(negedge CLK) begin
3018
   CLOCK = !CLOCK;
3019
end
3020
 
3021
 
3022
 
3023
   reg waiting=1;
3024
 
3025
always @(posedge G_N) begin
3026
 
3027
   waiting=1;
3028
 
3029
end
3030
 
3031
 
3032
 
3033
always @(CLK) begin
3034
 
3035
   if ((!G_N) && (CE_N == `LOW) && (ConfigReg_man.isSynchronous) && (CLK)) begin
3036
 
3037
      if (ConfigReg_man.isWaitBeforeActive && Burst_man.firstEOWL && waiting) begin
3038
         OutputBuffer_man.SetX(TimingData_man.tKHQX);
3039
         @(posedge (CLK))
3040
            OutputBuffer_man.SetX(TimingData_man.tKHQX);
3041
         OutputBuffer_man.SetValid(TimingData_man.tKHQV);
3042
         waiting=0;
3043
 
3044
      end else begin
3045
 
3046
         OutputBuffer_man.SetX(TimingData_man.tKHQX);
3047
         OutputBuffer_man.SetValid(TimingData_man.tKHQV);
3048
 
3049
      end
3050
 
3051
   end
3052
end
3053
 
3054
always @(negedge L_N) if(W_N==`HIGH)begin
3055
   if (ConfigReg_man.isSynchronous && CE_N==`LOW) begin
3056
      OutputBuffer_man.SetValid(TimingData_man.tLLQV);
3057
 
3058
 
3059
   end
3060
end
3061
 
3062
 
3063
always @(RP_N) begin
3064
   if (RP_N == `HIGH)
3065
      OutputBuffer_man.SetValid(TimingData_man.tPHWL);
3066
end
3067
 
3068
always @(posedge CE_N) begin
3069
   OutputBuffer_man.SetZ(TimingData_man.tEHQZ);
3070
end
3071
 
3072
always @(posedge G_N) begin
3073
   OutputBuffer_man.SetZ(TimingData_man.tGHQZ);
3074
   OutputBuffer_man.SetZ(TimingData_man.tGHTZ);
3075
 
3076
end
3077
 
3078
 
3079
 
3080
////////////////////////////////
3081
always @(CE_N) begin
3082
   if (CE_N == `LOW && W_N==`HIGH && G_N == `LOW) begin
3083
      if (ConfigReg_man.isSynchronous)
3084
         wait_ = #(TimingData_man.tELTV) ConfigReg_man.isWaitPolActiveHigh;
3085
      else wait_ = #(TimingData_man.tELTV) !ConfigReg_man.isWaitPolActiveHigh;
3086
   end
3087
   else
3088
      wait_ = #(TimingData_man.tEHTZ) 1'hZ;
3089
end
3090
 
3091
always @(G_N) begin
3092
   if (G_N == `LOW && CE_N == `LOW && W_N==`HIGH) begin
3093
      if (ConfigReg_man.isSynchronous) begin
3094
         wait_ = #(TimingData_man.tGLTV) ConfigReg_man.isWaitPolActiveHigh;
3095
      end else begin
3096
         wait_ = #(TimingData_man.tGLTV) !ConfigReg_man.isWaitPolActiveHigh;
3097
      end
3098
   end
3099
   else begin if (G_N == `HIGH )
3100
      wait_ = #(TimingData_man.tGHTZ) 1'hZ;
3101
 
3102
      disable Burst_man.pollingBurst;
3103
   end
3104
end
3105
 
3106
 
3107
 
3108
 
3109
always @(isWait) begin
3110
 
3111
   if ((CE_N == `LOW) && (G_N == `LOW) && ConfigReg_man.isSynchronous ) begin
3112
 
3113
      if (CLK) begin
3114
         if (isWait == `LOW ) begin
3115
            if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3116
            else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3117
         end else begin
3118
            if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3119
            else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3120
         end
3121
 
3122
      end else
3123
 
3124
         fork
3125
 
3126
            begin
3127
               @(posedge(CLK))
3128
 
3129
                  if (isWait == `LOW) begin
3130
                     if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3131
                     else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3132
                  end else begin
3133
                     if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3134
                     else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3135
                  end
3136
            end
3137
 
3138
 
3139
            begin
3140
 
3141
               @(isWait)
3142
 
3143
                  if (CLK) begin
3144
                     if (isWait == `LOW) begin
3145
                        if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
3146
                        else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
3147
                     end else begin
3148
                        if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
3149
                        else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
3150
                     end
3151
 
3152
                  end
3153
            end
3154
 
3155
         join
3156
 
3157
 
3158
   end else if  (G_N == `HIGH && isWait == `HIGH && W_N==`HIGH)
3159
      $display("%t --- WARNING --- WAIT should be deasserted but OE# is not yet LOW. Please check the timings!",$time);
3160
end
3161
 
3162
 
3163
endmodule
3164
 
3165
 
3166
 
3167
// *********************************
3168
//
3169
// Burst module :
3170
//
3171
//      manage the Read Burst operation
3172
//
3173
// *********************************
3174
 
3175
module BurstModule(address, data, ISWAIT, CLK, CLOCK, L_N, G_N, W_N, Info);
3176
   input [`ADDRBUS_range] address;
3177
   output [`WORD_range]   data;
3178
   reg [`WORD_range]      data;
3179
 
3180
   input                  CLK;
3181
   input                  CLOCK;
3182
   input                  L_N;
3183
   input                  G_N;
3184
   input                  W_N;
3185
   output                 ISWAIT;
3186
   input                  Info;
3187
 
3188
   reg [`ADDRBUS_range]   Start_address, Sync_address,new_address;
3189
   reg                    EnableBurst, isValidData, IsNowWait, endSingleSynchronous;
3190
   reg [2:0]               incLSBaddress, incMSBaddress, temp_address;
3191
 
3192
   wire                   isSingleSynchronous = (Read_man.Mode != `ReadArray_bus) ? `TRUE : `FALSE;
3193
 
3194
   integer                WaitState,nWait,nRead,xLatency;
3195
//aggiunta per il calcolo degli nwait
3196
   integer                boundary,offset;
3197
   reg                    firstEOWL;
3198
 
3199
initial begin                 // constructor sequence
3200
   Start_address = `ADDRBUS_dim'h000000;
3201
   EnableBurst = `FALSE;
3202
   endSingleSynchronous = `FALSE;
3203
   data = 16'hZZ;
3204
   nWait = 0;
3205
   IsNowWait = `FALSE;
3206
   isValidData = `FALSE;
3207
   xLatency=0;
3208
   nRead=0;
3209
   WaitState=0;
3210
   firstEOWL=0;
3211
end
3212
 
3213
always @(G_N) if (G_N==`TRUE) begin
3214
   IsNowWait = `FALSE;
3215
   isValidData = `FALSE;
3216
   EnableBurst = `FALSE;
3217
   endSingleSynchronous = `FALSE;
3218
   data = 16'hZZ;
3219
   nWait = 0;
3220
   xLatency=0;
3221
   nRead=0;
3222
   WaitState=0;
3223
   firstEOWL=0;
3224
end
3225
 
3226
 
3227
always @(isValidData) begin
3228
   case (isValidData)
3229
 
3230
      1: if (!ConfigReg_man.isWaitBeforeActive) begin
3231
 
3232
         IsNowWait = `TRUE;
3233
      end
3234
 
3235
      0: begin if (!ConfigReg_man.isWaitBeforeActive)
3236
         IsNowWait = `FALSE;
3237
 
3238
 
3239
      end
3240
 
3241
   endcase
3242
end
3243
 
3244
 
3245
assign ISWAIT = (IsNowWait) ? `TRUE : `FALSE;
3246
 
3247
 
3248
always @(negedge L_N) if(W_N==`HIGH) begin  : pollingBurst
3249
   fork  : pollingBurst
3250
 
3251
      begin: L_lacthing
3252
         @(posedge L_N) if (ConfigReg_man.isSynchronous) begin
3253
            #1;
3254
            Start_address = address;
3255
            Sync_address =  address;
3256
            firstEOWL=0;
3257
            disable K_lacthing;
3258
 
3259
            @(posedge CLK) begin
3260
 
3261
               case(ConfigReg_man.BurstLength)
3262
 
3263
                  0: begin
3264
                     boundary =16;
3265
                     offset = address[3:0];
3266
                  end
3267
 
3268
                  16:begin
3269
                     boundary =16;
3270
                     offset = address[3:0];
3271
                  end
3272
 
3273
                  8: begin
3274
                     boundary =8;
3275
                     offset = address[2:0];
3276
                  end
3277
 
3278
 
3279
                  4:begin
3280
                     boundary =4;
3281
                     offset = address[1:0];
3282
                  end
3283
               endcase
3284
 
3285
               xLatency = ConfigReg_man.Xlatency;
3286
               WaitState = xLatency - (boundary - offset);
3287
 
3288
               if (WaitState < 0) WaitState =0;
3289
               nWait = 0;
3290
               EnableBurst = `TRUE;
3291
               data = 16'hXX;
3292
               nRead = 0;
3293
               isValidData = `FALSE;
3294
               endSingleSynchronous=`FALSE;
3295
               disable pollingBurst;
3296
            end
3297
         end
3298
         else EnableBurst = `FALSE;
3299
      end
3300
 
3301
      begin: K_lacthing
3302
         @(posedge CLK) if (ConfigReg_man.isSynchronous && L_N==`LOW) begin
3303
            #1;
3304
            Start_address = address;
3305
            Sync_address =  address;
3306
            firstEOWL=0;
3307
            disable L_lacthing;
3308
 
3309
            @(posedge CLK) begin
3310
 
3311
               case(ConfigReg_man.BurstLength)
3312
 
3313
                  0: begin
3314
                     boundary =16;
3315
                     offset = address[3:0];
3316
                  end
3317
 
3318
                  16:begin
3319
                     boundary =16;
3320
                     offset = address[3:0];
3321
                  end
3322
 
3323
                  8: begin
3324
                     boundary =8;
3325
                     offset = address[2:0];
3326
                  end
3327
 
3328
 
3329
                  4:begin
3330
                     boundary =4;
3331
                     offset = address[1:0];
3332
                  end
3333
               endcase
3334
 
3335
               xLatency = ConfigReg_man.Xlatency;
3336
               WaitState = xLatency - (boundary - offset); //
3337
               if (WaitState < 0) WaitState =0;
3338
               nWait = 0;
3339
               EnableBurst = `TRUE;
3340
               data = 16'hXX;
3341
               nRead = 0;
3342
               isValidData = `FALSE;
3343
               endSingleSynchronous=`FALSE;
3344
               disable pollingBurst;
3345
            end
3346
         end
3347
         else EnableBurst = `FALSE;
3348
      end
3349
   join
3350
   $display("  %t address=%h",$time,Start_address);
3351
end
3352
 
3353
 
3354
always @(posedge (CLK)) if(G_N==`LOW) begin
3355
   if (EnableBurst) begin
3356
      if (xLatency == 2 && ConfigReg_man.isWaitBeforeActive)
3357
         IsNowWait = `TRUE;
3358
 
3359
      if (xLatency == 1) begin
3360
         isValidData = `TRUE;
3361
         if (offset == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
3362
            IsNowWait = `FALSE;
3363
 
3364
         end
3365
 
3366
 
3367
      end
3368
      if (xLatency) xLatency = xLatency - 1; //vuol dire se xLatency e' >1 o diverso da zero????
3369
   end
3370
end
3371
 
3372
always @(nRead) begin
3373
   if (isSingleSynchronous && nRead>=1) begin //End of SingleBurstRead???
3374
      endSingleSynchronous=`TRUE;
3375
      isValidData = `FALSE;
3376
   end
3377
   if((offset + nRead) == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
3378
      IsNowWait = `FALSE;
3379
 
3380
   end
3381
 
3382
end
3383
 
3384
 
3385
always @(CLK) begin
3386
 
3387
   if (EnableBurst) begin
3388
 
3389
      if (!xLatency) begin // burst is ongoing(after xLatency)
3390
 
3391
         if (!G_N) begin
3392
 
3393
            if (nWait || endSingleSynchronous) data = `DATABUS_dim'hXXXX; //Wait State;
3394
 
3395
            else begin  // Read is Possible!
3396
               // -- \\ 
3397
               case (Read_man.Mode)
3398
                  `ReadArray_bus       : begin
3399
                     data = Memory_man.Get(Sync_address);
3400
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: Memory[%h]=%h\n",$time,Sync_address,data);
3401
                  end
3402
                  `ReadCFI_bus         : begin
3403
                     data = CFIquery_man.Get(Sync_address);
3404
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: CFIMemory[%h]=%h\n",$time,Sync_address,data);
3405
                  end
3406
                  `ReadSignature_bus   : begin
3407
                     data = Signature_man.Get(Sync_address);
3408
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: Electronic Signature[%h]=%h\n",$time,Sync_address,data);
3409
                  end
3410
                  `ReadStatusReg_bus   : begin
3411
                     data = SR_man.SR;
3412
                     @(posedge (CLK)) if (Info && !G_N) $write("[%t]  Burst Read: StatusRegister: %b\n",$time,data[`BYTE_range]);
3413
                  end
3414
                  default             : $display("[%t]  !!!Model Error: Read mode not recognized!!!", $time);
3415
               endcase
3416
               // -- \\     
3417
            end
3418
            if((CLK)) begin
3419
 
3420
               if (!nWait) // Wait State??? if no calculate next address
3421
               begin
3422
 
3423
                  new_address = Sync_address + 1;
3424
                  nRead = nRead + 1;
3425
 
3426
               end
3427
               if (!isSingleSynchronous) begin
3428
 
3429
                  // Calcultate Address for Sequential and Wrap Burst 
3430
                  if ((ConfigReg_man.BurstLength != 5'd00) && ConfigReg_man.isWrapBurst)  begin
3431
                     case (ConfigReg_man.BurstLength_bit)
3432
                        3'd2: new_address = {Sync_address[`ADDRBUS_dim - 1 : 2], new_address[1:0] };
3433
                        3'd3: new_address = {Sync_address[`ADDRBUS_dim - 1 : 3], new_address[2:0] };
3434
                        3'd4: new_address = {Sync_address[`ADDRBUS_dim - 1 : 4], new_address[3:0] };
3435
                     endcase
3436
                  end
3437
 
3438
                  // Calculate Next Wait State
3439
                  if (ConfigReg_man.isNoWrapBurst || (ConfigReg_man.BurstLength == 5'd00) )  //Calculate WAIT STATE
3440
                     if ((new_address[3:0]==4'd0) && (Sync_address[3:0] == 4'd15)) begin
3441
 
3442
                        if(!ConfigReg_man.isWaitBeforeActive)  begin
3443
 
3444
                           if (nWait<WaitState && !firstEOWL) begin
3445
                              nWait = nWait+1; // Another Wait State???
3446
                              isValidData = `FALSE;
3447
                           end else begin
3448
                              nWait = 0;       // end of wait state
3449
                              Sync_address = new_address;
3450
                              isValidData = `TRUE;
3451
                              firstEOWL =1;
3452
 
3453
                           end
3454
 
3455
                        end else begin
3456
                           if (nWait<WaitState-1 && !firstEOWL ) begin
3457
                              nWait = nWait+1; // Another Wait State???
3458
                              IsNowWait = `FALSE;
3459
                           end else begin
3460
                              nWait = 0;       // end of wait state
3461
                              Sync_address = new_address;
3462
                              IsNowWait = `TRUE;
3463
                              firstEOWL =1;
3464
 
3465
                           end
3466
                        end
3467
 
3468
                     end
3469
                  if (!nWait)
3470
                     if ((nRead<ConfigReg_man.BurstLength) || (ConfigReg_man.BurstLength==5'd00) // Read Data is Over Burst Lenght???
3471
                         && !endSingleSynchronous) // end of SingleSinchronous Burst Read ???
3472
                        Sync_address = new_address;
3473
               end  // !isSyn
3474
 
3475
            end //aggiunta
3476
 
3477
         end //G_N
3478
      end // XLatency
3479
   end //Enable Burst
3480
end
3481
 
3482
 
3483
endmodule // end Burst Module 
3484
 
3485
 
3486
// Erase Manager
3487
// manage the erase functionality
3488
 
3489
module BlankCheckModule(address, data, progVoltOK, progHighVoltOK,Info);
3490
 
3491
   input [`WORD_range] data;
3492
   input [`ADDRBUS_range] address;
3493
   input                  progVoltOK, progHighVoltOK;
3494
   input                  Info;
3495
 
3496
   event                  ErrorCheckEvent, CompleteEvent;
3497
 
3498
   reg [`BYTE_range]      Status;
3499
   reg [`ADDRBUS_range]   hold_address;
3500
   reg [`BLOCKADDR_range] hold_block;
3501
 
3502
 
3503
   reg                    Busy;
3504
   integer                i;
3505
   time                   startTime, delayTime, Erase_time;
3506
 
3507
initial begin                   // constructor sequence             
3508
   Busy       = `FALSE;
3509
   Erase_time = `MainBlockErase_time; //modificato
3510
   delayTime  =  Erase_time;
3511
end
3512
 
3513
always @(progVoltOK,progHighVoltOK,address) begin
3514
   if (progHighVoltOK)
3515
      if (BankLib_man.isMainBlock(address)) Erase_time=`FastMainBlockErase_time;
3516
      else  Erase_time=`FastParameterBlockErase_time;
3517
   else
3518
      if (BankLib_man.isMainBlock(address)) Erase_time=`MainBlockErase_time;
3519
      else  Erase_time=`ParameterBlockErase_time;
3520
end
3521
 
3522
 
3523
function IsBusy;                // boolean function primitive       
3524
   input obbl;                     // all functions require a parameter
3525
   IsBusy = Busy;                // return Boolean value             
3526
endfunction
3527
 
3528
 
3529
 
3530
// *********************
3531
//
3532
// Task checkConfirm :
3533
//    check confirm code
3534
//
3535
// *********************
3536
 
3537
task checkConfirm;
3538
 
3539
   output  [`BYTE_range] outStatus;
3540
 
3541
   reg [`BYTE_range]     outStatus;
3542
 
3543
   begin
3544
 
3545
      if (data == `BLNKCHKconfirm_cmd) outStatus = `NoError_msg;
3546
 
3547
      else outStatus = `WrongBlankCheckConfirm_msg;
3548
   end
3549
endtask
3550
 
3551
 
3552
 
3553
 
3554
 
3555
// ****************
3556
//
3557
// Task Blank Check
3558
// 
3559
// ****************
3560
 
3561
task BlankCheck;
3562
 
3563
   output  [`BYTE_range] outStatus;
3564
 
3565
   reg [`BYTE_range]     outStatus;
3566
 
3567
   integer               hold_block;
3568
   reg [`ADDRBUS_range]  hold_address;
3569
 
3570
   begin
3571
      hold_address = address;
3572
      hold_block = BankLib_man.getBlock(hold_address);
3573
 
3574
      if (BankLib_man.isMainBlock(address)) begin
3575
         // Main Block
3576
         delayTime = `MainBlankCheck_time;
3577
      end else  // Parameter Block
3578
         -> ErrorCheckEvent;
3579
      disable Operation;
3580
 
3581
      fork
3582
         begin: Operation
3583
            Busy = `TRUE;
3584
            startTime = $time;
3585
            -> ErrorCheckEvent;
3586
            #delayTime
3587
               Memory_man.BlockBlankCheck(hold_block, Status);
3588
            -> CompleteEvent;
3589
         end
3590
         @CompleteEvent
3591
            disable Operation;
3592
      join
3593
      outStatus = Status;
3594
      Busy = `FALSE;
3595
   end
3596
endtask
3597
 
3598
 
3599
 
3600
always @(ErrorCheckEvent) begin
3601
   Status = `NoError_msg;
3602
   if (!progVoltOK)
3603
      Status = `InvVDD_msg;
3604
   if (BankLib_man.isParameterBlock(address)) begin
3605
 
3606
      Status = `WrongBlankCheckBlock;
3607
      $display("parameter block");
3608
   end
3609
   if (Status != `NoError_msg) begin
3610
      ->CompleteEvent;
3611
      disable ErrorCheck;
3612
   end
3613
   else
3614
      fork : ErrorCheck
3615
         @(negedge progVoltOK) Status = `InvVDD_msg;
3616
         @(Status) -> CompleteEvent;
3617
         @(CompleteEvent) disable ErrorCheck;
3618
      join
3619
end
3620
 
3621
endmodule  //end module Erase
3622
 
3623
 
3624
// *********************************
3625
//
3626
// Program Buffer module :
3627
//
3628
//      program buffer functionality
3629
//
3630
// *********************************
3631
 
3632
module ProgramBufferModule(address,data,voltOK,Info);
3633
   input [`ADDRBUS_range] address;
3634
   input [`WORD_range]    data;
3635
   input                  voltOK, Info;
3636
   event                  ErrorCheckEvent, CompleteEvent, WatchAddressEvent;
3637
   reg [`BYTE_range]      Status;
3638
   reg [`DATABUS_dim-1:0] Count;
3639
 
3640
   reg [`WORD_range]      bufferData [`ProgramBuffer_range];
3641
 
3642
   reg [`ADDRBUS_range]   AddressLatched, startAddress,newAddress;
3643
   reg                    Busy, Suspended, Empty;
3644
   time                   startTime, delayTime;
3645
   integer                i;
3646
 
3647
initial begin                 // constructor sequence             
3648
   Busy = `FALSE;
3649
   Suspended = `FALSE;
3650
   Empty = `TRUE;
3651
   delayTime = `ProgramBuffer_time;
3652
end
3653
 
3654
function IsBusy;              // boolean function primitive       
3655
   input obbl;               // all functions require a parameter
3656
   IsBusy = Busy;              // return Boolean value             
3657
endfunction
3658
 
3659
function IsSuspended;         // boolean function primitive       
3660
   input obbl;               // all functions require a parameter
3661
   IsSuspended = Suspended;    // return Boolean value             
3662
endfunction
3663
 
3664
function IsAddrSuspended;     // boolean function primitive       
3665
   input [`ADDRBUS_range] addr;
3666
   IsAddrSuspended = (Suspended && ((addr >= startAddress) && (addr < (startAddress + Count))));
3667
endfunction
3668
 
3669
 
3670
function [`DATABUS_dim-1:0] GetCount;
3671
   input                  required;
3672
   GetCount = Count;
3673
endfunction
3674
 
3675
task SetCount;                // sets the number of writes
3676
   output [`BYTE_range] outStatus;
3677
   reg [`BYTE_range]    outStatus;
3678
   begin
3679
      outStatus = `NoError_msg;
3680
      AddressLatched = address;
3681
      Count = data + 1;
3682
 
3683
 
3684
      if (Count > `ProgramBuffer_dim)
3685
         outStatus = `BuffSize_msg;
3686
      else if (BankLib_man.getBlock(AddressLatched) != BankLib_man.getBlock(AddressLatched + Count - 1))
3687
 
3688
         outStatus = `BlkBuffer_msg;
3689
      else
3690
         -> WatchAddressEvent;
3691
   end
3692
endtask
3693
 
3694
task Suspend;
3695
   output [`BYTE_range] outStatus;
3696
   reg [`BYTE_range]    outStatus;
3697
   begin
3698
      delayTime = delayTime - ($time - startTime);
3699
      #`ProgramSuspendLatency_time;
3700
      outStatus = `NoError_msg;
3701
      Status = `Suspend_msg;
3702
      Suspended = `TRUE;
3703
      -> CompleteEvent;
3704
   end
3705
endtask
3706
 
3707
task Resume;
3708
   output [`BYTE_range] Status;
3709
   begin
3710
      Suspended = `FALSE;
3711
      Program(Status);
3712
end
3713
endtask
3714
 
3715
task Load;
3716
   output [`BYTE_range] Status;
3717
   begin
3718
      if (Empty) begin
3719
         startAddress = address;
3720
         if (Info) $display("[%t]  Buffer start address: %h",$time,startAddress);
3721
         Empty = `FALSE;
3722
 
3723
      end
3724
      bufferData[address[`ProgramBuffer_addrRange]] = data;
3725
 
3726
   end
3727
endtask
3728
 
3729
task Program;
3730
   output [`BYTE_range] outStatus;
3731
   reg [`BYTE_range]    outStatus;
3732
begin
3733
 
3734
   fork
3735
      begin : Operation
3736
         Busy = `TRUE;
3737
 
3738
         startTime = $time;
3739
         -> ErrorCheckEvent;
3740
         -> WatchAddressEvent; // disable address watch
3741
         #delayTime
3742
            for (i = startAddress;i < ( Count + startAddress); i = i + 1) begin
3743
               Memory_man.Program(bufferData[i[`ProgramBuffer_addrRange]],i,Status);
3744
 
3745
end
3746
         delayTime = `ProgramBuffer_time;
3747
         -> CompleteEvent;
3748
      end
3749
      @CompleteEvent
3750
         disable Operation;
3751
 
3752
   join
3753
   if(!Suspended)
3754
      for (i = 0; i < `ProgramBuffer_dim; i = i + 1) begin
3755
         bufferData[i] =16'hFFFF;
3756
      end
3757
   Empty = `TRUE;
3758
   outStatus = Status;
3759
   Busy = `FALSE;
3760
end
3761
endtask
3762
 
3763
always @(ErrorCheckEvent) begin
3764
   Status = `NoError_msg;
3765
   if (BlockLock_man.IsLocked(AddressLatched))
3766
      Status = `BlockLock_msg;
3767
   else if (Suspended)
3768
      Status = `SuspAcc_msg;
3769
   else if (!voltOK)
3770
      Status = `InvVDD_msg;
3771
 
3772
   if (Status != `NoError_msg)
3773
      ->CompleteEvent;
3774
   else
3775
      fork : ErrorCheck
3776
         @(negedge voltOK) Status = `InvVDD_msg;
3777
         @(Status) -> CompleteEvent;
3778
         @(CompleteEvent) disable ErrorCheck;
3779
      join
3780
end
3781
 
3782
always @(WatchAddressEvent) fork : AddressWatch
3783
   while (`TRUE)
3784
      @address
3785
         if (BankLib_man.getBlock(address) != BankLib_man.getBlock(AddressLatched)) begin
3786
            Status = `AddrTog_msg;
3787
            -> CompleteEvent;
3788
         end
3789
   @WatchAddressEvent
3790
      disable AddressWatch;
3791
join
3792
 
3793
endmodule

powered by: WebSVN 2.1.0

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