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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [memctrl/] [sdmctrl.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      sdmctrl
20
-- File:        sdmctrl.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: SDRAM memory controller to fit with LEON2 memory controller.
23
------------------------------------------------------------------------------
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
library grlib;
28
use grlib.amba.all;
29
use grlib.stdlib.all;
30
library gaisler;
31
use gaisler.memctrl.all;
32
 
33
entity sdmctrl is
34
  generic (
35
    pindex  : integer := 0;
36
    invclk  : integer := 0;
37
    fast    : integer := 0;
38
    wprot   : integer := 0;
39
    sdbits  : integer := 32;
40
    pageburst : integer := 0;
41
    mobile  : integer := 0
42
  );
43
  port (
44
    rst    : in  std_ulogic;
45
    clk    : in  std_ulogic;
46
    sdi    : in  sdram_in_type;
47
    sdo    : out sdram_out_type;
48
    apbi   : in  apb_slv_in_type;
49
    wpo    : in  wprot_out_type;
50
    sdmo   : out sdram_mctrl_out_type
51
  );
52
end;
53
 
54
architecture rtl of sdmctrl is
55
 
56
constant WPROTEN  : boolean := (wprot /= 0);
57
constant SDINVCLK : boolean := (invclk /= 0);
58
constant BUS64    : boolean := (sdbits = 64);
59
 
60
constant PM_PD    : std_logic_vector(2 downto 0) := "001";
61
constant PM_SR    : std_logic_vector(2 downto 0) := "010";
62
constant PM_DPD   : std_logic_vector(2 downto 0) := "101";
63
 
64
type mcycletype is (midle, active, leadout);
65
type sdcycletype is (act1, act2, act3, rd1, rd2, rd3, rd4, rd5, rd6, rd7, rd8,
66
                     wr1, wr2, wr3, wr4, wr5, sidle, sref, pd, dpd);
67
type icycletype is (iidle, pre, ref, lmode, emode, finish);
68
 
69
-- sdram configuration register
70
 
71
type sdram_cfg_type is record
72
  command          : std_logic_vector(2 downto 0);
73
  csize            : std_logic_vector(1 downto 0);
74
  bsize            : std_logic_vector(2 downto 0);
75
  casdel           : std_ulogic;  -- CAS to data delay: 2/3 clock cycles
76
  trfc             : std_logic_vector(2 downto 0);
77
  trp              : std_ulogic;  -- precharge to activate: 2/3 clock cycles
78
  refresh          : std_logic_vector(14 downto 0);
79
  renable          : std_ulogic;
80
  pageburst        : std_ulogic;
81
  mobileen        : std_logic_vector(1 downto 0); -- Mobile SD support, Mobile SD enabled
82
  ds              : std_logic_vector(3 downto 0); -- ds(1:0) (ds(3:2) used to detect update)
83
  tcsr            : std_logic_vector(3 downto 0); -- tcrs(1:0) (tcrs(3:2) used to detect update)
84
  pasr            : std_logic_vector(5 downto 0); -- pasr(2:0) (pasr(5:3) used to detect update)
85
  pmode           : std_logic_vector(2 downto 0); -- Power-Saving mode
86
  txsr            : std_logic_vector(3 downto 0); -- Exit Self Refresh timing
87
  cke             : std_ulogic; -- Clock enable
88
end record;
89
 
90
-- local registers
91
 
92
type reg_type is record
93
  hready        : std_ulogic;
94
  hsel          : std_ulogic;
95
  bdrive        : std_ulogic;
96
  burst         : std_ulogic;
97
  busy          : std_ulogic;
98
  bdelay        : std_ulogic;
99
  wprothit      : std_ulogic;
100
  startsd       : std_ulogic;
101
  aload         : std_ulogic;
102
 
103
  mstate        : mcycletype;
104
  sdstate       : sdcycletype;
105
  cmstate       : mcycletype;
106
  istate        : icycletype;
107
  icnt          : std_logic_vector(2 downto 0);
108
 
109
  cfg           : sdram_cfg_type;
110
  trfc          : std_logic_vector(3 downto 0);
111
  refresh       : std_logic_vector(14 downto 0);
112
  sdcsn         : std_logic_vector(1  downto 0);
113
  sdwen         : std_ulogic;
114
  rasn          : std_ulogic;
115
  casn          : std_ulogic;
116
  dqm           : std_logic_vector(7 downto 0);
117
  bsel          : std_ulogic;
118
  haddr         : std_logic_vector(31 downto 10);
119
  -- only needed to keep address lines from switch too much
120
  address       : std_logic_vector(16 downto 2);  -- memory address
121
 
122
  idlecnt       : std_logic_vector(3 downto 0); -- Counter, 16 idle clock sycles before entering Power-Saving mode
123
  sref_tmpcom   : std_logic_vector(2 downto 0); -- Save SD command when exit sref
124
end record;
125
 
126
 
127
signal r, ri : reg_type;
128
 
129
begin
130
 
131
  ctrl : process(rst, apbi, sdi, wpo, r)
132
  variable v : reg_type;                -- local variables for registers
133
  variable startsd : std_ulogic;
134
  variable dataout : std_logic_vector(31 downto 0); -- data from memory
135
  variable haddr   : std_logic_vector(31 downto 0);
136
  variable regsd : std_logic_vector(31 downto 0);   -- data from registers
137
  variable dqm      : std_logic_vector(7 downto 0);
138
  variable raddr    : std_logic_vector(12 downto 0);
139
  variable adec     : std_ulogic;
140
  variable busy     : std_ulogic;
141
  variable aload    : std_ulogic;
142
  variable rams     : std_logic_vector(1 downto 0);
143
  variable hresp    : std_logic_vector(1 downto 0);
144
  variable ba       : std_logic_vector(1 downto 0);
145
  variable lline    : std_logic_vector(2 downto 0);
146
  variable rline    : std_logic_vector(2 downto 0);
147
  variable lineburst : boolean;
148
  variable arefresh : std_logic;
149
  begin
150
 
151
-- Variable default settings to avoid latches
152
 
153
    v := r; startsd := '0'; v.busy := '0'; hresp := HRESP_OKAY;
154
    lline := not r.cfg.casdel &  r.cfg.casdel &  r.cfg.casdel;
155
    rline := not r.cfg.casdel &  r.cfg.casdel &  r.cfg.casdel;
156
    arefresh := '0';
157
 
158
    if sdi.hready = '1' then v.hsel := sdi.hsel; end if;
159
    if (sdi.hready and sdi.hsel ) = '1' then
160
      if sdi.htrans(1) = '1' then v.hready := '0'; end if;
161
    end if;
162
 
163
    if fast = 1 then haddr := sdi.rhaddr; else haddr := sdi.haddr; end if;
164
    if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then
165
      lineburst := true;
166
    else lineburst := false; end if;
167
 
168
-- main state
169
 
170
    case sdi.hsize is
171
    when "00" =>
172
      case sdi.rhaddr(1 downto 0) is
173
      when "00" => dqm := "11110111";
174
      when "01" => dqm := "11111011";
175
      when "10" => dqm := "11111101";
176
      when others => dqm := "11111110";
177
      end case;
178
    when "01" =>
179
      if sdi.rhaddr(1) = '0' then dqm := "11110011"; else  dqm := "11111100"; end if;
180
    when others => dqm := "11110000";
181
    end case;
182
 
183
    if BUS64 and (r.bsel = '1') then
184
      dqm := dqm(3 downto 0) & "1111";
185
    end if;
186
 
187
-- main FSM
188
 
189
    case r.mstate is
190
    when midle =>
191
      if (v.hsel and sdi.nhtrans(1)) = '1' then
192
        if (r.sdstate = sidle) and (r.cfg.command = "000") and
193
           (r.cmstate = midle) and (sdi.idle = '1')
194
        then
195
          if fast = 1 then v.startsd := '1'; else startsd := '1'; end if;
196
          v.mstate := active;
197
        elsif ((r.sdstate = sref) or (r.sdstate = pd) or (r.sdstate = dpd))
198
           and (r.cfg.command = "000") and (r.cmstate = midle) --and (v.hio = '0')
199
        then
200
          v.startsd := '1';
201
          if r.sdstate = dpd then -- Error response when on Deep Power-Down mode
202
            hresp := HRESP_ERROR;
203
          else
204
            v.mstate := active;
205
          end if;
206
        end if;
207
      end if;
208
    when others => null;
209
    end case;
210
 
211
    startsd := r.startsd or startsd;
212
 
213
-- generate row and column address size
214
 
215
    case r.cfg.csize is
216
    when "00" => raddr := haddr(22 downto 10);
217
    when "01" => raddr := haddr(23 downto 11);
218
    when "10" => raddr := haddr(24 downto 12);
219
    when others =>
220
      if r.cfg.bsize = "111" then raddr := haddr(26 downto 14);
221
      else raddr := haddr(25 downto 13); end if;
222
    end case;
223
 
224
-- generate bank address
225
 
226
    ba := genmux(r.cfg.bsize, haddr(28 downto 21)) &
227
          genmux(r.cfg.bsize, haddr(27 downto 20));
228
 
229
-- generate chip select
230
 
231
    if BUS64 then
232
      adec := genmux(r.cfg.bsize, haddr(30 downto 23));
233
      v.bsel := genmux(r.cfg.bsize, sdi.rhaddr(29 downto 22));
234
    else
235
      adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
236
    end if;
237
    if (sdi.srdis = '0') and (r.cfg.bsize = "111") then adec := not adec; end if;
238
    rams := adec & not adec;
239
 
240
    if r.trfc /= "0000" then v.trfc := r.trfc - 1; end if;
241
 
242
    if r.idlecnt /= "0000" then v.idlecnt := r.idlecnt - 1; end if;
243
 
244
-- sdram access FSM
245
 
246
    case r.sdstate is
247
    when sidle =>
248
      v.bdelay := '0';
249
      if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) then
