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/] [sdctrl.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:  sdctrl
20
-- File:    sdctrl.vhd
21
-- Author:  Jiri Gaisler - Gaisler Research
22
-- Description: 32-bit SDRAM 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 grlib.devices.all;
32
use gaisler.memctrl.all;
33
 
34
entity sdctrl is
35
  generic (
36
    hindex  : integer := 0;
37
    haddr   : integer := 0;
38
    hmask   : integer := 16#f00#;
39
    ioaddr  : integer := 16#000#;
40
    iomask  : integer := 16#fff#;
41
    wprot   : integer := 0;
42
    invclk  : integer := 0;
43
    fast    : integer := 0;
44
    pwron   : integer := 0;
45
    sdbits  : integer := 32;
46
    oepol   : integer := 0;
47
    pageburst : integer := 0;
48
    mobile  : integer := 0
49
  );
50
  port (
51
    rst     : in  std_ulogic;
52
    clk     : in  std_ulogic;
53
    ahbsi   : in  ahb_slv_in_type;
54
    ahbso   : out ahb_slv_out_type;
55
    sdi     : in  sdctrl_in_type;
56
    sdo     : out sdctrl_out_type
57
  );
58
end;
59
 
60
architecture rtl of sdctrl is
61
 
62
constant WPROTEN   : boolean := wprot = 1;
63
constant SDINVCLK  : boolean := invclk = 1;
64
constant BUS64    : boolean := (sdbits = 64);
65
 
66
constant REVISION  : integer := 1;
67
 
68
constant PM_PD    : std_logic_vector(2 downto 0) := "001";
69
constant PM_SR    : std_logic_vector(2 downto 0) := "010";
70
constant PM_DPD   : std_logic_vector(2 downto 0) := "101";
71
 
72
constant std_rammask: Std_Logic_Vector(31 downto 20) :=
73
                        Conv_Std_Logic_Vector(hmask, 12);
74
 
75
constant hconfig : ahb_config_type := (
76
 
77
  4 => ahb_membar(haddr, '1', '1', hmask),
78
  5 => ahb_iobar(ioaddr, iomask),
79
  others => zero32);
80
 
81
type mcycletype is (midle, active, leadout);
82
type sdcycletype is (act1, act2, act3, rd1, rd2, rd3, rd4, rd5, rd6, rd7, rd8,
83
                     wr1, wr2, wr3, wr4, wr5, sidle,
84
                     sref, pd, dpd);
85
type icycletype is (iidle, pre, ref, lmode, emode, finish);
86
 
87
-- sdram configuration register
88
 
89
type sdram_cfg_type is record
90
  command         : std_logic_vector(2 downto 0);
91
  csize           : std_logic_vector(1 downto 0);
92
  bsize           : std_logic_vector(2 downto 0);
93
  casdel          : std_ulogic;  -- CAS to data delay: 2/3 clock cycles
94
  trfc            : std_logic_vector(2 downto 0);
95
  trp             : std_ulogic;  -- precharge to activate: 2/3 clock cycles
96
  refresh         : std_logic_vector(14 downto 0);
97
  renable         : std_ulogic;
98
  pageburst       : std_ulogic;
99
  mobileen        : std_logic_vector(1 downto 0); -- Mobile SD support, Mobile SD enabled
100
  ds              : std_logic_vector(3 downto 0); -- ds(1:0) (ds(3:2) used to detect update)
101
  tcsr            : std_logic_vector(3 downto 0); -- tcrs(1:0) (tcrs(3:2) used to detect update)
102
  pasr            : std_logic_vector(5 downto 0); -- pasr(2:0) (pasr(5:3) used to detect update)
103
  pmode           : std_logic_vector(2 downto 0); -- Power-Saving mode
104
  txsr            : std_logic_vector(3 downto 0); -- Exit Self Refresh timing
105
  cke             : std_ulogic; -- Clock enable
106
end record;
107
 
108
-- local registers
109
 
110
type reg_type is record
111
  hready        : std_ulogic;
112
  hsel          : std_ulogic;
113
  bdrive        : std_ulogic;
114
  nbdrive       : std_ulogic;
115
  burst         : std_ulogic;
116
  wprothit      : std_ulogic;
117
  hio           : std_ulogic;
118
  startsd       : std_ulogic;
119
 
120
  mstate        : mcycletype;
121
  sdstate       : sdcycletype;
122
  cmstate       : mcycletype;
123
  istate        : icycletype;
124
  icnt          : std_logic_vector(2 downto 0);
125
 
126
  haddr         : std_logic_vector(31 downto 0);
127
  hrdata        : std_logic_vector(sdbits-1 downto 0);
128
  hwdata        : std_logic_vector(31 downto 0);
129
  hwrite        : std_ulogic;
130
  htrans        : std_logic_vector(1 downto 0);
131
  hresp         : std_logic_vector(1 downto 0);
132
  size          : std_logic_vector(1 downto 0);
133
 
134
  cfg           : sdram_cfg_type;
135
  trfc          : std_logic_vector(3 downto 0);
136
  refresh       : std_logic_vector(14 downto 0);
137
  sdcsn         : std_logic_vector(1  downto 0);
138
  sdwen         : std_ulogic;
139
  rasn          : std_ulogic;
140
  casn          : std_ulogic;
141
  dqm           : std_logic_vector(7 downto 0);
142
  address       : std_logic_vector(16 downto 2);  -- memory address
143
  bsel          : std_ulogic;
144
 
145
  idlecnt       : std_logic_vector(3 downto 0); -- Counter, 16 idle clock sycles before entering Power-Saving mode
146
  sref_tmpcom   : std_logic_vector(2 downto 0); -- Save SD command when exit sref
147
end record;
148
 
149
signal r, ri : reg_type;
150
signal rbdrive, ribdrive : std_logic_vector(31 downto 0);
151
attribute syn_preserve : boolean;
152
attribute syn_preserve of rbdrive : signal is true;
153
 
154
begin
155
 
156
  ctrl : process(rst, ahbsi, r, sdi, rbdrive)
157
  variable v       : reg_type;                      -- local variables for registers
158
  variable startsd : std_ulogic;
159
  variable dataout : std_logic_vector(31 downto 0); -- data from memory
160
  variable regsd   : std_logic_vector(31 downto 0); -- data from registers
161
  variable dqm     : std_logic_vector(7 downto 0);
162
  variable raddr   : std_logic_vector(12 downto 0);
163
  variable adec    : std_ulogic;
164
  variable rams    : std_logic_vector(1 downto 0);
165
  variable ba      : std_logic_vector(1 downto 0);
166
  variable haddr   : std_logic_vector(31 downto 0);
167
  variable dout    : std_logic_vector(31 downto 0);
168
  variable hsize   : std_logic_vector(1 downto 0);
169
  variable hwrite  : std_ulogic;
170
  variable htrans  : std_logic_vector(1 downto 0);
171
  variable hready  : std_ulogic;
172
  variable vbdrive : std_logic_vector(31 downto 0);
173
  variable bdrive  : std_ulogic;
174
  variable lline    : std_logic_vector(2 downto 0);
175
  variable lineburst : boolean;
176
  variable haddr_tmp : std_logic_vector(31 downto 0);
177
  variable arefresh : std_logic;
178
 
179
  begin
180
 
181
-- Variable default settings to avoid latches
182
 
183
    v := r; startsd := '0'; v.hresp := HRESP_OKAY; vbdrive := rbdrive; arefresh := '0';
184
    v.hrdata(sdbits-1 downto sdbits-32) := sdi.data(sdbits-1 downto sdbits-32);
185
    v.hrdata(31 downto 0) := sdi.data(31 downto 0);
186
    v.hwdata := ahbsi.hwdata;
187
    lline := not r.cfg.casdel &  r.cfg.casdel &  r.cfg.casdel;
188
    if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then
189
      lineburst := true;
190
    else lineburst := false; end if;
191
 
192
 
193
    if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then
194
      v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite;
195
      v.htrans := ahbsi.htrans;
196
      if ahbsi.htrans(1) = '1' then
197
        v.hio := ahbsi.hmbsel(1);
198
        v.hsel := '1'; v.hready := v.hio;
199
      end if;
200
      v.haddr := ahbsi.haddr;
201
      -- addr must be masked since address range can be smaller than
202
      -- total banksize. this can result in wrong chip select being
203
      -- asserted
204
      for i in 31 downto 20 loop
205
        v.haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
206
      end loop;
207
    end if;
208
 
209
    if (r.hsel = '1') and (ahbsi.hready = '0') then
210
      haddr := r.haddr;  hsize := r.size;
211
      htrans := r.htrans; hwrite := r.hwrite;
212
    else
213
      haddr := ahbsi.haddr;  hsize := ahbsi.hsize(1 downto 0);
214
      htrans := ahbsi.htrans; hwrite := ahbsi.hwrite;
215
      -- addr must be masked since address range can be smaller than
216
      -- total banksize. this can result in wrong chip select being
217
      -- asserted
218
      for i in 31 downto 20 loop
219
        haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
220
      end loop;
221
    end if;
222
    if fast = 1 then haddr := r.haddr; end if;
223
 
224
    if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;
225
 
226
-- main state
227
 
228
    case r.size is
229
    when "00" =>
230
      case r.haddr(1 downto 0) is
231
      when "00" => dqm := "11110111";
232
      when "01" => dqm := "11111011";
233
      when "10" => dqm := "11111101";
234
      when others => dqm := "11111110";
235
      end case;
236
    when "01" =>
237
      if r.haddr(1) = '0' then dqm := "11110011"; else  dqm := "11111100"; end if;
238
    when others => dqm := "11110000";
239
    end case;
240
 
241
    if BUS64 and (r.bsel = '1') then dqm := dqm(3 downto 0) & "1111"; end if;
242
 
243
-- main FSM
244
 
245
    case r.mstate is
246
    when midle =>
247
      if ((v.hsel and htrans(1) and not v.hio) = '1') then
248
        if (r.sdstate = sidle) and (r.cfg.command = "000")
249
           and (r.cmstate = midle) and (v.hio = '0')
250
        then
251
          if fast = 0 then startsd := '1';  else v.startsd := '1'; end if;
252
          v.mstate := active;
253
        elsif ((r.sdstate = sref) or (r.sdstate = pd) or (r.sdstate = dpd))
254
           and (r.cfg.command = "000") and (r.cmstate = midle) and (v.hio = '0')
255
        then
256
          v.startsd := '1';
257
          if r.sdstate = dpd then -- Error response when on Deep Power-Down mode
258
            v.hresp := HRESP_ERROR;
259
          else
260
            v.mstate := active;
261
          end if;
262
        end if;
263
      end if;
264
    when others => null;
265
    end case;
266
 
267
    startsd := startsd or r.startsd;
268
 
269
-- generate row and column address size
270
 
271
    case r.cfg.csize is
272
    when "00" => raddr := haddr(22 downto 10);
273
    when "01" => raddr := haddr(23 downto 11);
274
    when "10" => raddr := haddr(24 downto 12);
275
    when others =>
276
      if r.cfg.bsize = "111" then raddr := haddr(26 downto 14);
277
      else raddr := haddr(25 downto 13); end if;
278
    end case;
279
 
280
-- generate bank address
281
 
282
    ba := genmux(r.cfg.bsize, haddr(28 downto 21)) &
283
          genmux(r.cfg.bsize, haddr(27 downto 20));
284
 
285
-- generate chip select
286
 
287
    if BUS64 then
288
      adec := genmux(r.cfg.bsize, haddr(30 downto 23));
289
      v.bsel := genmux(r.cfg.bsize, r.haddr(29 downto 22));
290
    else
291
      adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
292
    end if;
293
 
294
    rams := adec & not adec;
295
 
296
-- sdram access FSM
297
 
298
    if r.trfc /= "0000" then v.trfc := r.trfc - 1; end if;
299
 
300
    if r.idlecnt /= "0000" then v.idlecnt := r.idlecnt - 1; end if;
301
 
302
    case r.sdstate is
303
    when sidle =>
304
      if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) then
