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

Subversion Repositories ion

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

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

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

powered by: WebSVN 2.1.0

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