250
        v.address(16 downto 2) := ba & raddr;
251
        v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
252
        v.startsd := '0';
253
      elsif (r.idlecnt = "0000") and (r.cfg.command = "000")
254
            and (r.cmstate = midle) and (r.cfg.mobileen(1) = '1') then
255
        case r.cfg.pmode is
256
        when PM_SR =>
257
          v.cfg.cke := '0'; v.sdstate := sref;
258
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
259
          v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; -- Control minimum duration of Self Refresh mode (= tRAS)
260
        when PM_PD => v.cfg.cke := '0'; v.sdstate := pd;
261
        when PM_DPD =>
262
          v.cfg.cke := '0'; v.sdstate := dpd;
263
          v.sdcsn := (others => '0'); v.sdwen := '0'; v.rasn := '1'; v.casn := '1';
264
        when others =>
265
        end case;
266
      end if;
267
    when act1 =>
268
        v.rasn := '1'; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; v.haddr := sdi.rhaddr(31 downto 10);
269
        if r.cfg.casdel = '1' then v.sdstate := act2; else
270
          v.sdstate := act3;
271
          v.hready := sdi.hwrite and sdi.htrans(0) and sdi.htrans(1);
272
        end if;
273
        if WPROTEN then
274
          v.wprothit := wpo.wprothit;