305
        v.address(16 downto 2) := ba & raddr;
306
        v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
307
        v.startsd := '0';
308
      elsif (r.idlecnt = "0000") and (r.cfg.command = "000")
309
            and (r.cmstate = midle) and (r.cfg.mobileen(1) = '1') then
310
        case r.cfg.pmode is
311
        when PM_SR =>
312
          v.cfg.cke := '0'; v.sdstate := sref;
313
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
314
          v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; -- Control minimum duration of Self Refresh mode (= tRAS)
315
        when PM_PD => v.cfg.cke := '0'; v.sdstate := pd;
316
        when PM_DPD =>
317
          v.cfg.cke := '0'; v.sdstate := dpd;
318
          v.sdcsn := (others => '0'); v.sdwen := '0'; v.rasn := '1'; v.casn := '1';
319
        when others =>
320
        end case;
321
      end if;
322
    when act1 =>
323
      v.rasn := '1'; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
324
      if r.cfg.casdel = '1' then v.sdstate := act2; else
325
        v.sdstate := act3;
326
        v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
327
      end if;
328
      if WPROTEN then
329
        v.wprothit := sdi.wprot;
330
        if sdi.wprot = '1' then v.hresp := HRESP_ERROR; end if;
331
      end if;
332
    when act2 =>
333
      v.sdstate := act3;
