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

Subversion Repositories ion

[/] [ion/] [trunk/] [vhdl/] [sdram_controller.vhdl] - Blame information for rev 152

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

Line No. Rev Author Line
1 133 ja_rd
--##############################################################################
2
-- sdram_controller.vhdl -- Interface for 16-bit SDRAM (non-DDR).
3
--
4
-- This module has been tested with a PSC A2V64S40 chip (equivalent to ISSI's
5
-- IS42S16400). Many parameters are still hardcoded (see below) including the
6
-- number of banks.
7
--
8
--
9
--
10
--------------------------------------------------------------------------------
11
-- To Be Done:
12
-- 1) CL and BL are hardcoded, generics are ignored.
13
-- 2) Column width is partially hardcoded (see 'column' signal).
14
-- 3) Auto-refresh logic is missing.
15
-- 4) No. of banks is hardcoded to 4.
16
--
17
--##############################################################################
18
 
19
 
20
library ieee;
21
use ieee.std_logic_1164.all;
22
use ieee.std_logic_arith.all;
23
use ieee.std_logic_unsigned.all;
24
 
25
 
26
package sdram_pkg is
27
 
28
-- Record with all SDRAM control lines; all are outputs, data lines are excluded
29
type sdram_control_t is
30
record
31
    addr            : std_logic_vector(11 downto 0);
32
    ba              : std_logic_vector(1 downto 0);
33
    ldqm            : std_logic;
34
    udqm            : std_logic;
35
    ras_n           : std_logic;
36
    cas_n           : std_logic;
37
    cke             : std_logic;
38
    we_n            : std_logic;
39
    cs_n            : std_logic;
40
end record sdram_control_t;
41
 
42
type sdram_command_t is (
43
    cmd_inhibit,
44
    cmd_nop,
45
    cmd_active,
46
    cmd_read,
47
    cmd_reada,
48
    cmd_write,
49
    cmd_writea,
50
    cmd_burst_terminate,
51
    cmd_precharge,
52
    cmd_auto_refresh,
53
    cmd_self_refresh,
54
    cmd_load_mode_register
55
   );
56
 
57
 
58
end package sdram_pkg;
59
 
60
 
61
library ieee;
62
use ieee.std_logic_1164.all;
63
use ieee.std_logic_arith.all;
64
use ieee.std_logic_unsigned.all;
65
use work.sdram_pkg.all;
66
 
67
 
68
entity sdram_controller is
69
    generic (
70
        CLOCK_PERIOD    : integer := 20; -- Tclk in ns; for reset delay counters
71
        LATENCY         : integer := 2; -- CAS latency in clock cycles
72
        BURST           : integer := 8; -- Rd Burst Length in clock cycles
73
 
74
        ROW_WIDTH       : integer := 12;
75
        COL_WIDTH       : integer := 8
76
    );
77
    port (
78
    clk                 : in std_logic;
79
    reset               : in std_logic;
80
 
81
    -- ***** Cache interface
82
    data_rd             : out std_logic_vector(31 downto 0);
83
    data_wr             : in std_logic_vector(31 downto 0);
84
    data_addr           : in std_logic_vector(31 downto 2);
85
    enable              : in std_logic;
86
    byte_we             : in std_logic_vector(3 downto 0);
87
    rd                  : in std_logic;
88
    wr                  : in std_logic;
89
    busy                : out std_logic;
90
    done                : out std_logic;
91
    rd_data_valid       : out std_logic;
92
    burst_addr          : out std_logic_vector(2 downto 0); --@note1
93
 
94
    -- ***** DRAM interface pins (Tristate buffers not included)
95
    dram_control        : out sdram_control_t;
96
    dram_clk            : out std_logic;
97
    dram_dq_out         : out std_logic_vector(15 downto 0);
98
    dram_dq_in          : in std_logic_vector(15 downto 0)
99
    );
100
end sdram_controller;
101
 
102
architecture simple of sdram_controller is
103
 
