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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [rtl/] [verilog/] [cfi_ctrl/] [cfi_ctrl.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
////  Common Flash Interface (CFI) controller                     //// 
4
////                                                              //// 
5
////  This file is part of the cfi_ctrl project                   //// 
6
////  http://opencores.org/project,cfi_ctrl                       //// 
7
////                                                              //// 
8
////  Description                                                 //// 
9
////  See below                                                   //// 
10
////                                                              //// 
11
////  To Do:                                                      //// 
12
////   -                                                          //// 
13
////                                                              //// 
14
////  Author(s):                                                  //// 
15
////      - Julius Baxter, julius@opencores.org                   //// 
16
////                                                              //// 
17
////////////////////////////////////////////////////////////////////// 
18
////                                                              //// 
19
//// Copyright (C) 2011 Authors and OPENCORES.ORG                 //// 
20
////                                                              //// 
21
//// This source file may be used and distributed without         //// 
22
//// restriction provided that this copyright statement is not    //// 
23
//// removed from the file and that any derivative work contains  //// 
24
//// the original copyright notice and the associated disclaimer. //// 
25
////                                                              //// 
26
//// This source file is free software; you can redistribute it   //// 
27
//// and/or modify it under the terms of the GNU Lesser General   //// 
28
//// Public License as published by the Free Software Foundation; //// 
29
//// either version 2.1 of the License, or (at your option) any   //// 
30
//// later version.                                               //// 
31
////                                                              //// 
32
//// This source is distributed in the hope that it will be       //// 
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   //// 
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //// 
35
//// PURPOSE.  See the GNU Lesser General Public License for more //// 
36
//// details.                                                     //// 
37
////                                                              //// 
38
//// You should have received a copy of the GNU Lesser General    //// 
39
//// Public License along with this source; if not, download it   //// 
40
//// from http://www.gnu.org/copyleft/lesser.html                 //// 
41
////                                                              ////
42
////////////////////////////////////////////////////////////////////// 
43
 
44
/*
45
 Top level of CFI controller with 32-bit Wishbone classic interface
46
 
47
 Intended to be used at about 66MHz with a 32MB CFI flash part with 16-bit
48
 data interface.
49
 
50
 This module has two configurations - one where it pulls in the CFI control
51
 engine, which is intended to simplify accesses to a CFI flash, such as block
52
 unlock, erase, and programming. The alternate configuration is essentially
53
 mapping Wishbone accesses to the flash's bus.
54
 
55
 CFI Engine Wishbone interface:
56
 
57
 Basic functionality:
58
 Bits [27:26] decode the operation.
59
 2'b00 : read/write to the flash memory
60
 2'b01 : unlock block
61
 2'b10 : erase block
62
 2'b11 : block registers, other flash control features
63
 
64
 0xc00_0000 : block status/control register
65
 bits:
66
 [0]: r/o : CFI controller busy
67
 [1]: w/o : clear flash status register
68
 [2]: w/o : reset flash device and controller
69
 
70
 0xc00_0004 : flash device status register
71
 bits
72
 [7:0] : r/o : flash device status register
73
 
74
 0xe00_0000 : read device identifier information
75
 User is able to access the device identifier information such as:
76
 offset 0x0 : manufacturer code
77
 offset 0x2 : device id
78
 offset bba + 0x4 : block (add increments of 128KB block size)
79
 offset 0xa : read config register
80
 See CFI docs for further details (shift offset left by 1)
81
 
82
 0xe01_0000 : CFI query
83
 User is able to access the CFI query information
84
 The hex offsets in the CFI spec should be shifted left by one before
85
 applying to the Wishbone bus.
86
 
87
 Addresses under 0x000_0000 cause direct access to the flash
88
 Addresses under 0x400_0000 cause the block (addressed in [24:0]) to be unlocked
89
 Addresses under 0x800_0000 cause the block (addressed in [24:0]) to be erased
90
 
91
 */
92
 
93
module cfi_ctrl
94
  (
95
   wb_clk_i, wb_rst_i,
96
 
97
   wb_dat_i, wb_adr_i,
98
   wb_stb_i, wb_cyc_i,
99
   wb_we_i, wb_sel_i,
100
   wb_dat_o, wb_ack_o,
101
   wb_err_o, wb_rty_o,
102
 
103
 
104
   flash_dq_io,
105
   flash_adr_o,
106
   flash_adv_n_o,
107
   flash_ce_n_o,
108
   flash_clk_o,
109
   flash_oe_n_o,
110
   flash_rst_n_o,
111
   flash_wait_i,
112
   flash_we_n_o,
113
   flash_wp_n_o
114
 
115
   );
116
 
117
   parameter flash_dq_width = 16;
118
   parameter flash_adr_width = 24;
119
 
120
   parameter flash_write_cycles = 4; // wlwh/Tclk = 50ns / 15 ns (66Mhz)
121
   parameter flash_read_cycles = 7;  // elqv/Tclk = 95 / 15 ns (66MHz)
122
 
123
   parameter cfi_engine = "ENABLED";
124
 
125
   inout [flash_dq_width-1:0]       flash_dq_io;
126
   output [flash_adr_width-1:0]    flash_adr_o;
127
 
128
   output                          flash_adv_n_o;
129
   output                          flash_ce_n_o;
130
   output                          flash_clk_o;
131
   output                          flash_oe_n_o;
132
   output                          flash_rst_n_o;
133
   input                           flash_wait_i;
134
   output                          flash_we_n_o;
135
   output                          flash_wp_n_o;
136
 
137
 
138
   input                           wb_clk_i, wb_rst_i;
139
 
140
 
141
   input [31:0]             wb_dat_i, wb_adr_i;
142
   input                           wb_stb_i, wb_cyc_i,
143
                                   wb_we_i;
144
   input [3:0]                      wb_sel_i;
145
 
146
   output reg [31:0]                wb_dat_o;
147
   output reg                      wb_ack_o;
148
   output                          wb_err_o, wb_rty_o;
149
 
150
   reg [3:0]                        wb_state;
151
   generate
152
      if (cfi_engine == "ENABLED") begin : cfi_engine_gen
153
         wire                      do_rst, do_init, do_readstatus;
154
         wire                      do_clearstatus, do_eraseblock, do_write,
155
                                   do_read, do_unlockblock;
156
 
157
         /* Track when we have new bus accesses and are currently serving them */
158
         reg                       wb_req_in_progress;
159
         wire                      wb_req_new;
160
         always @(posedge wb_clk_i)
161
           if (wb_rst_i)
162
             wb_req_in_progress <= 0;
163
           else if (wb_req_new)
164
             wb_req_in_progress <= 1'b1;
165
           else if (wb_ack_o)
166
             wb_req_in_progress <= 0;
167
 
168
         assign wb_req_new = (wb_stb_i & wb_cyc_i) & !wb_req_in_progress;
169
 
170
         /* Registers for interfacing with the CFI controller */
171
         reg [15:0]                 cfi_bus_dat_i;
172
         wire [15:0]                cfi_bus_dat_o;
173
         reg [23:0]                 cfi_bus_adr_i;
174
         wire                      cfi_bus_ack_o;
175
         wire                      cfi_bus_busy_o;
176
 
177
         wire                      cfi_rw_sel;
178
         wire                      cfi_unlock_sel;
179
         wire                      cfi_erase_sel;
180
         wire                      cfi_scr_sel;
181
         wire                      cfi_readstatus_sel;
182
         wire                      cfi_clearstatus_sel;
183
         wire                      cfi_rst_sel;
184
         wire                      cfi_busy_sel;
185
         wire                      cfi_readdeviceident_sel;
186
         wire                      cfi_cfiquery_sel;
187
 
188
         reg                       cfi_bus_go;
189
 
190
         reg                       cfi_first_of_two_accesses;
191
 
192
         assign cfi_rw_sel = wb_adr_i[27:26]==2'b00;
193
         assign cfi_unlock_sel = wb_adr_i[27:26]==2'b01 && wb_we_i;
194
         assign cfi_erase_sel = wb_adr_i[27:26]==2'b10 && wb_we_i;
195
         assign cfi_scr_sel = wb_adr_i[27:26]==2'b11 && wb_adr_i[25:0]==26'd0;
196
         assign cfi_readstatus_sel = wb_adr_i[27:26]==2'b11 &&
197
                                     wb_adr_i[25:0]==26'd4 && !wb_we_i;
198
         assign cfi_clearstatus_sel = cfi_scr_sel && wb_dat_i[1] && wb_we_i;
199
         assign cfi_rst_sel = cfi_scr_sel && wb_dat_i[2] && wb_we_i;
200
         assign cfi_busy_sel = cfi_scr_sel & !wb_we_i;
201
         assign cfi_readdeviceident_sel = wb_adr_i[27:26]==2'b11 &&
202
                                          wb_adr_i[25]==1'b1 && !wb_adr_i[16]==1'b1 &&
203
                                          !wb_we_i;
204
 
205
         assign cfi_cfiquery_sel = wb_adr_i[27:26]==2'b11 &&
206
                                   wb_adr_i[25]==1'b1 && wb_adr_i[16]==1'b1 &&
207
                                   !wb_we_i;
208
 
209
 
210
         assign do_rst = cfi_rst_sel & cfi_bus_go;
211
         assign do_init = 0;
212
         assign do_readstatus = cfi_readstatus_sel & cfi_bus_go;
213
         assign do_clearstatus = cfi_clearstatus_sel & cfi_bus_go;
214
         assign do_eraseblock = cfi_erase_sel & cfi_bus_go;
215
         assign do_write = cfi_rw_sel & wb_we_i & cfi_bus_go ;
216
         assign do_read = cfi_rw_sel & !wb_we_i & cfi_bus_go ;
217
         assign do_unlockblock = cfi_unlock_sel & cfi_bus_go ;
218
         assign do_readdeviceident = cfi_readdeviceident_sel & cfi_bus_go ;
219
         assign do_cfiquery = cfi_cfiquery_sel & cfi_bus_go ;
220
 
221
 
222
         /* Main statemachine */
223
`define WB_FSM_IDLE 0
224
`define WB_FSM_CFI_CMD_WAIT 2
225
 
226
         always @(posedge wb_clk_i)
227
           if (wb_rst_i) begin
228
              wb_state <= `WB_FSM_IDLE;
229
              cfi_bus_go <= 0;
230
 
231
              /* Wishbone regs */
232
              wb_dat_o <= 0;
233
              wb_ack_o <= 0;
234
 
235
              cfi_first_of_two_accesses <= 0;
236
 
237
           end
238
           else begin
239
              case (wb_state)
240
                `WB_FSM_IDLE: begin
241
                   wb_ack_o <= 0;
242
                   cfi_bus_go <= 0;
243
                   /* Pickup new incoming accesses */
244
                   /* Potentially get into a state where we received a bus request
245
                    but the CFI was still busy so waited. In this case we'll get a
246
                    ACK from the controller and have a new request registered */
247
                   if (wb_req_new) begin
248
 
249
                      if (cfi_busy_sel) /* want to read the busy flag */
250
                        begin
251
                           wb_ack_o <= 1;
252
                           wb_dat_o <= {30'd0, cfi_bus_busy_o};
253
                        end
254
                      else if (!cfi_bus_busy_o | (wb_req_in_progress & cfi_bus_ack_o))
255
                        begin
256
                           if (cfi_rw_sel | cfi_unlock_sel | cfi_erase_sel |
257
                               cfi_readstatus_sel | cfi_clearstatus_sel |
258
                               cfi_rst_sel | cfi_readdeviceident_sel |
259
                               cfi_cfiquery_sel)
260
                             begin
261
                                wb_state <= `WB_FSM_CFI_CMD_WAIT;
262
                                cfi_bus_go <= 1;
263
 
264
                                if (cfi_rw_sel) begin
265
                                   /* Map address onto the 16-bit word bus*/
266
                                   /* Reads always do full 32-bits, so adjust
267
                                    address accordingly.*/
268
 
269
 
270
                                   /* setup address and number of cycles depending
271
                                    on request */
272
                                   if (wb_we_i) begin /* Writing */
273
                                      /* Only possible to write shorts at a time */
274
                                      cfi_bus_dat_i <= wb_sel_i[1:0]==2'b11 ?
275
                                                       wb_dat_i[15:0] :
276
                                                       wb_dat_i[31:16];
277
                                      cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
278
                                   end
279
                                   else begin /* Reading */
280
                                      /* Full or part word? */
281
                                      if ((&wb_sel_i)) begin /* 32-bits */
282
                                         cfi_first_of_two_accesses <= 1;
283
                                         cfi_bus_adr_i[23:0] <= {wb_adr_i[24:2],1'b0};
284
                                      end
285
                                      else begin /*16-bits or byte */
286
                                         cfi_bus_adr_i[23:0] <= {wb_adr_i[24:1]};
287
                                      end
288
                                   end
289
                                end
290
                                if (cfi_unlock_sel | cfi_erase_sel)
291
                                  cfi_bus_adr_i[23:0] <= wb_adr_i[24:1];
292
                                if (cfi_readdeviceident_sel)
293
                                  cfi_bus_adr_i[23:0] <= {wb_adr_i[24:17],1'b0,
294
                                                          7'd0,wb_adr_i[9:1]};
295
                                if (cfi_cfiquery_sel)
296
                                  cfi_bus_adr_i[23:0] <= {14'd0,wb_adr_i[10:1]};
297
                             end // if (cfi_rw_sel | cfi_unlock_sel | ...
298
                        end // if (!cfi_bus_busy_o | (wb_req_in_progress & ...
299
                   end // if (wb_req_new)
300
                end // case: `WB_FSM_IDLE
301
                `WB_FSM_CFI_CMD_WAIT: begin
302
                   cfi_bus_go <= 0;
303
                   /* Wait for the CFI controller to do its thing */
304
                   if (cfi_bus_ack_o) begin
305
                      if (cfi_rw_sel) begin
306
                         /* Is this the first of two accesses? */
307
                         if (cfi_first_of_two_accesses) begin
308
                            cfi_bus_adr_i <= cfi_bus_adr_i+1;
309
                            cfi_first_of_two_accesses <= 0;
310
                            cfi_bus_go <= 1;
311
                            /* Dealing with a read or a write */
312
                            /*
313
                             if (wb_we_i)
314
                             cfi_bus_dat_i <= wb_dat_i[31:16];
315
                             else
316
                             */
317
                            wb_dat_o[31:16] <= cfi_bus_dat_o;
318
                         end
319
                         else begin
320
                            wb_state <= `WB_FSM_IDLE;
321
                            wb_ack_o <= 1'b1;
322
                            if (!wb_we_i) begin
323
                               if (&wb_sel_i)
324
                                 wb_dat_o[15:0] <= cfi_bus_dat_o;
325
                               else begin
326
                                  case (wb_sel_i)
327
                                    4'b0001 :
328
                                      wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
329
                                    4'b0010:
330
                                      wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
331
                                    4'b0011 :
332
                                      wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
333
                                    4'b0100 :
334
                                      wb_dat_o[31:0] <= {4{cfi_bus_dat_o[7:0]}};
335
                                    4'b1100 :
336
                                      wb_dat_o[31:0] <= {cfi_bus_dat_o,cfi_bus_dat_o};
337
                                    4'b1000 :
338
                                      wb_dat_o[31:0] <= {4{cfi_bus_dat_o[15:8]}};
339
                                  endcase // case (wb_sel_i)
340
                               end
341
 
342
 
343
                            end
344
                         end // else: !if(cfi_first_of_two_accesses)
345
                      end // if (cfi_rw_sel)    
346
                      else begin
347
                         /* All other accesses should be a single go of the CFI
348
                          controller */
349
                         wb_state <= `WB_FSM_IDLE;
350
                         wb_ack_o <= 1'b1;
351
                         /* Get the read status data out */
352
                         if (cfi_readstatus_sel)
353
                           wb_dat_o <= {4{cfi_bus_dat_o[7:0]}};
354
                         if (cfi_readdeviceident_sel | cfi_cfiquery_sel)
355
                           wb_dat_o <= {2{cfi_bus_dat_o[15:0]}};
356
                      end
357
                   end // if (cfi_bus_ack_o)
358
                   else if (cfi_rst_sel)begin
359
                      /* The reset command won't ACK back over the bus, incase
360
                       the FSM hung and it actually reset all of its internals */
361
                      wb_state <= `WB_FSM_IDLE;
362
                      wb_ack_o <= 1'b1;
363
                   end
364
                end // case: `WB_FSM_CFI_CMD_WAIT
365
              endcase // case (wb_state)
366
           end // else: !if(wb_rst_i)
367
 
368
         assign wb_err_o = 0;
369
         assign wb_rty_o = 0;
370
 
371
         cfi_ctrl_engine
372
           # (.cfi_part_wlwh_cycles(flash_write_cycles),
373
              .cfi_part_elqv_cycles(flash_read_cycles)
374
              )
375
         cfi_ctrl_engine0
376
           (
377
            .clk_i(wb_clk_i),
378
            .rst_i(wb_rst_i),
379
 
380
            .do_rst_i(do_rst),
381
            .do_init_i(do_init),
382
            .do_readstatus_i(do_readstatus),
383
            .do_clearstatus_i(do_clearstatus),
384
            .do_eraseblock_i(do_eraseblock),
385
            .do_unlockblock_i(do_unlockblock),
386
            .do_write_i(do_write),
387
            .do_read_i(do_read),
388
            .do_readdeviceident_i(do_readdeviceident),
389
            .do_cfiquery_i(do_cfiquery),
390
 
391
            .bus_dat_o(cfi_bus_dat_o),
392
            .bus_dat_i(cfi_bus_dat_i),
393
            .bus_adr_i(cfi_bus_adr_i),
394
            .bus_req_done_o(cfi_bus_ack_o),
395
            .bus_busy_o(cfi_bus_busy_o),
396
 
397
            .flash_dq_io(flash_dq_io),
398
            .flash_adr_o(flash_adr_o),
399
            .flash_adv_n_o(flash_adv_n_o),
400
            .flash_ce_n_o(flash_ce_n_o),
401
            .flash_clk_o(flash_clk_o),
402
            .flash_oe_n_o(flash_oe_n_o),
403
            .flash_rst_n_o(flash_rst_n_o),
404
            .flash_wait_i(flash_wait_i),
405
            .flash_we_n_o(flash_we_n_o),
406
            .flash_wp_n_o(flash_wp_n_o)
407
 
408
            );
409
      end // if (cfi_engine == "ENABLED")
410
      else begin : cfi_simple
411
 
412
         reg long_read;
413
         reg [4:0] flash_ctr;
414
         reg [3:0] wb_state;
415
 
416
 
417
         reg [flash_dq_width-1:0] flash_dq_o_r;
418
         reg [flash_adr_width-1:0] flash_adr_o_r;
419
         reg                       flash_oe_n_o_r;
420
         reg                       flash_we_n_o_r;
421
         reg                       flash_rst_n_o_r;
422
         wire                      our_flash_oe;
423
 
424
         assign flash_ce_n_o = 0;
425
         assign flash_clk_o = 1;
426
         assign flash_rst_n_o = flash_rst_n_o_r;
427
         assign flash_wp_n_o = 1;
428
         assign flash_adv_n_o = 0;
429
         assign flash_dq_io = (our_flash_oe) ? flash_dq_o_r :
430
                              {flash_dq_width{1'bz}};
431
         assign flash_adr_o = flash_adr_o_r;
432
         assign flash_oe_n_o = flash_oe_n_o_r;
433
         assign flash_we_n_o = flash_we_n_o_r;
434
 
435
 
436
`define WB_STATE_IDLE 0
437
`define WB_STATE_WAIT 1
438
 
439
         assign our_flash_oe = (wb_state == `WB_STATE_WAIT ||
440
                                wb_ack_o) & wb_we_i;
441
 
442
         always @(posedge wb_clk_i)
443
           if (wb_rst_i)
444
             begin
445
                wb_ack_o <= 0;
446
                wb_dat_o <= 0;
447
                wb_state <= `WB_STATE_IDLE;
448
                flash_dq_o_r <= 0;
449
                flash_adr_o_r <= 0;
450
                flash_oe_n_o_r <= 1;
451
                flash_we_n_o_r <= 1;
452
                flash_rst_n_o_r <= 0; /* active */
453
                long_read <= 0;
454
                flash_ctr <= 0;
455
 
456
             end
457
           else begin
458
              if (|flash_ctr)
459
                flash_ctr <= flash_ctr - 1;
460
 
461
              case(wb_state)
462
                `WB_STATE_IDLE: begin
463
                   /* reset some signals to NOP status */
464
                   wb_ack_o <= 0;
465
                   flash_oe_n_o_r <= 1;
466
                   flash_we_n_o_r <= 1;
467
                   flash_rst_n_o_r <= 1;
468
 
469
                   if (wb_stb_i & wb_cyc_i & !wb_ack_o) begin
470
                      flash_adr_o_r <= wb_adr_i[flash_adr_width:1];
471
                      wb_state <= `WB_STATE_WAIT;
472
                      if (wb_adr_i[27]) begin
473
                         /* Reset the flash, no matter the access */
474
                         flash_rst_n_o_r <= 0;
475
                         flash_ctr <= 5'd16;
476
                      end
477
                      else if (wb_we_i) begin
478
                         /* load counter with write cycle counter */
479
                         flash_ctr <= flash_write_cycles - 1;
480
                         /* flash bus write command */
481
                         flash_we_n_o_r <= 0;
482
                         flash_dq_o_r <= (|wb_sel_i[3:2]) ? wb_dat_i[31:16] :
483
                                         wb_dat_i[15:0];
484
                      end
485
                      else begin
486
                         /* load counter with write cycle counter */
487
                         flash_ctr <= flash_read_cycles - 1;
488
                         if (&wb_sel_i)
489
                           long_read <= 1; // Full 32-bit read, 2 read cycles
490
                         flash_oe_n_o_r <= 0;
491
                      end // else: !if(wb_we_i)
492
                   end // if (wb_stb_i & wb_cyc_i)
493
 
494
                end
495
                `WB_STATE_WAIT: begin
496
                   if (!(|flash_ctr)) begin
497
                      if (wb_we_i) begin
498
                         /* write finished */
499
                         wb_ack_o <= 1;
500
                         wb_state <= `WB_STATE_IDLE;
501
                         flash_we_n_o_r <= 1;
502
                      end
503
                      else begin
504
                         /* read finished */
505
                         if (!(&wb_sel_i)) /* short or byte read */ begin
506
                            case (wb_sel_i)
507
                              4'b0001,
508
                              4'b0100:
509
                                wb_dat_o <= {4{flash_dq_io[7:0]}};
510
                              4'b1000,
511
                              4'b0010:
512
                                wb_dat_o <= {4{flash_dq_io[15:8]}};
513
                              default:
514
                                wb_dat_o <= {2{flash_dq_io}};
515
                            endcase // case (wb_sel_i)
516
                            wb_state <= `WB_STATE_IDLE;
517
                            wb_ack_o <= 1;
518
                            flash_oe_n_o_r <= 1;
519
                         end
520
                         else if (long_read) begin
521
                            /* now go on to read next word */
522
                            wb_dat_o[31:16] <= flash_dq_io;
523
                            long_read <= 0;
524
                            flash_ctr <= flash_read_cycles;
525
                            flash_adr_o_r <= flash_adr_o_r + 1;
526
                         end
527
                         else begin
528
                            /* finished two-part read */
529
                            wb_dat_o[15:0] <= flash_dq_io;
530
                            wb_state <= `WB_STATE_IDLE;
531
                            wb_ack_o <= 1;
532
                            flash_oe_n_o_r <= 1;
533
                         end
534
                      end
535
                   end
536
                end
537
 
538
                default:
539
                  wb_state <= `WB_STATE_IDLE;
540
              endcase // case (wb_state)
541
           end // else: !if(wb_rst_i)
542
 
543
      end // block: cfi_simple
544
   endgenerate
545
 
546
endmodule // cfi_ctrl
547
 

powered by: WebSVN 2.1.0

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