334
      v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
335
      if WPROTEN and (r.wprothit = '1') then
336
        v.hresp := HRESP_ERROR; v.hready := '0';
337
      end if;
338
    when act3 =>
339
      v.casn := '0';
340
      v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
341
      v.dqm := dqm; v.burst := r.hready;
342
 
343
      if r.hwrite = '1' then
344
 
345
        v.sdstate := wr1; v.sdwen := '0'; v.bdrive := '0';
346
        if ahbsi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
347
        if WPROTEN and (r.wprothit = '1') then
348
          v.hresp := HRESP_ERROR; v.hready := '1';
349
          v.sdstate := wr1; v.sdwen := '1'; v.bdrive := '1'; v.casn := '1';
350
        end if;
351
      else v.sdstate := rd1; end if;
352
    when wr1 =>
353
      v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
354
      if (((r.burst and r.hready) = '1') and (r.htrans = "11"))
355
         and not (WPROTEN and (r.wprothit = '1'))
356
      then
357
        v.hready := ahbsi.htrans(0) and ahbsi.htrans(1) and r.hready;
358
        if ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) then -- exit on refresh
359
          v.hready := '0';
360
        end if;
361
      else
362
        v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
363
        v.dqm := (others => '1');
364
      end if;
365
    when wr2 =>