104
type sdram_state_t is (
105
    --**** Chip initialization states
106
    init_reset,             -- initial state
107
    init_wait_for_clock,    -- waiting for power & clock to stabilize
108
    init_wait_for_chip,     -- waiting for SDRAM chip to reset
109
    init_precharge_all,     -- Issue PALL
110
    init_wait_trp,          -- Wait for command latency
111
    init_autorefresh,       -- Issue SELF command
112
    init_wait_trfc_0,       -- Wait for command latency
113
    init_wait_trfc_1,       -- Wait for command latency
114
    init_wait_trfc_2,       -- Wait for command latency
115
    init_wait_trfc_3,       -- Wait for command latency
116
    init_load_mode_reg,     -- Issue LMR command
117
    init_wait_tmrd_0,       -- Wait for command latency
118
    init_wait_tmrd_1,       -- Wait for command latency
119
    init_wait_tmrd_2,       -- Wait for command latency
120
 
121
    --**** States for write operation *******************************
122
 
123
    -- Activate target row
124
    write_00_act,           -- Issue ACT command
125
    write_01_act_wait,      -- Wait for command latency
126
    write_02_act_wait,      -- Wait for command latency
127
 
128
    -- Actual write cycles
129
    write_03_whi,           -- Write high halfword
130
    write_04_wlo,           -- Write low halfword, with autoprecharge
131
 
132
    write_05_pre_wait,      -- Wait for autoprecharge delay (tRP)
133
    write_06_pre_wait,      -- 
134
    write_07_pre_wait,      -- 
135
 
136
    idle,                   -- Waiting for r/w request
137
 
138
    --**** states for read operation ********************************
139
 
140
    -- Activate target row
141
    read_00_act,            -- Issue ACT command
142
    read_01_act_wait,       -- Wait for command latency
143
    read_02_act_wait,       -- Wait for command latency
144
 
145
    -- Read burst
146
    read_03_rd,             -- Issue READ command with autoprecharge
147
    read_04_rd_wait,        -- Wait for command latency
148
    read_05_rd_wait,        -- Wait for command latency
149
    read_06_rd_w0hi,        -- On bus: Word 0, HI
150
    read_07_rd_w0lo,        -- On bus: Word 0, LO
151
    read_08_rd_w1hi,        -- On bus: Word 1, HI
152
    read_09_rd_w1lo,        -- On bus: Word 1, LO
153
    read_10_rd_w2hi,        -- On bus: Word 2, HI
154
    read_11_rd_w2lo,        -- On bus: Word 2, LO
155
    read_12_rd_w3hi,        -- On bus: Word 3, HI
156
    read_13_rd_w3lo,        -- On bus: Word 3, LO
157
 
158
    void
159
   );
160
 
161
 
162
signal ps, ns :             sdram_state_t;
163
signal ctr_pause :          integer range 0 to 16383;
164
signal end_pause :          std_logic;
165
 
166
signal ddr_command :        sdram_command_t;
167
signal command_code :       std_logic_vector(3 downto 0);
168
 
169
 
170
signal end_autorefresh_loop : std_logic;
171
signal ctr_auto_refresh :   integer range 0 to 15;
172
 
173
signal byte_we_reg :        std_logic_vector(3 downto 0); --
174
signal data_wr_reg :        std_logic_vector(31 downto 0); --
175
signal data_rd_reg :        std_logic_vector(31 downto 0);
176
signal addr_reg :           std_logic_vector(31 downto 2);
177
signal load_hw_hi :         std_logic;
178
signal load_hw_lo :         std_logic;
179
 
180
signal row :                std_logic_vector(11 downto 0);
181
signal column :             std_logic_vector(9 downto 0);
182
signal bank :               std_logic_vector(1 downto 0);
183
signal halfword_addr :      std_logic;
184
 
185
begin
186
 
187
state_machine_reg:
188
process(clk)
189
begin
190
    if clk'event and clk='1' then
191
        if reset='1' then
192
            ps <= init_reset;
193
        else
194
            ps <= ns;
195
        end if;
196
    end if;
197
end process state_machine_reg;
198
 
199
state_machine_transitions:
200
process(ps,end_pause,end_autorefresh_loop, rd, byte_we, enable)
201
begin
202
    case ps is
203
    when init_reset =>
204
        ns <= init_wait_for_clock;
205
    when init_wait_for_clock =>
206
        if end_pause='1' then
207
            ns <= init_wait_for_chip;
208
        else
209
            ns <= ps;
210
        end if;
211
    when init_wait_for_chip =>
212
        if end_pause='1' then
213
            ns <= init_precharge_all;
214
        else
215
            ns <= ps;
216
        end if;
217
 
218
    when init_precharge_all =>
219
        ns <= init_wait_trp;
220
    when init_wait_trp =>
221
        ns <= init_autorefresh;
222
    when init_autorefresh =>
223
        ns <= init_wait_trfc_0;
224
    when init_wait_trfc_0 =>
225
        ns <= init_wait_trfc_1;
226
    when init_wait_trfc_1 =>
227
        ns <= init_wait_trfc_2;
228
    when init_wait_trfc_2 =>
229
        ns <= init_wait_trfc_3;
230
    when init_wait_trfc_3 =>
231
        ns <= init_load_mode_reg;
232
    when init_load_mode_reg =>
233
        ns <= init_wait_tmrd_0;
234
    when init_wait_tmrd_0 =>
235
        ns <= init_wait_tmrd_1;
236
    when init_wait_tmrd_1 =>
237
        ns <= init_wait_tmrd_2;
238
    when init_wait_tmrd_2 =>
239
        ns <= idle;
240
 
241
 
242
    when idle =>