275
          if wpo.wprothit = '1' then hresp := HRESP_ERROR; end if;
276
        end if;
277
    when act2 =>
278
        v.sdstate := act3;
279
        v.hready := sdi.hwrite and sdi.htrans(0) and sdi.htrans(1);
280
        if WPROTEN and (r.wprothit = '1') then
281
          hresp := HRESP_ERROR; v.hready := '0';
282
        end if;
283
    when act3 =>
284
      v.casn := '0';
285
      v.address(14 downto 2) := sdi.rhaddr(13 downto 12) & '0' & sdi.rhaddr(11 downto 2);
286
      v.dqm := dqm; v.burst := r.hready;
287
 
288
      if sdi.hwrite = '1' then
289
 
290
        v.sdstate := wr1; v.sdwen := '0'; v.bdrive := '1';
291
        if sdi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
292
        if WPROTEN and (r.wprothit = '1') then
293
          hresp := HRESP_ERROR; v.hready := '1';
294
          v.sdstate := wr1; v.sdwen := '1'; v.bdrive := '0'; v.casn := '1';
295
        end if;
296
      else v.sdstate := rd1; end if;
297
    when wr1 =>
298
      v.address(14 downto 2) := sdi.rhaddr(13 downto 12) & '0' & sdi.rhaddr(11 downto 2);
299
      if (((r.burst and r.hready) = '1') and (sdi.rhtrans = "11"))
300
      and not (WPROTEN and (r.wprothit = '1'))
301
      then
302
        v.hready := sdi.htrans(0) and sdi.htrans(1) and r.hready;
303
        if ((sdi.rhaddr(5 downto 2) = "1111") and (r.cfg.command = "100")) then -- exit on refresh
304
          v.hready := '0';
305
        end if;
306
      else
307
        v.sdstate := wr2; v.bdrive := '0'; v.casn := '1'; v.sdwen := '1';