366
      if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if;
367
      v.sdstate := wr3;
368
    when wr3 =>
369
      if (r.cfg.trp = '1') then
370
        v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4;
371
      else
372
        v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1'; v.sdstate := sidle;
373
        v.idlecnt := (others => '1');
374
      end if;
375
    when wr4 =>
376
      v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
377
      if (r.cfg.trp = '1') then v.sdstate := wr5;
378
      else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
379
    when wr5 =>
380
      v.sdstate := sidle; v.idlecnt := (others => '1');
381
    when rd1 =>
382
      v.casn := '1'; v.sdstate := rd7;
383
      if lineburst and (ahbsi.htrans = "11") then
384
        if r.haddr(4 downto 2) = "111" then
385
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
386
          v.address(4 downto 2) := "000"; v.casn := '0';
387
        end if;
388
      end if;
389
    when rd7 =>
390
      v.casn := '1';
391
      if r.cfg.casdel = '1' then
392
        v.sdstate := rd2;
393
        if lineburst and (ahbsi.htrans = "11") then
394
          if r.haddr(4 downto 2) = "110" then
395
            v.address(9 downto 5) := r.address(9 downto 5) + 1;
396
            v.address(4 downto 2) := "000"; v.casn := '0';
397
          end if;
398
        end if;
399
      else
400
        v.sdstate := rd3;
401
        if ahbsi.htrans /= "11" then
402
          if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if;
403
        elsif lineburst then
404
          if r.haddr(4 downto 2) = "110" then
405
            v.address(9 downto 5) := r.address(9 downto 5) + 1;
406
            v.address(4 downto 2) := "000"; v.casn := '0';
407
          end if;
408
        end if;
409
      end if;
