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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [soc/] [bench/] [s25fl032a.v] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 xianfeng
////////////////////////////////////////////////////////////////////////////////
2
//  File name : s25fl032a.v
3
////////////////////////////////////////////////////////////////////////////////
4
//  Copyright (C) 2005 Spansion, LLC.
5
//
6
//  MODIFICATION HISTORY :
7
//
8
//  version: | author:     | mod date:  | changes made:
9
//    V1.0    M.Milanovic    05 Nov 11    Initial release
10
////////////////////////////////////////////////////////////////////////////////
11
//  PART DESCRIPTION:
12
//
13
//  Library:        FLASH
14
//  Technology:     Flash Memory
15
//  Part:           S25FL032A
16
//
17
//  Description:    32 Megabit CMOS 3.0 Volt Flash Memory
18
//                  with 50MHz SPI Bus Interface
19
//
20
////////////////////////////////////////////////////////////////////////////////
21
//  Known Bugs:
22
//
23
////////////////////////////////////////////////////////////////////////////////
24
 
25
////////////////////////////////////////////////////////////////////////////////
26
// MODULE DECLARATION                                                         //
27
////////////////////////////////////////////////////////////////////////////////
28
`timescale 1 ns/1 ns
29
module s25fl032a
30
(
31
    SCK      ,
32
    SI       ,
33
    CSNeg    ,
34
    HOLDNeg  ,
35
    WNeg     ,
36
    SO
37
);
38
 
39
////////////////////////////////////////////////////////////////////////
40
// Port / Part Pin Declarations
41
////////////////////////////////////////////////////////////////////////
42
    input  SCK     ;
43
    input  SI      ;
44
    input  CSNeg   ;
45
    input  HOLDNeg ;
46
    input  WNeg    ;
47
 
48
    output SO      ;
49
 
50
// interconnect path delay signals
51
    wire  SCK_ipd      ;
52
    wire  SI_ipd       ;
53
    wire  CSNeg_ipd    ;
54
    wire  HOLDNeg_ipd  ;
55
    wire  WNeg_ipd     ;
56
 
57
//  internal delays
58
    reg DP_in    = 0;
59
    reg DP_out   = 0;
60
    reg RES_in   = 0;
61
    reg RES_out  = 0;
62
 
63
    reg SO_zd = 1'bZ;
64
    reg SO_z  = 1'bZ;
65
 
66
    parameter UserPreload     = 1;
67
    parameter mem_file_name   = "flash_mem.txt";
68
 
69
    parameter TimingModel = "DefaultTimingModel";
70
 
71
    parameter PartID = "s25fl032a";
72
    parameter MaxData = 255;
73
    parameter SecSize = 65535;
74
    parameter SecNum = 63;
75
    parameter HiAddrBit = 23;
76
    parameter AddrRANGE = 24'h3FFFFF;
77
    parameter BYTE = 8;
78
    parameter ES = 8'h15;
79
    parameter DeviceID = 24'h010215;
80
 
81
    // powerup
82
    reg PoweredUp = 0;
83
 
84
    reg PDONE    = 1; ////Prog. Done
85
    reg PSTART   = 0; ////Start Programming
86
 
87
    reg EDONE    = 1; ////Era. Done
88
    reg ESTART   = 0; ////Start Erasing
89
 
90
    reg WDONE    = 1; //// Writing Done
91
    reg WSTART   = 0; ////Start writing
92
 
93
    //Command Register
94
    reg write    = 0;
95
    reg read_out = 0;
96
 
97
    //Status reg.
98
    reg[7:0] Status_reg = 8'b0;
99
    reg[7:0] Status_reg_in = 8'b0;
100
 
101
    integer SA      = 0;         // 0 TO SecNum+1
102
    integer Byte_number = 0;
103
 
104
    //Address
105
    integer Address = 0;         // 0 - AddrRANGE
106
    reg change_addr = 0;
107
    reg  rd_fast = 1;
108
    reg  rd_slow = 0;
109
    wire fast_rd;
110
    wire rd;
111
 
112
    //Sector Protection Status
113
    reg [SecNum:0] Sec_Prot = 64'b0;
114
 
115
    // timing check violation
116
    reg Viol = 1'b0;
117
 
118
    integer Mem[0:AddrRANGE];
119
 
120
    integer WByte[0:255];
121
 
122
    integer AddrLo = 0;
123
    integer AddrHi = 0;
124
 
125
    reg[7:0]  old_bit = 8'b0;
126
    reg[7:0]  new_bit = 8'b0;
127
    integer old_int = 0;
128
    integer new_int = 0;
129
    integer wr_cnt = 0;
130
 
131
    integer read_cnt = 0;
132
    integer read_addr = 0;
133
    reg[7:0] data_out = 8'b0;
134
    reg[23:0] ident_out = 23'b0;
135
 
136
    reg oe = 1'b0;
137
    event oe_event;
138
 
139
///////////////////////////////////////////////////////////////////////////////
140
//Interconnect Path Delay Section
141
///////////////////////////////////////////////////////////////////////////////
142
 
143
 buf   (SCK_ipd, SCK);
144
 buf   (SI_ipd, SI);
145
 buf   (CSNeg_ipd, CSNeg);
146
 buf   (HOLDNeg_ipd, HOLDNeg);
147
 buf   (WNeg_ipd, WNeg);
148
 
149
///////////////////////////////////////////////////////////////////////////////
150
// Propagation  delay Section
151
///////////////////////////////////////////////////////////////////////////////
152
    nmos   (SO, SO_z, 1);
153
 
154
 specify
155
        // tipd delays: interconnect path delays , mapped to input port delays.
156
        // In Verilog is not necessary to declare any tipd_ delay variables,
157
        // they can be taken from SDF file
158
        // With all the other delays real delays would be taken from SDF file
159
 
160
                        // tpd delays
161
     specparam           tpd_SCK_SO              =1;
162
     specparam           tpd_CSNeg_SO            =1;
163
     specparam           tpd_HOLDNeg_SO          =1;
164
 
165
     specparam           tsetup_SI_SCK           =1;   //tsuDAT /
166
     specparam           tsetup_CSNeg_SCK        =1;   // tCSS /
167
     specparam           tsetup_HOLDNeg_SCK      =1;   //tHD /
168
     specparam           tsetup_SCK_HOLDNeg      =1;   //tCH \
169
     specparam           tsetup_WNeg_CSNeg       =1;   //tWPS \
170
 
171
                          // thold values: hold times
172
     specparam           thold_SI_SCK            =1; //thdDAT /
173
     specparam           thold_CSNeg_SCK         =1; //tCSH /
174
     specparam           thold_HOLDNeg_SCK       =1; //tCD /
175
     specparam           thold_SCK_HOLDNeg       =1; //tHC \
176
     specparam           thold_WNeg_CSNeg        =1; //tWPH \
177
 
178
        // tpw values: pulse width
179
     specparam           tpw_SCK_posedge         =1; //tWH
180
     specparam           tpw_SCK_negedge         =1; //tWL
181
     specparam           tpw_CSNeg_posedge       =1; //tCS
182
 
183
        // tperiod min (calculated as 1/max freq)
184
     specparam           tperiod_SCK_rd          =1; // fSCK = 33MHz
185
     specparam           tperiod_SCK_fast_rd     =1; // fSCK = 50MHz
186
 
187
        // tdevice values: values for internal delays
188
 
189
            // Page Program Operation
190
     specparam   tdevice_PP                     = 3000000; //3 ms;
191
            //Sector Erase Operation
192
     specparam   tdevice_SE                     = 3e9; //3 sec;
193
            //Bulk Erase Operation
194
     specparam   tdevice_BE                     = 192e9; //192 sec;
195
            //Write Status Register Operation
196
     specparam   tdevice_WR                     = 150000000; // 150 ms;
197
            //Software Protect Mode
198
     specparam   tdevice_DP                     = 3000; // 3 us;
199
            //Release from Software Protect Mode
200
     specparam   tdevice_RES                    = 30000; // 30 us;
201
            //VCC (min) to CS# Low
202
//     specparam   tdevice_PU                     = 10000000; //10 ms;
203
     specparam   tdevice_PU                     = 10000; //10 us;
204
 
205
///////////////////////////////////////////////////////////////////////////////
206
// Input Port  Delays  don't require Verilog description
207
///////////////////////////////////////////////////////////////////////////////
208
// Path delays                                                               //
209
///////////////////////////////////////////////////////////////////////////////
210
  (SCK => SO) = tpd_SCK_SO;
211
  (CSNeg => SO) = tpd_CSNeg_SO;
212
  (HOLDNeg => SO) = tpd_HOLDNeg_SO;
213
 
214
////////////////////////////////////////////////////////////////////////////////
215
// Timing Violation                                                           //
216
////////////////////////////////////////////////////////////////////////////////
217
        $setup ( WNeg , negedge CSNeg, tsetup_WNeg_CSNeg, Viol);
218
        $setup ( negedge HOLDNeg, posedge SCK, tsetup_HOLDNeg_SCK, Viol);
219
        $setup ( posedge SCK, posedge HOLDNeg, tsetup_SCK_HOLDNeg, Viol);
220
 
221
        $hold ( posedge CSNeg&&&WNeg, WNeg,  thold_WNeg_CSNeg, Viol);
222
        $hold ( posedge SCK, negedge HOLDNeg, thold_HOLDNeg_SCK, Viol);
223
        $hold ( posedge HOLDNeg, posedge SCK, thold_SCK_HOLDNeg, Viol);
224
 
225
        $setuphold ( posedge SCK, SI, tsetup_SI_SCK, thold_SI_SCK, Viol);
226
        $setuphold ( posedge SCK, CSNeg, tsetup_CSNeg_SCK,
227
                                                  thold_CSNeg_SCK, Viol);
228
 
229
        $width (posedge SCK, tpw_SCK_posedge);
230
        $width (negedge SCK, tpw_SCK_negedge);
231
 
232
        $width (posedge CSNeg, tpw_CSNeg_posedge);
233
 
234
        $period (posedge SCK &&& rd, tperiod_SCK_rd);
235
        $period (posedge SCK &&& fast_rd, tperiod_SCK_fast_rd);
236
 
237
    endspecify
238
 
239
////////////////////////////////////////////////////////////////////////////////
240
// Main Behavior Block                                                        //
241
////////////////////////////////////////////////////////////////////////////////
242
// FSM states
243
 parameter IDLE            =4'd0;
244
 parameter WRITE_SR        =4'd1;
245
 parameter DP_DOWN         =4'd2;
246
 parameter SECTOR_ER       =4'd3;
247
 parameter BULK_ER         =4'd4;
248
 parameter PAGE_PG         =4'd5;
249
 
250
 reg [3:0] current_state = IDLE;
251
 reg [3:0] next_state = IDLE;
252
 
253
// Instructions
254
 parameter NONE            =5'd0;
255
 parameter WREN            =5'd1;
256
 parameter WRDI            =5'd2;
257
 parameter WRSR            =5'd3;
258
 parameter RDSR            =5'd4;
259
 parameter READ            =5'd5;
260
 parameter FAST_READ       =5'd6;
261
 parameter SE              =5'd8;
262
 parameter BE              =5'd9;
263
 parameter PP              =5'd10;
264
 parameter DP              =5'd11;
265
 parameter RDID            =5'd12;
266
 parameter RES_READ_ES     =5'd13;
267
 
268
 reg [4:0] Instruct = NONE;
269
 
270
//Bus cycle states
271
 parameter STAND_BY        =3'd0;
272
 parameter CODE_BYTE       =3'd1;
273
 parameter ADDRESS_BYTES   =3'd2;
274
 parameter DUMMY_BYTES     =3'd3;
275
 parameter DATA_BYTES      =3'd4;
276
 
277
 reg [2:0] bus_cycle_state = STAND_BY;
278
 
279
    initial
280
    begin : Init
281
 
282
        write    = 1'b0;
283
        read_out  = 1'b0;
284
        Address   = 0;
285
        change_addr = 1'b0;
286
 
287
        PDONE    = 1'b1;
288
        PSTART   = 1'b0;
289
 
290
        EDONE    = 1'b1;
291
        ESTART   = 1'b0;
292
 
293
        WDONE    = 1'b1;
294
        WSTART   = 1'b0;
295
 
296
        DP_in = 1'b0;
297
        DP_out = 1'b0;
298
        RES_in = 1'b0;
299
        RES_out = 1'b0;
300
        Instruct = NONE;
301
        bus_cycle_state = STAND_BY;
302
        current_state = IDLE;
303
        next_state = IDLE;
304
    end
305
 
306
    // initialize memory
307
    initial
308
    begin: InitMemory
309
    integer i;
310
 
311
        for (i=0;i<=AddrRANGE;i=i+1)
312
        begin
313
            Mem[i] = MaxData;
314
        end
315
 
316
        if ((UserPreload) && !(mem_file_name == "none"))
317
        begin
318
           // Memory Preload
319
           //s25fl032a.mem, memory preload file
320
           //  @aaaaaa - <aaaaaa> stands for address
321
           //  dd      - <dd> is byte to be written at Mem(aaaaaa++)
322
           // (aaaaaa is incremented at every load)
323
           $readmemh(mem_file_name,Mem);
324
        end
325
    end
326
 
327
    //Power Up time;
328
    initial
329
    begin
330
        PoweredUp = 1'b0;
331
        #tdevice_PU PoweredUp = 1'b1;
332
    end
333
 
334
   always @(posedge DP_in)
335
   begin:TDPr
336
     #tdevice_DP DP_out = DP_in;
337
   end
338
   always @(negedge DP_in)
339
   begin:TDPf
340
     #1 DP_out = DP_in;
341
   end
342
 
343
   always @(posedge RES_in)
344
   begin:TRESr
345
     #tdevice_RES RES_out = RES_in;
346
   end
347
   always @(negedge RES_in)
348
   begin:TRESf
349
     #1 RES_out = RES_in;
350
   end
351
 
352
   always @(next_state or PoweredUp)
353
   begin: StateTransition
354
       if (PoweredUp)
355
       begin
356
           current_state = next_state;
357
       end
358
   end
359
 
360
////////////////////////////////////////////////////////////////////////////////
361
// Instruction cycle decode
362
////////////////////////////////////////////////////////////////////////////////
363
 integer data_cnt = 0;
364
 integer addr_cnt = 0;
365
 integer code_cnt = 0;
366
 integer dummy_cnt = 0;
367
 integer bit_cnt = 0;
368
 reg[2047:0] Data_in = 2048'b0;
369
 reg[7:0] code = 8'b0;
370
 reg[7:0] code_in = 8'b0;
371
 reg[7:0] Byte_slv = 8'b0;
372
 reg[HiAddrBit:0] addr_bytes = 24'b0;
373
 reg[23:0] Address_in = 24'b0;
374
 
375
    always @(negedge CSNeg_ipd)
376
    begin: Buscycle1
377
        if (bus_cycle_state==STAND_BY)
378
        begin
379
            bus_cycle_state = CODE_BYTE;
380
            Instruct = NONE;
381
            write = 1'b1;
382
            code_cnt = 0;
383
            addr_cnt = 0;
384
            data_cnt = 0;
385
            dummy_cnt = 0;
386
        end
387
    end
388
 
389
    always @(posedge SCK_ipd)
390
    begin: Buscycle2
391
    integer i;
392
        if ( HOLDNeg_ipd)
393
        begin
394
            case (bus_cycle_state)
395
                CODE_BYTE :
396
                begin
397
                    code_in[code_cnt] = SI_ipd;
398
                    code_cnt = code_cnt + 1;
399
                    if (code_cnt == BYTE)
400
                    begin
401
                        for (i=0;i<=7;i=i+1)
402
                        begin
403
                            code[i] = code_in[7-i];
404
                        end
405
                        case(code)
406
                            8'b00000110 :
407
                            begin
408
                                Instruct = WREN;
409
                                bus_cycle_state = DATA_BYTES;
410
                            end
411
                            8'b00000100 :
412
                            begin
413
                                Instruct = WRDI;
414
                                bus_cycle_state = DATA_BYTES;
415
                            end
416
                            8'b00000001 :
417
                            begin
418
                                Instruct = WRSR;
419
                                bus_cycle_state = DATA_BYTES;
420
                            end
421
                            8'b00000101 :
422
                            begin
423
                                Instruct = RDSR;
424
                                bus_cycle_state = DATA_BYTES;
425
                            end
426
                            8'b00000011 :
427
                            begin
428
                                Instruct = READ;
429
                                bus_cycle_state = ADDRESS_BYTES;
430
                            end
431
                            8'b00001011 :
432
                            begin
433
                                Instruct = FAST_READ;
434
                                bus_cycle_state = ADDRESS_BYTES;
435
                            end
436
                            8'b10101011 :
437
                            begin
438
                                Instruct = RES_READ_ES;
439
                                bus_cycle_state = DUMMY_BYTES;
440
                            end
441
                            8'b11011000 :
442
                            begin
443
                                Instruct = SE;
444
                                bus_cycle_state = ADDRESS_BYTES;
445
                            end
446
                            8'b11000111 :
447
                            begin
448
                                Instruct = BE;
449
                                bus_cycle_state = DATA_BYTES;
450
                            end
451
                            8'b00000010 :
452
                            begin
453
                                Instruct = PP;
454
                                bus_cycle_state = ADDRESS_BYTES;
455
                            end
456
                            8'b10111001 :
457
                            begin
458
                                Instruct = DP;
459
                                bus_cycle_state = DATA_BYTES;
460
                            end
461
                            8'b10011111 :
462
                            begin
463
                                Instruct = RDID;
464
                                bus_cycle_state = DATA_BYTES;
465
                            end
466
                        endcase
467
                    end
468
                end
469
 
470
                ADDRESS_BYTES :
471
                begin
472
                    Address_in[addr_cnt] = SI_ipd;
473
                    addr_cnt = addr_cnt + 1;
474
                    if (addr_cnt == 3*BYTE)
475
                    begin
476
                        for (i=23;i>=0;i=i-1)
477
                        begin
478
                            addr_bytes[23-i] = Address_in[i];
479
                        end
480
                        Address = addr_bytes;
481
                        change_addr = 1'b1;
482
                        #1 change_addr = 1'b0;
483
                        if (Instruct == FAST_READ)
484
                            bus_cycle_state = DUMMY_BYTES;
485
                        else
486
                            bus_cycle_state = DATA_BYTES;
487
                    end
488
                end
489
 
490
                DUMMY_BYTES :
491
                begin
492
                    dummy_cnt = dummy_cnt + 1;
493
                    if ((dummy_cnt == BYTE && Instruct == FAST_READ) ||
494
                        (dummy_cnt == 3*BYTE && Instruct == RES_READ_ES))
495
                        bus_cycle_state = DATA_BYTES;
496
                end
497
 
498
                DATA_BYTES :
499
                begin
500
                    if (data_cnt > 2047)
501
                    //In case of PP, if more than 256 bytes are
502
                    //sent to the device
503
                    begin
504
                        if (bit_cnt == 0)
505
                        begin
506
                            for (i=0;i<=(255*BYTE-1);i=i+1)
507
                            begin
508
                                Data_in[i] = Data_in[i+8];
509
                            end
510
                        end
511
                        Data_in[2040 + bit_cnt] = SI_ipd;
512
                        bit_cnt = bit_cnt + 1;
513
                        if (bit_cnt == 8)
514
                        begin
515
                            bit_cnt = 0;
516
                        end
517
                        data_cnt = data_cnt + 1;
518
                    end
519
                    else
520
                    begin
521
                        Data_in[data_cnt] = SI_ipd;
522
                        data_cnt = data_cnt + 1;
523
                        bit_cnt = 0;
524
                    end
525
                end
526
            endcase
527
        end
528
    end
529
 
530
    always @(negedge SCK_ipd)
531
    begin: Buscycle3
532
        if (bus_cycle_state==DATA_BYTES && (~CSNeg_ipd) && (HOLDNeg_ipd))
533
            if (Instruct == READ || Instruct == RES_READ_ES ||
534
                Instruct == FAST_READ || Instruct == RDSR ||
535
                Instruct == RDID)
536
                read_out = 1'b1;
537
                #1 read_out = 1'b0;
538
    end
539
 
540
    always @(posedge CSNeg_ipd)
541
    begin: Buscycle4
542
    integer i;
543
    integer j;
544
        if (bus_cycle_state == DATA_BYTES)
545
        begin
546
            bus_cycle_state = STAND_BY;
547
            if (HOLDNeg_ipd)
548
            begin
549
                case (Instruct)
550
                    WREN,
551
                    WRDI,
552
                    DP,
553
                    BE,
554
                    SE :
555
                    begin
556
                        if (data_cnt == 0)
557
                            write = 1'b0;
558
                    end
559
 
560
                    RES_READ_ES,
561
                    RDID :
562
                    begin
563
                        write = 1'b0;
564
                    end
565
 
566
                    WRSR :
567
                    begin
568
                        if (data_cnt == BYTE)
569
                            write = 1'b0;
570
                            Status_reg_in = Data_in[7:0];
571
                    end
572
 
573
                    PP :
574
                    begin
575
                        if ((data_cnt > 0) && ((data_cnt % 8) == 0))
576
                        begin
577
                            write = 1'b0;
578
                            for (i=0;i<=255;i=i+1)
579
                            begin
580
                                for (j=7;j>=0;j=j-1)
581
                                begin
582
                                    Byte_slv[j] = Data_in[(i*8) + (7-j)];
583
                                end
584
                                WByte[i] = Byte_slv;
585
                            end
586
                            if (data_cnt > 256*BYTE)
587
                                Byte_number = 255;
588
                            else
589
                                Byte_number = ((data_cnt/8) - 1);
590
                        end
591
                    end
592
                endcase
593
            end
594
        end
595
 
596
        if (bus_cycle_state == DUMMY_BYTES)
597
        begin
598
            bus_cycle_state = STAND_BY;
599
            if (HOLDNeg_ipd && Instruct == RES_READ_ES)
600
                write = 1'b0;
601
        end
602
 
603
    end
604
 
605
////////////////////////////////////////////////////////////////////////////////
606
// Timing control for the Program Operations
607
// start
608
////////////////////////////////////////////////////////////////////////////////
609
 
610
 event pdone_event;
611
 
612
    always @(PSTART)
613
    begin
614
        if (PSTART && PDONE)
615
        begin
616
            PDONE = 1'b0;
617
            ->pdone_event;
618
        end
619
    end
620
 
621
    always @(pdone_event)
622
    begin:pdone_process
623
        PDONE = 1'b0;
624
        #tdevice_PP PDONE = 1'b1;
625
    end
626
 
627
////////////////////////////////////////////////////////////////////////////////
628
// Timing control for the Write Status Register Operation
629
// start
630
////////////////////////////////////////////////////////////////////////////////
631
 
632
 event wdone_event;
633
 
634
    always @(WSTART)
635
    begin
636
        if (WSTART && WDONE)
637
        begin
638
            WDONE = 1'b0;
639
            ->wdone_event;
640
        end
641
    end
642
 
643
    always @(wdone_event)
644
    begin:wdone_process
645
        WDONE = 1'b0;
646
        #tdevice_WR WDONE = 1'b1;
647
    end
648
 
649
////////////////////////////////////////////////////////////////////////////////
650
// Timing control for the Erase Operations
651
////////////////////////////////////////////////////////////////////////////////
652
 integer cnt_erase = 0;
653
 time duration_erase;
654
 
655
    event edone_event;
656
 
657
    always @(ESTART)
658
    begin: erase
659
        if (ESTART && EDONE)
660
        begin
661
 
662
            if (Instruct == BE)
663
            begin
664
                duration_erase = tdevice_BE;
665
            end
666
            else //if (Instruct == SE)
667
            begin
668
                duration_erase = tdevice_SE;
669
            end
670
 
671
            EDONE = 1'b0;
672
            ->edone_event;
673
        end
674
    end
675
 
676
    always @(edone_event)
677
    begin : edone_process
678
        EDONE = 1'b0;
679
        #duration_erase EDONE = 1'b1;
680
    end
681
 
682
////////////////////////////////////////////////////////////////////////////////
683
// Main Behavior Process
684
// combinational process for next state generation
685
////////////////////////////////////////////////////////////////////////////////
686
 
687
    integer sect = 0;
688
 
689
    always @(negedge write)
690
    begin: StateGen1
691
 
692
        case (current_state)
693
            IDLE :
694
            begin
695
                if (~write)
696
                begin
697
                    if (Instruct == WRSR && Status_reg[1])
698
                    begin
699
                        if (~(Status_reg[7] && (~WNeg_ipd)))
700
                            next_state = WRITE_SR;
701
                    end
702
                    else if (Instruct == PP && Status_reg[1])
703
                    begin
704
                        sect = Address / 24'h10000;
705
                        if (Sec_Prot[sect] == 1'b0)
706
                            next_state = PAGE_PG;
707
                    end
708
                    else if (Instruct == SE && Status_reg[1])
709
                    begin
710
                        sect = Address / 24'h10000;
711
                        if (Sec_Prot[sect] == 1'b0)
712
                            next_state = SECTOR_ER;
713
                    end
714
                    else if (Instruct == BE && Status_reg[1])
715
                    begin
716
                        if (Status_reg[2] == 1'b0 && Status_reg[3] == 1'b0 &&
717
                            Status_reg[4] == 1'b0)
718
                            next_state = BULK_ER;
719
                    end
720
                    else if (Instruct == DP)
721
                        next_state = DP_DOWN;
722
                    else
723
                        next_state = IDLE;
724
                end
725
            end
726
 
727
            DP_DOWN:
728
            begin
729
                if (~write)
730
                begin
731
                    if (Instruct == RES_READ_ES)
732
                        next_state = IDLE;
733
                end
734
            end
735
 
736
        endcase
737
    end
738
 
739
    always @(posedge PDONE)
740
    begin: StateGen2
741
        if (current_state==PAGE_PG)
742
        begin
743
            next_state = IDLE;
744
        end
745
    end
746
 
747
    always @(posedge WDONE)
748
    begin: StateGen3
749
        if (current_state==WRITE_SR)
750
        begin
751
            next_state = IDLE;
752
        end
753
    end
754
 
755
    always @(posedge EDONE)
756
    begin: StateGen4
757
        if (current_state==SECTOR_ER || current_state==BULK_ER)
758
        begin
759
            next_state = IDLE;
760
        end
761
    end
762
 
763
////////////////////////////////////////////////////////////////////////////////
764
// FSM Output generation and general funcionality
765
////////////////////////////////////////////////////////////////////////////////
766
 
767
    always @(posedge read_out)
768
    begin
769
        if (PoweredUp == 1'b1)
770
            ->oe_event;
771
    end
772
 
773
    always @(oe_event)
774
    begin
775
        oe = 1'b1;
776
        #1 oe = 1'b0;
777
    end
778
 
779
    always @(Instruct)
780
    begin
781
        read_cnt = 0;
782
    end
783
 
784
    always @(change_addr)
785
    begin
786
        if (change_addr)
787
            read_addr = Address;
788
    end
789
 
790
    always @(Instruct)
791
    begin
792
        rd_fast = 1'b1;
793
        rd_slow = 1'b0;
794
    end
795
 
796
    always @(posedge CSNeg_ipd)
797
    begin
798
        rd_fast = 1'b1;
799
        rd_slow = 1'b0;
800
    end
801
 
802
    always @(oe or current_state)
803
    begin
804
        case (current_state)
805
            IDLE :
806
            begin
807
                if (oe && RES_in == 1'b0)
808
                begin
809
                    if (Instruct == RDSR)
810
                    begin
811
                    //Read Status Register
812
                        SO_zd = Status_reg[7-read_cnt];
813
                        read_cnt = read_cnt + 1;
814
                        if (read_cnt == 8)
815
                            read_cnt = 0;
816
                    end
817
                    else if (Instruct == READ || Instruct == FAST_READ)
818
                    begin
819
                    //Read Memory array
820
                        if (Instruct == READ)
821
                        begin
822
                            rd_fast = 1'b0;
823
                            rd_slow = 1'b1;
824
                        end
825
                        data_out[7:0] = Mem[read_addr];
826
                        SO_zd = data_out[7-read_cnt];
827
                        read_cnt = read_cnt + 1;
828
                        if (read_cnt == 8)
829
                        begin
830
                            read_cnt = 0;
831
                            if (read_addr == AddrRANGE)
832
                                read_addr = 0;
833
                            else
834
                                read_addr = read_addr + 1;
835
                        end
836
                    end
837
                    else if (Instruct == RDID)
838
                    begin
839
                    // Read ID
840
                        ident_out[23:0] = DeviceID;
841
                        SO_zd = ident_out[23-read_cnt];
842
                        read_cnt = read_cnt + 1;
843
                        if (read_cnt == 24)
844
                            read_cnt = 0;
845
                    end
846
                    else if (Instruct == RES_READ_ES)
847
                    begin
848
                    // Read Electronic Signature
849
                        data_out[7:0] = ES;
850
                        SO_zd = data_out[7-read_cnt];
851
                        read_cnt = read_cnt + 1;
852
                        if (read_cnt == 8)
853
                            read_cnt = 0;
854
                    end
855
                end
856
                else if (oe && RES_in == 1'b1)
857
                begin
858
                    $display ("Command results can be corrupted");
859
                    SO_zd = 1'bX;
860
                    read_cnt = read_cnt + 1;
861
                    if (read_cnt == 8)
862
                        read_cnt = 0;
863
                end
864
            end
865
 
866
            WRITE_SR,
867
            SECTOR_ER,
868
            BULK_ER,
869
            PAGE_PG :
870
            begin
871
                if (oe && Instruct == RDSR)
872
                begin
873
                //Read Status Register
874
                    SO_zd = Status_reg[7-read_cnt];
875
                    read_cnt = read_cnt + 1;
876
                    if (read_cnt == 8)
877
                        read_cnt = 0;
878
                end
879
            end
880
 
881
            DP_DOWN :
882
            begin
883
                if (~write)
884
                begin
885
                    if (Instruct == RES_READ_ES)
886
                        RES_in = 1'b1;
887
                end
888
                else if (oe && Instruct == RES_READ_ES)
889
                begin
890
                // Read Electronic Signature
891
                    data_out[7:0] = ES;
892
                    SO_zd = data_out[7-read_cnt];
893
                    read_cnt = read_cnt + 1;
894
                    if (read_cnt == 8)
895
                        read_cnt = 0;
896
                end
897
            end
898
 
899
        endcase
900
    end
901
 
902
    assign fast_rd = rd_fast;
903
    assign rd = rd_slow;
904
 
905
    integer sector = 0;
906
    integer WData [0:255];
907
    integer Addr = 0;
908
 
909
    always @(negedge write)
910
    begin : Output_generation
911
    integer i;
912
 
913
        case (current_state)
914
            IDLE :
915
            begin
916
                if (~write)
917
                begin
918
                        if (RES_in == 1'b1)
919
                        begin
920
                            $display ("Command results can be corrupted");
921
                        end
922
                        if (Instruct == WREN)
923
                            Status_reg[1] = 1'b1;
924
                        else if (Instruct == WRDI)
925
                            Status_reg[1] = 1'b0;
926
                        else if (Instruct == WRSR && Status_reg[1] &&
927
                                (~(Status_reg[7] == 1'b1 && WNeg_ipd == 1'b0)))
928
                        begin
929
                            WSTART = 1'b1;
930
                            WSTART <= #1 1'b0;
931
                            Status_reg[0] = 1'b1;
932
                        end
933
                        else if (Instruct == PP && Status_reg[1] == 1'b1)
934
                        begin
935
                            sector = Address / 20'h10000;
936
                            if (Sec_Prot[sector] == 1'b0)
937
                            begin
938
                                PSTART = 1'b1;
939
                                PSTART <= #1 1'b0;
940
                                Status_reg[0] = 1'b1;
941
                                Addr = Address;
942
                                SA = sector;
943
                                wr_cnt = Byte_number;
944
                                for (i=0;i<=wr_cnt;i=i+1)
945
                                begin
946
                                    if (Viol!=1'b0)
947
                                        WData[i] = -1;
948
                                    else
949
                                        WData[i] = WByte[i];
950
                                end
951
                            end
952
                        end
953
                        else if (Instruct == SE && Status_reg[1] == 1'b1)
954
                        begin
955
                            sector = Address / 20'h10000;
956
                            if (Sec_Prot[sector] == 1'b0)
957
                            begin
958
                                ESTART = 1'b1;
959
                                ESTART <= #1 1'b0;
960
                                Status_reg[0] = 1'b1;
961
                                Addr = Address;
962
                            end
963
                        end
964
                        else if (Instruct == BE && Status_reg[1] == 1'b1 &&
965
                             Status_reg[2] == 1'b0 && Status_reg[3] == 1'b0 &&
966
                             Status_reg[4] == 1'b0)
967
                        begin
968
                            ESTART = 1'b1;
969
                            ESTART <= #1 1'b0;
970
                            Status_reg[0] = 1'b1;
971
                        end
972
                        else if (Instruct == DP && RES_in == 1'b0)
973
                            DP_in = 1'b1;
974
                    end
975
 
976
            end
977
 
978
            DP_DOWN :
979
            begin
980
                if (~write)
981
                begin
982
                    if (Instruct == RES_READ_ES)
983
                        RES_in = 1'b1;
984
                end
985
            end
986
 
987
        endcase
988
    end
989
 
990
    always @(RES_out)
991
    begin : DPDOWN1
992
        if (RES_out)
993
        begin
994
            RES_in = 1'b0;
995
        end
996
    end
997
 
998
    always @(current_state or EDONE)
999
    begin: ERASE1
1000
    integer i;
1001
        case (current_state)
1002
 
1003
            SECTOR_ER :
1004
            begin
1005
                ADDRHILO_SEC(AddrLo, AddrHi, Addr);
1006
                for (i=AddrLo;i<=AddrHi;i=i+1)
1007
                begin
1008
                    Mem[i] = -1;
1009
                end
1010
 
1011
                if (EDONE)
1012
                begin
1013
                    Status_reg[0] = 1'b0;
1014
                    Status_reg[1] = 1'b0;
1015
                    for (i=AddrLo;i<=AddrHi;i=i+1)
1016
                    begin
1017
                        Mem[i] = MaxData;
1018
                    end
1019
                end
1020
            end
1021
 
1022
            BULK_ER :
1023
            begin
1024
                for (i=0;i<=AddrRANGE;i=i+1)
1025
                begin
1026
                    Mem[i] = -1;
1027
                end
1028
 
1029
                if (EDONE)
1030
                begin
1031
                    Status_reg[0] = 1'b0;
1032
                    Status_reg[1] = 1'b0;
1033
                    for (i=0;i<=AddrRANGE;i=i+1)
1034
                    begin
1035
                        Mem[i] = MaxData;
1036
                    end
1037
                end
1038
            end
1039
        endcase
1040
    end
1041
 
1042
    always @(current_state or WDONE)
1043
    begin: WRSR1
1044
        if (current_state == WRITE_SR)
1045
        begin
1046
            if (WDONE)
1047
            begin
1048
                Status_reg[0] = 1'b0;//WIP
1049
                Status_reg[1] = 1'b0;//WEL
1050
                Status_reg[7] = Status_reg_in[0];//MSB first, SRWD
1051
                Status_reg[4] = Status_reg_in[3];//MSB first, BP2
1052
                Status_reg[3] = Status_reg_in[4];//MSB first, BP1
1053
                Status_reg[2] = Status_reg_in[5];//MSB first, BP0
1054
                case (Status_reg[4:2])
1055
 
1056
                    3'b000 :
1057
                    begin
1058
                        Sec_Prot = 64'h0000000000000000;
1059
                    end
1060
 
1061
                    3'b001 :
1062
                    begin
1063
                        Sec_Prot = 64'h8000000000000000;
1064
                    end
1065
 
1066
                    3'b010 :
1067
                    begin
1068
                        Sec_Prot = 64'hC000000000000000;
1069
                    end
1070
 
1071
                    3'b011 :
1072
                    begin
1073
                        Sec_Prot = 64'hF000000000000000;
1074
                    end
1075
 
1076
                    3'b100 :
1077
                    begin
1078
                        Sec_Prot = 64'hFF00000000000000;
1079
                    end
1080
 
1081
                    3'b101 :
1082
                    begin
1083
                        Sec_Prot = 64'hFFFF000000000000;
1084
                    end
1085
 
1086
                    3'b110 :
1087
                    begin
1088
                        Sec_Prot = 64'hFFFFFFFF00000000;
1089
                    end
1090
 
1091
                    3'b111 :
1092
                    begin
1093
                        Sec_Prot = 64'hFFFFFFFFFFFFFFFF;
1094
                    end
1095
 
1096
                endcase
1097
            end
1098
        end
1099
    end
1100
 
1101
    always @(current_state or PDONE)
1102
    begin: PPPG1
1103
    integer i;
1104
    integer j;
1105
        if (current_state == PAGE_PG)
1106
        begin
1107
            ADDRHILO_PG(AddrLo, AddrHi, Addr);
1108
            if ((Addr + wr_cnt) > AddrHi)
1109
                wr_cnt = AddrHi - Addr;
1110
            for (i=Addr;i<=Addr+wr_cnt;i=i+1)
1111
            begin
1112
                new_int = WData[i-Addr];
1113
                old_int = Mem[i];
1114
                if (new_int > -1)
1115
                begin
1116
                    new_bit = new_int;
1117
                    if (old_int > -1)
1118
                    begin
1119
                        old_bit = old_int;
1120
                        for(j=0;j<=7;j=j+1)
1121
                            if (~old_bit[j])
1122
                                new_bit[j]=1'b0;
1123
                        new_int=new_bit;
1124
                    end
1125
 
1126
                    WData[i-Addr]= new_int;
1127
                end
1128
                else
1129
                begin
1130
                    WData[i-Addr] = -1;
1131
                end
1132
            end
1133
 
1134
            for (i=Addr;i<=Addr+wr_cnt;i=i+1)
1135
            begin
1136
                Mem[i] = -1;
1137
            end
1138
 
1139
            if (PDONE)
1140
            begin
1141
                Status_reg[0] = 1'b0;//wip
1142
                Status_reg[1] = 1'b0;// wel
1143
                for (i=Addr;i<=Addr+wr_cnt;i=i+1)
1144
                begin
1145
                    Mem[i] = WData[i-Addr];
1146
                end
1147
            end
1148
        end
1149
    end
1150
 
1151
// Output Control
1152
    always @(CSNeg_ipd or HOLDNeg_ipd or SCK_ipd)
1153
    begin
1154
        //Output Disable Control
1155
        if (CSNeg_ipd )
1156
            SO_zd = 1'bZ;
1157
     end
1158
 
1159
     always @(SO_zd or HOLDNeg_ipd)
1160
     begin
1161
         if (HOLDNeg_ipd == 1)
1162
             SO_z = SO_zd;
1163
         else
1164
             SO_z = 1'bZ;
1165
     end
1166
 
1167
// Procedure ADDRHILO_SEC
1168
 task ADDRHILO_SEC;
1169
 inout  AddrLOW;
1170
 inout  AddrHIGH;
1171
 input   Addr;
1172
 integer AddrLOW;
1173
 integer AddrHIGH;
1174
 integer Addr;
1175
 integer sector;
1176
 begin
1177
 
1178
    sector = Addr / 20'h10000;
1179
    AddrLOW = sector * 20'h10000;
1180
    AddrHIGH = sector * 20'h10000 + 16'hFFFF;
1181
 
1182
 end
1183
 endtask
1184
 
1185
// Procedure ADDRHILO_PG
1186
 task ADDRHILO_PG;
1187
 inout  AddrLOW;
1188
 inout  AddrHIGH;
1189
 input   Addr;
1190
 integer AddrLOW;
1191
 integer AddrHIGH;
1192
 integer Addr;
1193
 integer page;
1194
 begin
1195
 
1196
    page = Addr / 16'h100;
1197
    AddrLOW = page * 16'h100;
1198
    AddrHIGH = page * 16'h100 + 8'hFF;
1199
 
1200
 end
1201
 endtask
1202
 
1203
endmodule

powered by: WebSVN 2.1.0

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