308
        v.dqm := (others => '1');
309
      end if;
310
    when wr2 =>
311
      if (sdi.rhtrans = "10") and (sdi.rhaddr(31 downto 10) = r.haddr) and (r.hsel = '1') then
312
        if sdi.hwrite = '1' then v.hready := '1'; end if; v.sdstate := act3;
313
      elsif (r.trfc(2 downto 1) = "00") then
314
        if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if;
315
        v.sdstate := wr3;
316
      end if;
317
    when wr3 =>
318
      if (sdi.rhtrans = "10") and (sdi.rhaddr(31 downto 10) = r.haddr) and (r.sdwen = '1') and (r.hsel = '1') then
319
        if sdi.hwrite = '1' then v.hready := '1'; end if; v.sdstate := act3;
320
      elsif (r.cfg.trp = '1') then
321
        v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4;
322
      else
323
        v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
324
        if r.trfc = "0000" then v.sdstate := sidle; end if;
325
      end if;
326
    when wr4 =>
327
      v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
328
      if (r.cfg.trp = '1') then v.sdstate := wr5;
329
      else
330
        if r.trfc = "0000" then v.sdstate := sidle; end if;
331
      end if;
332
    when wr5 =>
333
      if r.trfc = "0000" then v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
334
    when rd1 =>
335
      v.casn := '1'; v.sdstate := rd7;
336
      if lineburst and (sdi.htrans = "11") then
337
        if sdi.rhaddr(4 downto 2) = "111" then
338
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
339
          v.address(4 downto 2) := "000"; v.casn := '0';
340
        end if;
341
      end if;
342
    when rd7 =>
343
      v.casn := '1';
344
      if r.cfg.casdel = '1' then
345
        v.sdstate := rd2;
346
        if lineburst and (sdi.htrans = "11") then
347
          if sdi.rhaddr(4 downto 2) = "110" then
348
            v.address(9 downto 5) := r.address(9 downto 5) + 1;
349
            v.address(4 downto 2) := "000"; v.casn := '0';
350
          end if;
351
        end if;
352
      else
353
        v.sdstate := rd3;
354
        if sdi.htrans /= "11" then
355
          if (r.trfc(2 downto 1) = "00") then v.rasn := '0'; v.sdwen := '0'; end if;
356
        elsif lineburst then
357
          if sdi.rhaddr(4 downto 2) = "110" then
358
            v.address(9 downto 5) := r.address(9 downto 5) + 1;
359
            v.address(4 downto 2) := "000"; v.casn := '0';
360
          end if;
361
        end if;
362
      end if;
363
    when rd2 =>
364
      v.casn := '1'; v.sdstate := rd3;
365
      if sdi.htrans /= "11" then -- v.rasn := '0'; v.sdwen := '0';
366
          if (r.trfc(2 downto 1) = "00") then v.rasn := '0'; v.sdwen := '0'; end if;
367
      elsif lineburst then
368
        if sdi.rhaddr(4 downto 2) = "101" then
369
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
370
          v.address(4 downto 2) := "000"; v.casn := '0';
371
        end if;
372
      end if;
373
      if v.sdwen = '0' then v.dqm := (others => '1'); end if;
374
    when rd3 =>
375
      v.sdstate := rd4; v.hready := '1'; v.casn := '1';
376
      if r.sdwen = '0' then
377
        v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1');
378
      elsif lineburst and (sdi.htrans = "11") and (r.casn = '1') then
379
        if sdi.rhaddr(4 downto 2) = ("10" & not r.cfg.casdel) then
380
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
381
          v.address(4 downto 2) := "000"; v.casn := '0';
382
        end if;
383
      end if;
384
 
385
    when rd4 =>
386
      v.hready := '1'; v.casn := '1';
387
      if (sdi.htrans /= "11") or (r.sdcsn = "11") or
388
         ((sdi.rhaddr(5 downto 2) = "1111") and (r.cfg.command = "100")) -- exit on refresh
389
      then
390
        v.hready := '0'; v.dqm := (others => '1');
391
        if (r.sdcsn /= "11") then
392
          v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
393
        else
394
          if r.cfg.trp = '1' then v.sdstate := rd6;
395
          else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
396
        end if;
397
      elsif lineburst then
398
        if (sdi.rhaddr(4 downto 2) = lline) and (r.casn = '1') then
399
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
400
          v.address(4 downto 2) := "000"; v.casn := '0';
401
        end if;