410
    when rd2 =>
411
      v.casn := '1'; v.sdstate := rd3;
412
      if ahbsi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0';
413
      elsif lineburst then
414
        if r.haddr(4 downto 2) = "101" then
415
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
416
          v.address(4 downto 2) := "000"; v.casn := '0';
417
        end if;
418
      end if;
419
      if v.sdwen = '0' then v.dqm := (others => '1'); end if;
420
    when rd3 =>
421
      v.sdstate := rd4; v.hready := '1'; v.casn := '1';
422
      if r.sdwen = '0' then
423
        v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1');
424
      elsif lineburst and (ahbsi.htrans = "11") and (r.casn = '1') then
425
        if r.haddr(4 downto 2) = ("10" & not r.cfg.casdel) then
426
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
427
          v.address(4 downto 2) := "000"; v.casn := '0';
428
        end if;
429
      end if;
430
 
431
    when rd4 =>
432
      v.hready := '1'; v.casn := '1';
433
      if (ahbsi.htrans /= "11") or (r.sdcsn = "11") or
434
         ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) -- exit on refresh
435
      then
436
        v.hready := '0'; v.dqm := (others => '1');
437
        if (r.sdcsn /= "11") then
438
          v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
439
        else
440
          if r.cfg.trp = '1' then v.sdstate := rd6;
441
          else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
442
        end if;
443
      elsif lineburst then
444
        if (r.haddr(4 downto 2) = lline) and (r.casn = '1') then
445
          v.address(9 downto 5) := r.address(9 downto 5) + 1;
446
          v.address(4 downto 2) := "000"; v.casn := '0';
447
        end if;
448
      end if;
449
    when rd5 =>
450
      if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
451
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1');
452
      v.casn := '1';
453
    when rd6 =>
454
      v.sdstate := sidle; v.idlecnt := (others => '1'); v.dqm := (others => '1');
455
 
456
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
457
 
458
    when sref =>
459
      if (startsd = '1' and (r.hio = '0'))
460
          or (r.cfg.command /= "000") or r.cfg.pmode /= PM_SR then
461
        if r.trfc = "0000" then -- Minimum duration (= tRAS) 
462
          v.cfg.cke := '1';
463
          v.sdcsn := (others => '0'); v.rasn := '1'; v.casn := '1';
464
        end if;
465
        if r.cfg.cke = '1' then
466
          if (r.idlecnt = "0000") then -- tXSR ns with NOP 
467
            v.sdstate := sidle;
468
            v.idlecnt := (others => '1');
469
            v.sref_tmpcom := r.cfg.command;
470
            v.cfg.command := "100";
471
          end if;
472
        else
473
          v.idlecnt := r.cfg.txsr;
474
        end if;
475
      end if;
476
    when pd =>
477
      if (startsd = '1' and (r.hio = '0'))
478
          or (r.cfg.command /= "000") or r.cfg.pmode /= PM_PD then
479
        v.cfg.cke := '1';
480
        v.sdstate := sidle;
481
        v.idlecnt := (others => '1');
482
      end if;
483
    when dpd =>
484
      v.sdcsn := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1';
485
      v.cfg.renable := '0';
486
      if (startsd = '1' and r.hio = '0') then
487
        v.hready := '1'; -- ack all accesses with Error response
488
        v.startsd := '0';
489
        v.hresp := HRESP_ERROR;
490
      elsif r.cfg.pmode /= PM_DPD then
491
        v.cfg.cke := '1';
492
        if r.cfg.cke = '1' then
493
          v.sdstate := sidle;
494
          v.idlecnt := (others => '1');
495
          v.cfg.renable := '1';
496
        end if;
497
      end if;
498
    when others =>
499
      v.sdstate := sidle; v.idlecnt := (others => '1');
500
    end case;
501
 
502
-- sdram commands
503
 
504
    case r.cmstate is
505
    when midle =>
506
      if r.sdstate = sidle then
507
        case r.cfg.command is
508
        when "010" => -- precharge
509
          v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
510
          v.address(12) := '1'; v.cmstate := active;
511
        when "100" => -- auto-refresh
512
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
513
          v.cmstate := active;
