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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [peripherals/] [mem/] [sdmctrl.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 tarookumic
 
2
 
3
 
4
 
5
----------------------------------------------------------------------------
6
--  This file is a part of the LEON VHDL model
7
--  Copyright (C) 1999  European Space Agency (ESA)
8
--
9
--  This library is free software; you can redistribute it and/or
10
--  modify it under the terms of the GNU Lesser General Public
11
--  License as published by the Free Software Foundation; either
12
--  version 2 of the License, or (at your option) any later version.
13
--
14
--  See the file COPYING.LGPL for the full details of the license.
15
 
16
 
17
-----------------------------------------------------------------------------
18
-- Entity       mctrl
19
-- File         mctrl.vhd
20
-- Author:      Jiri Gaisler - Gaisler Research
21
-- Description: SDRAM memory controller.
22
------------------------------------------------------------------------------
23
 
24
library IEEE;
25
use IEEE.std_logic_1164.all;
26
use IEEE.std_logic_unsigned."+";
27
use IEEE.std_logic_unsigned."-";
28
use IEEE.std_logic_unsigned.conv_integer;
29
use IEEE.std_logic_arith.conv_unsigned;
30
use work.peri_mem_config.all;
31
use work.peri_mem_comp.all;
32
use work.macro.all;
33
use work.amba.all;
34
 
35
entity sdmctrl is
36
  port (
37
    rst    : in  std_logic;
38
    clk    : in  std_logic;
39
    sdi    : in  sdram_in_type;
40
    sdo    : out sdram_out_type;
41
    apbi   : in  apb_slv_in_type;
42
    apbo   : out apb_slv_out_type;
43
    wpo    : in  wprot_out_type;
44
    sdmo   : out sdram_mctrl_out_type
45
  );
46
end;
47
 
48
architecture rtl of sdmctrl is
49
 
50
 
51
type mcycletype is (midle, active, leadout);
52
type sdcycletype is (act1, act2, act3, rd1, rd2, rd3, rd4, rd5, rd6, rd7, rd8,
53
                     wr1, wr2, wr3, wr4, sidle);
54
type icycletype is (iidle, pre, ref1, ref2, lmode, finish);
55
 
56
-- sdram configuration register
57
 
58
type sdram_cfg_type is record
59
  command          : std_logic_vector(1 downto 0);
60
  csize            : std_logic_vector(1 downto 0);
61
  bsize            : std_logic_vector(2 downto 0);
62
  casdel           : std_logic;  -- CAS to data delay: 2/3 clock cycles
63
  trfc             : std_logic_vector(2 downto 0);
64
  trp              : std_logic;  -- precharge to activate: 2/3 clock cycles
65
  refresh          : std_logic_vector(14 downto 0);
66
  renable          : std_logic;
67
end record;
68
 
69
-- local registers
70
 
71
type reg_type is record
72
  hready        : std_logic;
73
  hsel          : std_logic;
74
  bdrive        : std_logic;
75
  burst         : std_logic;
76
  busy          : std_logic;
77
  bdelay        : std_logic;
78
  wprothit      : std_logic;
79
 
80
  mstate        : mcycletype;
81
  sdstate       : sdcycletype;
82
  cmstate       : mcycletype;
83
  istate        : icycletype;
84
 
85
  cfg           : sdram_cfg_type;
86
  trfc          : std_logic_vector(2 downto 0);
87
  refresh       : std_logic_vector(14 downto 0);
88
  sdcsn  : std_logic_vector(1  downto 0);
89
  sdwen  : std_logic;
90
  rasn : std_logic;
91
  casn : std_logic;
92
  dqm  : std_logic_vector(3 downto 0);
93
  -- only needed to keep address lines from switch too much
94
  address       : std_logic_vector(16 downto 2);  -- memory address
95
end record;
96
 
97
 
98
signal r, ri : reg_type;
99
 
100
begin
101
 
102
  ctrl : process(rst, apbi, sdi, wpo, r)
103
  variable v : reg_type;                -- local variables for registers
104
  variable startsd : std_logic;
105
  variable dataout : std_logic_vector(31 downto 0); -- data from memory
106
  variable regsd : std_logic_vector(31 downto 0);   -- data from registers
107
  variable dqm      : std_logic_vector(3 downto 0);
108
  variable raddr    : std_logic_vector(12 downto 0);
109
  variable adec     : std_logic;
110
  variable rams     : std_logic_vector(1 downto 0);
111
  variable hresp    : std_logic_vector(1 downto 0);
112
  variable ba       : std_logic_vector(1 downto 0);
113
 
114
  begin
115
 
116
-- Variable default settings to avoid latches
117
 
118
    v := r; startsd := '0'; v.busy := '0'; hresp := HRESP_OKAY;
119
 
120
    if sdi.hready = '1' then v.hsel := sdi.hsel; end if;
121
    if (sdi.hready and sdi.hsel ) = '1' then
122
      if sdi.htrans(1) = '1' then v.hready := '0'; end if;
123
    end if;
124
 
125
 
126
-- main state
127
 
128
    case sdi.hsize is
129
    when "00" =>
130
      case sdi.rhaddr(1 downto 0) is
131
      when "00" => dqm := "0111";
132
      when "01" => dqm := "1011";
133
      when "10" => dqm := "1101";
134
      when others => dqm := "1110";
135
      end case;
136
    when "01" =>
137
      if sdi.rhaddr(1) = '0' then dqm := "0011"; else  dqm := "1100"; end if;
138
    when others => dqm := "0000";
139
    end case;
140
 
141
-- main FSM
142
 
143
    case r.mstate is
144
    when midle =>
145
      if (v.hsel and sdi.nhtrans(1)) = '1' then
146
        if (r.sdstate = sidle) and (r.cfg.command = "00") and
147
           (r.cmstate = midle) and (sdi.idle = '1')
148
        then startsd := '1'; v.mstate := active; end if;
149
      end if;
150
    when others => null;
151
    end case;
152
 
153
-- generate row and column address size
154
 
155
    case r.cfg.csize is
156
    when "00" => raddr := sdi.haddr(22 downto 10);
157
    when "01" => raddr := sdi.haddr(23 downto 11);
158
    when "10" => raddr := sdi.haddr(24 downto 12);
159
    when others =>
160
      if r.cfg.bsize = "111" then raddr := sdi.haddr(26 downto 14);
161
      else raddr := sdi.haddr(25 downto 13); end if;
162
    end case;
163
 
164
-- generate bank address
165
 
166
    ba := genmux(r.cfg.bsize, sdi.haddr(28 downto 21)) &
167
          genmux(r.cfg.bsize, sdi.haddr(27 downto 20));
168
 
169
-- generate chip select
170
 
171
    adec := genmux(r.cfg.bsize, sdi.haddr(29 downto 22));
172
    rams := adec & not adec;
173
 
174
-- sdram access FSM
175
 
176
    case r.sdstate is
177
    when sidle =>
178
      v.bdelay := '0';
179
      if startsd = '1' then
180
        v.address(16 downto 2) := ba & raddr;
181
        v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
182
      end if;
183
    when act1 =>
184
        v.rasn := '1';
185
        if r.cfg.casdel = '1' then v.sdstate := act2; else
186
          v.sdstate := act3;
187
          v.hready := sdi.hwrite and sdi.htrans(0) and sdi.htrans(1);
188
        end if;
189
        if CFG_PERIMEM_WPROTEN then
190
          v.wprothit := wpo.wprothit;
191
          if wpo.wprothit = '1' then hresp := HRESP_ERROR; end if;
192
        end if;
193
    when act2 =>
194
        v.sdstate := act3;
195
        v.hready := sdi.hwrite and sdi.htrans(0) and sdi.htrans(1);
196
        if CFG_PERIMEM_WPROTEN and (r.wprothit = '1') then
197
          hresp := HRESP_ERROR; v.hready := '0';
198
        end if;
199
    when act3 =>
200
      v.casn := '0';
201
      v.address(14 downto 2) := sdi.rhaddr(13 downto 12) & '0' & sdi.rhaddr(11 downto 2);
202
      v.dqm := dqm; v.burst := r.hready;
203
 
204
      if sdi.hwrite = '1' then
205
 
206
        v.sdstate := wr1; v.sdwen := '0'; v.bdrive := '1';
207
        if sdi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
208
        if CFG_PERIMEM_WPROTEN and (r.wprothit = '1') then
209
          hresp := HRESP_ERROR; v.hready := '1';
210
          v.sdstate := wr1; v.sdwen := '1'; v.bdrive := '0'; v.casn := '1';
211
        end if;
212
      else v.sdstate := rd1; end if;
213
    when wr1 =>
214
      v.address(14 downto 2) := sdi.rhaddr(13 downto 12) & '0' & sdi.rhaddr(11 downto 2);
215
      if (((r.burst and r.hready) = '1') and (sdi.rhtrans = "11"))
216
      and not (CFG_PERIMEM_WPROTEN and (r.wprothit = '1'))
217
      then
218
        v.hready := sdi.htrans(0) and sdi.htrans(1) and r.hready;
219
--      v.hready := sdi.htrans(0) and r.hready;
220
      else
221
        v.sdstate := wr2; v.bdrive := '0'; v.casn := '1'; v.sdwen := '1';
222
        v.dqm := "1111";
223
      end if;
224
    when wr2 =>
225
      v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr3;
226
    when wr3 =>
227
      v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
228
      if (r.cfg.trp = '1') then v.sdstate := wr4;
229
      else v.sdstate := sidle; end if;
230
    when wr4 =>
231
      v.sdstate := sidle;
232
    when rd1 =>
233
--      v.bdelay := r.cfg.casdel;
234
      v.casn := '1';
235
      if CFG_PERIMEM_SDINVCLK then
236
        if r.cfg.casdel = '1' then v.sdstate := rd2;
237
        else
238
          v.sdstate := rd3;
239
          if sdi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; end if;
240
        end if;
241
      else v.sdstate := rd7; end if;
242
 
243
    when rd7 =>
244
      if r.cfg.casdel = '1' then v.sdstate := rd2;
245
      else
246
        v.sdstate := rd3;
247
        if sdi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; end if;
248
      end if;
249
 
250
    when rd2 =>
251
      v.sdstate := rd3;
252
      if sdi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; end if;
253
 
254
      if v.sdwen = '0' then v.dqm := "1111"; end if;
255
    when rd3 =>
256
      v.sdstate := rd4; v.hready := '1';
257
      if r.sdwen = '0' then
258
        v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := "1111";
259
      end if;
260
 
261
    when rd4 =>
262
      v.hready := '1';
263
 
264
      if sdi.htrans /= "11" or (r.sdcsn = "11") then
265
 
266
        v.hready := '0'; v.dqm := "1111";
267
        if (r.sdcsn /= "11") then
268
          v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
269
        else
270
          if r.cfg.trp = '1' then v.sdstate := rd6;
271
          else v.sdstate := sidle; end if;
272
        end if;
273
      end if;
274
    when rd5 =>
275
--      if (r.cfg.trp or (r.hsel and not sdi.rhaddr(30)))= '1' then 
276
      if r.cfg.trp = '1' then
277
        v.sdstate := rd6;
278
      else v.sdstate := sidle; end if;
279
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := "1111";
280
    when rd6 =>
281
      v.sdstate := sidle; v.dqm := "1111";
282
 
283
      v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
284
 
285
    when others =>
286
        v.sdstate := sidle;
287
    end case;
288
 
289
-- sdram commands
290
 
291
    case r.cmstate is
292
    when midle =>
293
      if r.sdstate = sidle then
294
        case r.cfg.command is
295
        when "01" => -- precharge
296
          if (sdi.idle = '1') then
297
            v.busy := '1';
298
            v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
299
            v.address(12) := '1'; v.cmstate := active;
300
          end if;
301
        when "10" => -- auto-refresh
302
          v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
303
          v.cmstate := active;
304
        when "11" =>
305
          if (sdi.idle = '1') then
306
            v.busy := '1';
307
            v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
308
            v.sdwen := '0'; v.cmstate := active;
309
            v.address(15 downto 2) := "000010001" & r.cfg.casdel & "0111";
310
          end if;
311
        when others => null;
312
        end case;
313
      end if;
314
    when active =>
315
      v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
316
      v.sdwen := '1'; v.cfg.command := "00";
317
      v.cmstate := leadout; v.trfc := r.cfg.trfc;
318
    when leadout =>
319
      v.trfc := r.trfc - 1;
320
      if r.trfc = "000" then v.cmstate := midle; end if;
321
 
322
    end case;
323
 
324
-- sdram init
325
 
326
    case r.istate is
327
    when iidle =>
328
      if (sdi.idle and sdi.enable) = '1' then
329
        v.cfg.command := "01"; v.istate := pre;
330
      end if;
331
    when pre =>
332
      if r.cfg.command = "00" then
333
        v.cfg.command := "10"; v.istate := ref1;
334
      end if;
335
    when ref1 =>
336
      if r.cfg.command = "00" then
337
        v.cfg.command := "10"; v.istate := ref2;
338
      end if;
339
    when ref2 =>
340
      if r.cfg.command = "00" then
341
        v.cfg.command := "11"; v.istate := lmode;
342
      end if;
343
    when lmode =>
344
      if r.cfg.command = "00" then
345
        v.istate := finish;
346
      end if;
347
    when others =>
348
      if sdi.enable = '0' then
349
        v.istate := iidle;
350
      end if;
351
    end case;
352
 
353
    if (sdi.hready and sdi.hsel ) = '1' then
354
      if sdi.htrans(1) = '0' then v.hready := '1'; end if;
355
    end if;
356
 
357
-- second part of main fsm
358
 
359
    case r.mstate is
360
    when active =>
361
      if v.hready = '1' then
362
        v.mstate := midle;
363
      end if;
364
    when others => null;
365
    end case;
366
 
367
-- sdram refresh counter
368
 
369
-- pragma translate_off
370
    if not is_x(r.cfg.refresh) then
371
-- pragma translate_on
372
      if (r.cfg.renable = '1') and (r.istate = finish) then
373
        v.refresh := r.refresh - 1;
374
        if (v.refresh(14) and not r.refresh(14))  = '1' then
375
          v.refresh := r.cfg.refresh;
376
          v.cfg.command := "10";
377
        end if;
378
      end if;
379
-- pragma translate_off
380
    end if;
381
-- pragma translate_on
382
 
383
-- APB register access
384
 
385
 
386
    if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then
387
      case apbi.paddr(3 downto 2) is
388
      when "01" =>
389
        if sdi.enable = '1' then
390
          v.cfg.command     :=  apbi.pwdata(20 downto 19);
391
        end if;
392
        v.cfg.csize       :=  apbi.pwdata(22 downto 21);
393
        v.cfg.bsize       :=  apbi.pwdata(25 downto 23);
394
        v.cfg.casdel      :=  apbi.pwdata(26);
395
        v.cfg.trfc        :=  apbi.pwdata(29 downto 27);
396
        v.cfg.trp         :=  apbi.pwdata(30);
397
        v.cfg.renable     :=  apbi.pwdata(31);
398
      when "10" =>
399
        v.cfg.refresh     :=  apbi.pwdata(26 downto 12);
400
        v.refresh         :=  (others => '0');
401
      when others =>
402
      end case;
403
    end if;
404
 
405
    regsd := (others => '0');
406
    case apbi.paddr(3 downto 2) is
407
    when "01" =>
408
      regsd(31 downto 19) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
409
         r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command;
410
    when others =>
411
      regsd(26 downto 12) := r.cfg.refresh;
412
    end case;
413
    apbo.prdata <= regsd;
414
 
415
-- synchronise with sram/prom controller
416
 
417
    if (r.sdstate < wr3) or (v.hsel = '1') then v.busy := '1';end if;
418
    v.busy := v.busy or r.bdelay;
419
 
420
-- generate memory address
421
 
422
    sdmo.address <= v.address;
423
 
424
-- reset
425
 
426
    if rst = '0' then
427
      v.sdstate       := sidle;
428
      v.mstate        := midle;
429
      v.istate        := iidle;
430
      v.cmstate       := midle;
431
      v.hsel          := '0';
432
      v.cfg.command   := "00";
433
      v.cfg.csize     := "10";
434
      v.cfg.bsize     := "000";
435
      v.cfg.casdel    :=  '1';
436
      v.cfg.trfc      := "111";
437
      v.cfg.renable   :=  '0';
438
      v.cfg.trp       :=  '1';
439
      v.dqm           := (others => '1');
440
      v.sdwen         := '1';
441
      v.rasn          := '1';
442
      v.casn          := '1';
443
      v.hready        := '1';
444
    end if;
445
 
446
    ri <= v;
447
 
448
    sdmo.bdrive  <= v.bdrive;
449
 
450
    sdo.sdcke    <= (others => '1');
451
    sdo.sdcsn    <= r.sdcsn;
452
    sdo.sdwen    <= r.sdwen;
453
    sdo.dqm      <= r.dqm;
454
    sdo.rasn     <= r.rasn;
455
    sdo.casn     <= r.casn;
456
    sdmo.busy    <= v.busy or r.busy;
457
    sdmo.aload   <= r.busy and not v.busy;
458
 
459
    sdmo.hready  <= r.hready;
460
 
461
    sdmo.hresp   <= hresp;
462
    sdmo.hsel    <= r.hsel;
463
 
464
  end process;
465
 
466
 
467
    regs : process(clk,rst)
468
    begin
469
 
470
      if rising_edge(clk) then r <= ri; end if;
471
 
472
      if rst = '0' then
473
        r.bdrive <= '0';
474
        r.sdcsn  <= (others => '1');
475
      end if;
476
    end process;
477
 
478
end;
479
 

powered by: WebSVN 2.1.0

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