402
      end if;
403
    when rd5 =>
404
      if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
405
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1');
406
      v.casn := '1';
407
    when rd6 =>
408
      v.sdstate := sidle; v.idlecnt := (others => '1'); v.dqm := (others => '1');
409
 
410
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
411
 
412
    when sref =>
413
      if (startsd = '1') -- and (r.hio = '0')) 
414
          or (r.cfg.command /= "000") or r.cfg.pmode /= PM_SR then
415
        if r.trfc = "0000" then -- Minimum duration (= tRAS) 
416
          v.cfg.cke := '1';
417
          v.sdcsn := (others => '0'); v.rasn := '1'; v.casn := '1';
418
        end if;
419
        if r.cfg.cke = '1' then
420
          if (r.idlecnt = "0000") then -- tXSR ns with NOP 
421
            v.sdstate := sidle;
422
            v.idlecnt := (others => '1');
423
            v.sref_tmpcom := r.cfg.command;
424
            v.cfg.command := "100";
425
          end if;
426
        else
427
          v.idlecnt := r.cfg.txsr;
428
        end if;
429
      end if;
430
    when pd =>
431
      if (startsd = '1') -- and (r.hio = '0')) 
432
          or (r.cfg.command /= "000") or r.cfg.pmode /= PM_PD then
433
        v.cfg.cke := '1';
434
        v.sdstate := sidle;
435
        v.idlecnt := (others => '1');
436
      end if;
437
    when dpd =>
438
      v.sdcsn := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1';
439
      v.cfg.renable := '0';
440
      if (startsd = '1') then -- and r.hio = '0') then
441
        v.hready := '1'; -- ack all accesses with Error response
442
        v.startsd := '0';
443
        hresp := HRESP_ERROR;
444
      elsif r.cfg.pmode /= PM_DPD then
445
        v.cfg.cke := '1';
446
        if r.cfg.cke = '1' then
447
          v.sdstate := sidle;
448
          v.idlecnt := (others => '1');
449
          v.cfg.renable := '1';
450
        end if;
451
      end if;
452
    when others =>
453
      v.sdstate := sidle; v.idlecnt := (others => '1');
454
    end case;
455
 
456
-- sdram commands
457
 
458
    case r.cmstate is
459
    when midle =>
460
      if r.sdstate = sidle then
461
        case r.cfg.command is
462
        when "010" => -- precharge
463
          if (sdi.idle = '1') then
464
            v.busy := '1';
465
            v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
466
            v.address(12) := '1'; v.cmstate := active;
467
          end if;
468
        when "100" => -- auto-refresh
469
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
470
          v.cmstate := active;
471
        when "110" =>
472
          if (sdi.idle = '1') then
473
            v.busy := '1';
474
            v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
475
            v.sdwen := '0'; v.cmstate := active;
476
            if lineburst then
477
              v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0011";
478
            else
479
              v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0111";
480
            end if;
481
          end if;
482
        when "111" => -- Load Ext-Mode Reg
483
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
484
          v.sdwen := '0'; v.cmstate := active;
485
          v.address(16 downto 2) := "10000000" & r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0)
486
                                    & r.cfg.pasr(2 downto 0);
487
        when others => null;
488
        end case;
489
      end if;
490
    when active =>
491
      v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
492
      v.sdwen := '1'; --v.cfg.command := "000";
493
      v.cfg.command := r.sref_tmpcom; v.sref_tmpcom := "000";
494
      v.cmstate := leadout; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
495
    when leadout =>
496
      if r.trfc = "0000" then v.cmstate := midle; end if;
497
 
498
    end case;
499
 
500
-- sdram init
501
 
502
    case r.istate is
503
    when iidle =>
504
      v.cfg.cke := '1';
505
      if (sdi.idle and sdi.enable) = '1' and r.cfg.cke = '1' then
506
        v.cfg.command := "010"; v.istate := pre;
507
      end if;
508
    when pre =>
509
      if r.cfg.command = "000" then
510
        v.cfg.command := "100"; v.istate := ref; v.icnt := "111";
511
      end if;
512
    when ref =>
513
      if r.cfg.command = "000" then
514
        v.cfg.command := "100"; v.icnt := r.icnt - 1;
515
        if r.icnt = "000" then v.istate := lmode; v.cfg.command := "110"; end if;
516
      end if;
517
    when lmode =>
518
      if r.cfg.command = "000" then