514
        when "110" => -- Lodad Mode Reg
515
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
516
          v.sdwen := '0'; v.cmstate := active;
517
          if lineburst then
518
            v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0011";
519
          else
520
            v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0111";
521
          end if;
522
        when "111" => -- Load Ext-Mode Reg
523
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
524
          v.sdwen := '0'; v.cmstate := active;
525
          v.address(16 downto 2) := "10000000" & r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0)
526
                                    & r.cfg.pasr(2 downto 0);
527
        when others => null;
528
        end case;
529
      end if;
530
    when active =>
531
      v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
532
      v.sdwen := '1'; --v.cfg.command := "000";
533
      v.cfg.command := r.sref_tmpcom; v.sref_tmpcom := "000";
534
      v.cmstate := leadout; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
535
    when leadout =>
536
      if r.trfc = "0000" then v.cmstate := midle; end if;
537
 
538
    end case;
539
 
540
-- sdram init
541
 
542
    case r.istate is
543
    when iidle =>
544
      v.cfg.cke := '1';
545
      if r.cfg.renable = '1' and r.cfg.cke = '1' then
546
        v.cfg.command := "010"; v.istate := pre;
547
      end if;
548
    when pre =>
549
      if r.cfg.command = "000" then
550
        v.cfg.command := "100"; v.istate := ref; v.icnt := "111";
551
      end if;
552
    when ref =>
553
      if r.cfg.command = "000" then
554
        v.cfg.command := "100"; v.icnt := r.icnt - 1;
555
        if r.icnt = "000" then v.istate := lmode; v.cfg.command := "110"; end if;
556
      end if;
557
    when lmode =>
558
      if r.cfg.command = "000" then
559
        if r.cfg.mobileen = "11" then
560
          v.cfg.command := "111"; v.istate := emode;
561
        else
562
          v.istate := finish;
563
        end if;
564
      end if;
565
    when emode =>
566
      if r.cfg.command = "000" then
567
        v.istate := finish;
568
      end if;
569
    when others =>
570
      if r.cfg.renable = '0' and r.sdstate /= dpd then
571
        v.istate := iidle;
572
      end if;
573
    end case;
574
 
575
    if (ahbsi.hready and ahbsi.hsel(hindex) ) = '1' then
576
      if ahbsi.htrans(1) = '0' then v.hready := '1'; end if;
577
    end if;
578
 
579
    if (r.hsel and r.hio and not r.hready) = '1' then v.hready := '1'; end if;
580
 
581
-- second part of main fsm
582
 
583
    case r.mstate is
584
    when active =>
585
      if v.hready = '1' then
586
        v.mstate := midle;
587
      end if;
588
    when others => null;
589
    end case;
590
 
591
-- sdram refresh counter
592
 
593
-- pragma translate_off
594
    if not is_x(r.cfg.refresh) then
595
-- pragma translate_on
596
      if (r.cfg.renable = '1') and (r.istate = finish) and r.sdstate /= sref then
597
        v.refresh := r.refresh - 1;
598
        if (v.refresh(14) and not r.refresh(14))  = '1' then
599
          v.refresh := r.cfg.refresh;
600
          v.cfg.command := "100";
601
          arefresh := '1';
602
        end if;
603
      end if;
604
-- pragma translate_off
605
    end if;
606
-- pragma translate_on
607
 
608
-- AHB register access
609
 
610
    if (r.hsel and r.hio and r.hwrite and r.htrans(1)) = '1' then
611
      if r.haddr(3 downto 2) = "00" then
612
        if pageburst = 2 then v.cfg.pageburst :=  ahbsi.hwdata(17); end if;
613
        v.cfg.command   :=  ahbsi.hwdata(20 downto 18);
614
        v.cfg.csize     :=  ahbsi.hwdata(22 downto 21);
615
        v.cfg.bsize     :=  ahbsi.hwdata(25 downto 23);
616
        v.cfg.casdel    :=  ahbsi.hwdata(26);
617
        v.cfg.trfc      :=  ahbsi.hwdata(29 downto 27);
618
        v.cfg.trp       :=  ahbsi.hwdata(30);
619
        v.cfg.renable   :=  ahbsi.hwdata(31);