243
        if rd='1' then
244
            ns <= read_00_act;
245
        elsif wr='1' then
246
            ns <= write_00_act;
247
        else
248
            ns <= ps;
249
        end if;
250
 
251
    when write_00_act =>
252
        ns <= write_01_act_wait;
253
    when write_01_act_wait =>
254
        ns <= write_02_act_wait;
255
    when write_02_act_wait =>
256
        ns <= write_03_whi;
257
    when write_03_whi =>
258
        ns <= write_04_wlo;
259
    when write_04_wlo =>
260
        ns <= write_05_pre_wait;
261
    when write_05_pre_wait =>
262
        ns <= write_06_pre_wait;
263
    when write_06_pre_wait =>
264
        ns <= write_07_pre_wait;
265
    when write_07_pre_wait =>
266
        ns <= idle;
267
 
268
    when read_00_act =>
269
        ns <= read_01_act_wait;
270
    when read_01_act_wait =>
271
        ns <= read_02_act_wait;
272
    when read_02_act_wait =>
273
        ns <= read_03_rd;
274
    when read_03_rd =>
275
        ns <= read_04_rd_wait;
276
    when read_04_rd_wait => -- FIXME RD burst latency hardcoded
277
        --ns <= read_05_rd_wait;
278
        ns <= read_06_rd_w0hi;
279
    when read_05_rd_wait =>
280
        ns <= read_06_rd_w0hi;
281
    when read_06_rd_w0hi =>
282
        ns <= read_07_rd_w0lo;
283
    when read_07_rd_w0lo =>
284
        ns <= read_08_rd_w1hi;
285
    when read_08_rd_w1hi =>
286
        ns <= read_09_rd_w1lo;
287
    when read_09_rd_w1lo =>
288
        ns <= read_10_rd_w2hi;
289
    when read_10_rd_w2hi =>
290
        ns <= read_11_rd_w2lo;
291
    when read_11_rd_w2lo =>
292
        ns <= read_12_rd_w3hi;
293
    when read_12_rd_w3hi =>
294
        ns <= read_13_rd_w3lo;
295
    when read_13_rd_w3lo =>
296
        ns <= idle;
297
 
298
    when void =>
299
        ns <= void;
300
 
301
    when others =>
302
        ns <= init_reset;
303
    end case;
304
end process state_machine_transitions;
305
 
306
 
307
with ps select ddr_command <=
308
    cmd_precharge           when init_precharge_all,
309
    cmd_auto_refresh        when init_autorefresh,
310
    cmd_load_mode_register  when init_load_mode_reg,
311
 
312
    cmd_active              when read_00_act,
313
    cmd_active              when write_00_act,
314
    cmd_write               when write_03_whi,
315
    cmd_writea              when write_04_wlo,
316
    cmd_reada               when read_03_rd,
317
 
318
    cmd_nop                 when others;
319
 
320
-- assert 'busy' when the controller is idle
321
with ps select busy <=
322
    '0' when idle,
323
    '1' when others;
324
 
325
-- assert 'done' for 1 cycle when current operation ends, before clearing 'busy'
326
with ps select done <=
327
    '1' when init_wait_tmrd_2,
328
    '1' when read_13_rd_w3lo,
329
    '1' when write_07_pre_wait,
330
    '0' when others;
331
 
332
--%%%%% Counters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333
 
334
pause_counter:
335
process(clk)
336
begin
337
    if clk'event and clk='1' then
338
        if ps=init_reset then
339
            ctr_pause <= 20000 / CLOCK_PERIOD; -- 20 us -- clock & vcc stable
340
        elsif ps=init_wait_for_clock then
341
            if ctr_pause/=0 then
342
                ctr_pause <= ctr_pause - 1;
343
            else
344
                ctr_pause <= 1000 / CLOCK_PERIOD; -- 1 us -- chip reset
345
            end if;
346
        elsif ps=init_wait_for_chip then
347
            if ctr_pause/=0 then
348
                ctr_pause <= ctr_pause - 1;
349
            end if;
350
        end if;
351
    end if;
352
end process pause_counter;
353
 
354
end_pause <= '1' when ctr_pause=0 else '0';
355
 
356
-- FIXME auto-refresh control logic missing
357
 
358
--init_auto_refresh_counter:
359
--process(clk)
360
--begin
361
--    if clk'event and clk='1' then
362
--        if ps=init_reset then
363
--            ctr_auto_refresh <= 10;
364
--        else
365
--            if ps=init_wait_trfc_3 and ctr_auto_refresh /= 0 then
366
--                ctr_auto_refresh <= ctr_auto_refresh - 1;
367
--            end if;
368
--        end if;
369
--    end if;
370
--end process init_auto_refresh_counter;
371
--
372
--end_autorefresh_loop <= '1' when ctr_auto_refresh = 0 else '0';
373
 