519
        if r.cfg.mobileen = "11" then
520
          v.cfg.command := "111"; v.istate := emode;
521
        else
522
          v.istate := finish;
523
        end if;
524
      end if;
525
    when emode =>
526
      if r.cfg.command = "000" then
527
        v.istate := finish;
528
      end if;
529
    when others =>
530
      if sdi.enable = '0' and r.sdstate /= dpd then
531
        v.istate := iidle;
532
      end if;
533
    end case;
534
 
535
    if (sdi.hready and sdi.hsel ) = '1' then
536
      if sdi.htrans(1) = '0' then v.hready := '1'; end if;
537
    end if;
538
 
539
-- second part of main fsm
540
 
541
    case r.mstate is
542
    when active =>
543
      if v.hready = '1' then
544
        v.mstate := midle;
545
      end if;
546
    when others => null;
547
    end case;
548
 
549
-- sdram refresh counter
550
 
551
      if (r.cfg.renable = '1') and (r.istate = finish) and r.sdstate /= sref then
552
        v.refresh := r.refresh - 1;
553
        if (v.refresh(14) and not r.refresh(14))  = '1' then
554
          v.refresh := r.cfg.refresh;
555
          v.cfg.command := "100";
556
          arefresh := '1';
557
        end if;
558
      end if;
559
 
560
-- APB register access
561
 
562
 
563
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
564
      case apbi.paddr(3 downto 2) is
565
      when "01" =>
566
        if pageburst = 2 then v.cfg.pageburst :=  apbi.pwdata(17); end if;
567
        if sdi.enable = '1' then
568
          v.cfg.command(2 downto 1)     :=  apbi.pwdata(20 downto 19);
569
        end if;
570
        v.cfg.csize       :=  apbi.pwdata(22 downto 21);
571
        v.cfg.bsize       :=  apbi.pwdata(25 downto 23);
572
        v.cfg.casdel      :=  apbi.pwdata(26);
573
        v.cfg.trfc        :=  apbi.pwdata(29 downto 27);
574
        v.cfg.trp         :=  apbi.pwdata(30);
575
        v.cfg.renable     :=  apbi.pwdata(31);
576
      when "10" =>
577
        v.cfg.refresh     :=  apbi.pwdata(26 downto 12);
578
        v.refresh         :=  (others => '0');
579
      when "11" =>
580
        if r.cfg.mobileen(1) = '1' and mobile /= 3 then v.cfg.mobileen(0) := apbi.pwdata(31); end if;
581
        if r.cfg.pmode = "000" then
582
          v.cfg.cke               :=  apbi.pwdata(30);
583
        end if;
584
        if r.cfg.mobileen(1) = '1' then
585
          if sdi.enable = '1' then
586
            v.cfg.command(0)        :=  apbi.pwdata(29);
587
          end if;
588
          v.cfg.txsr              :=  apbi.pwdata(23 downto 20);
589
          v.cfg.pmode             :=  apbi.pwdata(18 downto 16);
590
          v.cfg.ds(3 downto 2)    :=  apbi.pwdata( 6 downto  5);
591
          v.cfg.tcsr(3 downto 2)  :=  apbi.pwdata( 4 downto  3);
592
          v.cfg.pasr(5 downto 3)  :=  apbi.pwdata( 2 downto  0);
593
        end if;
594
      when others =>
595
      end case;
596
    end if;
597
 
598
    -- Disable CS and DPD when Mobile SDR is Disabled
599
    if r.cfg.mobileen(0) = '0' then v.cfg.pmode(2) := '0'; end if;
600
 
601
    -- Update EMR when ds, tcsr or pasr change
602
    if r.cfg.command = "000" and arefresh = '0' and r.cfg.mobileen(0) = '1' then
603
      if r.cfg.ds(1 downto 0) /= r.cfg.ds(3 downto 2) then
604
        v.cfg.command := "111"; v.cfg.ds(1 downto 0) := r.cfg.ds(3 downto 2);
605
      end if;
606
      if r.cfg.tcsr(1 downto 0) /= r.cfg.tcsr(3 downto 2) then
607
        v.cfg.command := "111"; v.cfg.tcsr(1 downto 0) := r.cfg.tcsr(3 downto 2);
608
      end if;
609
      if r.cfg.pasr(2 downto 0) /= r.cfg.pasr(5 downto 3) then
610
        v.cfg.command := "111"; v.cfg.pasr(2 downto 0) := r.cfg.pasr(5 downto 3);