620
        v.cfg.refresh   :=  ahbsi.hwdata(14 downto 0);
621
        v.refresh       :=  (others => '0');
622
      elsif r.haddr(3 downto 2) = "01" then
623
        if r.cfg.mobileen(1) = '1' and mobile /= 3 then v.cfg.mobileen(0) := ahbsi.hwdata(31); end if;
624
        if r.cfg.pmode = "000" then
625
          v.cfg.cke               :=  ahbsi.hwdata(30);
626
        end if;
627
        if r.cfg.mobileen(1) = '1' then
628
          v.cfg.txsr              :=  ahbsi.hwdata(23 downto 20);
629
          v.cfg.pmode             :=  ahbsi.hwdata(18 downto 16);
630
          v.cfg.ds(3 downto 2)    :=  ahbsi.hwdata( 6 downto  5);
631
          v.cfg.tcsr(3 downto 2)  :=  ahbsi.hwdata( 4 downto  3);
632
          v.cfg.pasr(5 downto 3)  :=  ahbsi.hwdata( 2 downto  0);
633
        end if;
634
      end if;
635
    end if;
636
 
637
    -- Disable CS and DPD when Mobile SDR is Disabled
638
    if r.cfg.mobileen(0) = '0' then v.cfg.pmode(2) := '0'; end if;
639
 
640
    -- Update EMR when ds, tcsr or pasr change
641
    if r.cfg.command = "000" and arefresh = '0' and r.cfg.mobileen(0) = '1' then
642
      if r.cfg.ds(1 downto 0) /= r.cfg.ds(3 downto 2) then
643
        v.cfg.command := "111"; v.cfg.ds(1 downto 0) := r.cfg.ds(3 downto 2);
644
      end if;
645
      if r.cfg.tcsr(1 downto 0) /= r.cfg.tcsr(3 downto 2) then
646
        v.cfg.command := "111"; v.cfg.tcsr(1 downto 0) := r.cfg.tcsr(3 downto 2);
647
      end if;
648
      if r.cfg.pasr(2 downto 0) /= r.cfg.pasr(5 downto 3) then
649
        v.cfg.command := "111"; v.cfg.pasr(2 downto 0) := r.cfg.pasr(5 downto 3);
650
      end if;
651
    end if;
652
 
653
    regsd := (others => '0');
654
 
655
    if r.haddr(3 downto 2) = "00" then
656
      regsd(31 downto 18) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
657
                             r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command;
658
      if not lineburst then regsd(17) := '1'; end if;
659
      regsd(16) := r.cfg.mobileen(1);
660
      if BUS64 then regsd(15) := '1'; end if;
661
      regsd(14 downto 0) := r.cfg.refresh;
662
    elsif r.haddr(3 downto 2) = "01" then
663
      regsd(31) := r.cfg.mobileen(0);
664
      regsd(30) := r.cfg.cke;
665
      regsd(23 downto 0) := r.cfg.txsr & '0' & r.cfg.pmode & "000000000" &
666
                            r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0) & r.cfg.pasr(2 downto 0);
667
    end if;
668
 
669
    if (r.hsel and r.hio) = '1' then dout := regsd;
670
    else
671
      if BUS64 and r.bsel = '1' then dout := r.hrdata(63 downto 32);
672
      else dout := r.hrdata(31 downto 0); end if;
673
    end if;
674
 
675
    v.nbdrive := not v.bdrive;
676
 
677
    if oepol = 1 then bdrive := r.nbdrive; vbdrive := (others => v.nbdrive);
678
    else bdrive := r.bdrive; vbdrive := (others => v.bdrive);end if;
679
 
680
-- reset
681
 
682
    if rst = '0' then
683
      v.sdstate       := sidle;
684
      v.mstate        := midle;
685
      v.istate        := iidle;
686
      v.cmstate       := midle;
687
      v.hsel          := '0';
688
      v.cfg.command   := "000";
689
      v.cfg.csize     := "10";
690
      v.cfg.bsize     := "000";
691
      v.cfg.casdel    :=  '1';
692
      v.cfg.trfc      := "111";
693
      if pwron = 1 then v.cfg.renable :=  '1';