374
 
375
--%%%%% Interface registers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376
 
377
cpu_interface_registers:
378
process(clk)
379
begin
380
    if clk'event and clk='1' then
381
        if ps=idle then
382
            if rd='1' or byte_we/="0000" then
383
                data_wr_reg <= data_wr;
384
                addr_reg <= data_addr;
385
                byte_we_reg <= byte_we;
386
            end if;
387
        end if;
388
    end if;
389
end process cpu_interface_registers;
390
 
391
 
392
 
393
halfword_addr <= '1' when ps=write_04_wlo else '0';
394
-- FIXME zero-padding is not parametrized
395
column  <= "00" & addr_reg(COL_WIDTH downto 2) & halfword_addr;
396
 
397
row     <= addr_reg(COL_WIDTH+ROW_WIDTH downto COL_WIDTH+1);
398
bank    <= addr_reg(COL_WIDTH+ROW_WIDTH+2 downto COL_WIDTH+ROW_WIDTH+1);
399
 
400
--%%%%% Control lines %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401
 
402
with ddr_command select command_code <=
403
    "1111"          when cmd_inhibit,
404
    "0111"          when cmd_nop,
405
    "0011"          when cmd_active,
406
    "0101"          when cmd_read,
407
    "0101"          when cmd_reada,
408
    "0100"          when cmd_write,
409
    "0100"          when cmd_writea,
410
    "0110"          when cmd_burst_terminate,
411
    "0010"          when cmd_precharge,
412
    "0001"          when cmd_self_refresh,
413
    "0001"          when cmd_auto_refresh,
414
    "0000"          when cmd_load_mode_register,
415
    "1111"          when others;
416
 
417
dram_control.cs_n   <= command_code(3);
418
dram_control.ras_n  <= command_code(2);
419
dram_control.cas_n  <= command_code(1);
420
dram_control.we_n   <= command_code(0);
421
 
422
with ps select dram_control.cke <=
423
    '0'             when init_reset,
424
    '1'             when others;
425
 
426
-- FIXME hardcoded BL and CL
427
with ps select dram_control.addr <=
428
--   OOAOOLLLTBBB
429
    "001000100011"  when init_load_mode_reg, -- CL = 2, BL = 8
430
    "010000000000"  when init_precharge_all, -- A10=1 => Precharge ALL banks
431
    row             when read_00_act,
432
    row             when write_00_act,
433
    "00" & column   when write_03_whi,
434
    "01" & column   when write_04_wlo,
435
    "00" & column   when read_03_rd,
436
    "010000000000"  when others;
437
 
438
dram_control.ba <= bank;
439
dram_clk <= clk;
440
 
441
-- DQM[0] is '1' when the byte is NOT to be written to
442
with ps select dram_control.ldqm <=
443
    not byte_we_reg(2)  when write_03_whi,
444
    not byte_we_reg(0)  when write_04_wlo,
445
    '0'                 when others;
446
 
447
-- DQM[1] is '1' when the byte is NOT to be written to
448
with ps select dram_control.udqm <=
449
    not byte_we_reg(3)  when write_03_whi,
450
    not byte_we_reg(1)  when write_04_wlo,
451
    '0'                 when others;
452
 
453
with ps select dram_dq_out <=
454
    data_wr_reg(31 downto 16)  when write_03_whi,
455
    data_wr_reg(15 downto  0)  when others;
456
 
457
data_rd <= data_rd_reg;
458
 
459
with ps select load_hw_hi <=
460
    '1' when read_06_rd_w0hi,
461
    '1' when read_08_rd_w1hi,
462
    '1' when read_10_rd_w2hi,
463
    '1' when read_12_rd_w3hi,
464
    '0' when others;
465
 
466
with ps select load_hw_lo <=
467
    '1' when read_07_rd_w0lo,
468
    '1' when read_09_rd_w1lo,
469
    '1' when read_11_rd_w2lo,
470
    '1' when read_13_rd_w3lo,
471
    '0' when others;
472
 
473
data_valid_ff:
474
process(clk)
475
begin
476
    if clk'event and clk='1' then
477
        -- NOTE: no need to reset this FF, will always be valid when read
478
        rd_data_valid <= load_hw_lo;
479
    end if;
480
end process data_valid_ff;
481
 
482
-- Data RD register is split in two 16-bit halves which are loaded separately
483
data_read_register:
484
process(clk)
485
begin
486
    if clk'event and clk='1' then
487
        if load_hw_hi='1' then
488
            data_rd_reg(31 downto 16) <= dram_dq_in;
489
        end if;
490
        if load_hw_lo='1' then
491
            data_rd_reg(15 downto  0) <= dram_dq_in;
492
        end if;
493
    end if;
494
end process data_read_register;
495
 
496
 
497
end simple;

powered by: WebSVN 2.1.0

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