611
      end if;
612
    end if;
613
 
614
    regsd := (others => '0');
615
    case apbi.paddr(3 downto 2) is
616
    when "01" =>
617
      regsd(31 downto 19) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
618
         r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command(2 downto 1);
619
      if not lineburst then regsd(17) := '1'; end if;
620
      regsd(16) := r.cfg.mobileen(1);
621
    when "11" =>
622
      regsd(31) := r.cfg.mobileen(0);
623
      regsd(30) := r.cfg.cke;
624
      regsd(30) := r.cfg.command(0);
625
      regsd(23 downto 0) := r.cfg.txsr & '0' & r.cfg.pmode & "000000000" &
626
                            r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0) & r.cfg.pasr(2 downto 0);
627
    when others =>
628
      regsd(26 downto 12) := r.cfg.refresh;
629
    end case;
630
    sdmo.prdata <= regsd;
631
 
632
-- synchronise with sram/prom controller
633
 
634
    if fast = 0 then
635
      if (r.sdstate < wr4) or (v.hsel = '1') then v.busy := '1';end if;
636
    else
637
      if (r.sdstate < wr4) or (r.startsd = '1') then v.busy := '1';end if;
638
    end if;
639
    v.busy := v.busy or r.bdelay;
640
    busy := v.busy or r.busy;
641
    v.aload := r.busy and not v.busy;
642
    aload := v.aload;
643
 
644
-- generate memory address
645
 
646
    sdmo.address <= v.address;
647
 
648
-- reset
649
 
650
    if rst = '0' then
651
      v.sdstate       := sidle;
652
      v.mstate        := midle;
653
      v.istate        := iidle;
654
      v.cmstate       := midle;
655
      v.hsel          := '0';
656
      v.cfg.command   := "000";
657
      v.cfg.csize     := "10";
658
      v.cfg.bsize     := "000";
659
      v.cfg.casdel    :=  '1';
660
      v.cfg.trfc      := "111";
661
      v.cfg.renable   :=  '0';
662
      v.cfg.trp       :=  '1';
663
      v.dqm           := (others => '1');
664
      v.sdwen         := '1';
665
      v.rasn          := '1';
666
      v.casn          := '1';
667
      v.hready        := '1';
668
      v.startsd       := '0';
669
      if (pageburst = 2) then
670
        v.cfg.pageburst   :=  '0';
671
      end if;
672
      if mobile >= 2 then v.cfg.mobileen := "11";
673
      elsif mobile = 1 then v.cfg.mobileen := "10";
674
      else v.cfg.mobileen := "00"; end if;
675
      v.cfg.txsr      := (others => '1');
676
      v.cfg.pmode     := (others => '0');
677
      v.cfg.ds        := (others => '0');
678
      v.cfg.tcsr      := (others => '0');
679
      v.cfg.pasr      := (others => '0');
680
      if mobile >= 2 then v.cfg.cke := '0';
681
      else v.cfg.cke       := '1'; end if;
682
      v.sref_tmpcom   := "000";
683
      v.idlecnt := (others => '1');
684
    end if;
685
 
686
    ri <= v;
687
 
688
    sdmo.bdrive  <= v.bdrive;
689
 
690
    --sdo.sdcke    <= (others => '1');
691
    sdo.sdcke    <= (others => r.cfg.cke);
692
    sdo.sdcsn    <= r.sdcsn;
693
    sdo.sdwen    <= r.sdwen;
694
    sdo.dqm      <= r.dqm;
695
    sdo.rasn     <= r.rasn;
696
    sdo.casn     <= r.casn;
697
    sdmo.busy    <= busy;
698
    sdmo.aload   <= aload;
699
 
700
    sdmo.hready  <= r.hready;
701
 
702
    sdmo.hresp   <= hresp;
703
    sdmo.hsel    <= r.hsel;
704
    sdmo.bsel    <= r.bsel;
705
 
706
  end process;
707
 
708
 
709
    regs : process(clk,rst)
710
    begin
711
 
712
      if rising_edge(clk) then
713
        r <= ri;
714
        if rst = '0' then
715
          r.icnt <= (others => '0');
716
        end if;
717
      end if;
718
 
719
      if rst = '0' then
720
        r.bdrive <= '0';
721
        r.sdcsn  <= (others => '1');
722
      end if;
723
    end process;
724
 
725
end;
726
 

powered by: WebSVN 2.1.0

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