694
      else v.cfg.renable :=  '0'; end if;
695
      v.cfg.trp       :=  '1';
696
      v.dqm           := (others => '1');
697
      v.sdwen         := '1';
698
      v.rasn          := '1';
699
      v.casn          := '1';
700
      v.hready        := '1';
701
      v.bsel          := '0';
702
      v.startsd       := '0';
703
      if (pageburst = 2) then
704
        v.cfg.pageburst   :=  '0';
705
      end if;
706
      if mobile >= 2 then v.cfg.mobileen := "11";
707
      elsif mobile = 1 then v.cfg.mobileen := "10";
708
      else v.cfg.mobileen := "00"; end if;
709
      v.cfg.txsr      := (others => '1');
710
      v.cfg.pmode     := (others => '0');
711
      v.cfg.ds        := (others => '0');
712
      v.cfg.tcsr      := (others => '0');
713
      v.cfg.pasr      := (others => '0');
714
      if mobile >= 2 then v.cfg.cke := '0';
715
      else v.cfg.cke       := '1'; end if;
716
      v.sref_tmpcom   := "000";
717
      v.idlecnt := (others => '1');
718
    end if;
719
 
720
    ri <= v;
721
    ribdrive <= vbdrive;
722
 
723
    ahbso.hready  <= r.hready;
724
    ahbso.hresp   <= r.hresp;
725
    ahbso.hrdata  <= dout;
726
    ahbso.hcache  <= not r.hio;
727
 
728
  end process;
729
 
730
  --sdo.sdcke     <= (others => '1');
731
  sdo.sdcke     <= (others => r.cfg.cke);
732
  ahbso.hconfig <= hconfig;
733
  ahbso.hirq    <= (others => '0');
734
  ahbso.hindex  <= hindex;
735
  ahbso.hsplit  <= (others => '0');
736
 
737
  regs : process(clk, rst) begin
738
    if rising_edge(clk) then
739
      r <= ri; rbdrive <= ribdrive;
740
      if rst = '0' then r.icnt <= (others => '0'); end if;
741
    end if;
742
    if (rst = '0') then
743
      r.sdcsn  <= (others => '1'); r.bdrive <= '1'; r.nbdrive <= '0';
744
      if oepol = 0 then rbdrive <= (others => '1');
745
      else rbdrive <= (others => '0'); end if;
746
    end if;
747
  end process;
748
 
749
  rgen : if not SDINVCLK generate
750
    sdo.address  <= r.address;
751
    sdo.bdrive   <= r.nbdrive when oepol = 1 else r.bdrive;
752
    sdo.vbdrive  <= rbdrive;
753
    sdo.sdcsn    <= r.sdcsn;
754
    sdo.sdwen    <= r.sdwen;
755
    sdo.dqm      <= "11111111" & r.dqm;
756
    sdo.rasn     <= r.rasn;
757
    sdo.casn     <= r.casn;
758
    sdo.data(31 downto 0) <= r.hwdata;
759
  end generate;
760
 
761
  ngen : if SDINVCLK generate
762
    nregs : process(clk, rst) begin
763
      if falling_edge(clk) then
764
        sdo.address  <= r.address;
765
        if oepol = 1 then sdo.bdrive <= r.nbdrive;
766
        else sdo.bdrive <= r.bdrive; end if;
767
        sdo.vbdrive  <= rbdrive;
768
        sdo.sdcsn    <= r.sdcsn;
769
        sdo.sdwen    <= r.sdwen;
770
        sdo.dqm      <= "11111111" & r.dqm;
771
        sdo.rasn     <= r.rasn;
772
        sdo.casn     <= r.casn;
773
        sdo.data(31 downto 0) <= r.hwdata;
774
      end if;
775
      if rst = '0' then sdo.sdcsn <= (others => '1'); end if;
776
    end process;
777
  end generate;
778
 
779
-- pragma translate_off
780
  bootmsg : report_version
781
  generic map ("sdctrl" & tost(hindex) &
782
    ": PC133 SDRAM controller rev " & tost(REVISION));
783
-- pragma translate_on
784
 
785
end;
786
 

powered by: WebSVN 2.1.0

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