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

Subversion Repositories sdram_ctrl

[/] [sdram_ctrl/] [trunk/] [src/] [sdram_ctrl.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 ntpqa
------------------------------------------------------------------
2
--                                                              
3
-- sdram_ctrl.vhd                                          
4
--                                                                                          
5
-- Module Description:                                          
6
-- SDRAM small&fast controller
7
-- 
8
--                                                              
9
-- To Do:        
10
-- multichipselect support
11
-- configurable times 
12
-- nios simulation support
13
--                                                              
14
-- Author(s):                                                   
15
-- Aleksey Kuzmenok, ntpqa@opencores.org                      
16
--                                                              
17
------------------------------------------------------------------
18
--                                                              
19
-- Copyright (C) 2006 Aleksey Kuzmenok and OPENCORES.ORG        
20
--                                                              
21
-- This module is free software; you can redistribute it and/or
22
-- modify it under the terms of the GNU Lesser General Public
23
-- License as published by the Free Software Foundation; either
24
-- version 2.1 of the License, or (at your option) any later version.
25
--
26
-- This module is distributed in the hope that it will be useful,
27
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
28
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29
-- Lesser General Public License for more details.
30
--
31
-- You should have received a copy of the GNU Lesser General Public
32
-- License along with this software; if not, write to the Free Software
33
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA            
34
--                                                              
35
------------------------------------------------------------------
36
-- Test results                                                                                                                                                                 
37
-- FPGA                     SDRAM                                CLK (not less than)
38
-- EP1C12XXXXC8             MT48LC4M32B2TG-7:G           125 MHz
39
-- EP1C6XXXXC8              IS42S16100C1-7TL             125 MHz   
40
--
41
------------------------------------------------------------------
42
 
43
LIBRARY ieee;
44
USE ieee.std_logic_1164.ALL;
45
USE ieee.numeric_std.ALL;
46
LIBRARY altera_mf;
47
USE altera_mf.altera_mf_components.all;
48
 
49
entity sdram_ctrl is
50
        generic(
51
                DATA_WIDTH: integer:=32;
52
                BANK_WIDTH: integer:=4;
53
                ROW_WIDTH: integer:=12;
54
                COLUMN_WIDTH: integer:=8;
55
 
56
                clk_MHz: integer:=120
57
                );
58
        port(
59
                signal clk : IN STD_LOGIC;
60
                signal reset : IN STD_LOGIC;
61
 
62
                -- IMPORTANT: for this Avalon(tm) interface 
63
                -- 'Minimum Arbitration Shares'=1 
64
                -- 'Max Pending Read Transactions'=9
65
                signal avs_nios_chipselect : IN STD_LOGIC;
66
                signal avs_nios_address : IN STD_LOGIC_VECTOR ((BANK_WIDTH+ROW_WIDTH+COLUMN_WIDTH-1) DOWNTO 0);
67
                signal avs_nios_byteenable : IN STD_LOGIC_VECTOR (((DATA_WIDTH/8)-1) DOWNTO 0);
68
                signal avs_nios_writedata : IN STD_LOGIC_VECTOR ((DATA_WIDTH-1) DOWNTO 0);
69
                signal avs_nios_write : IN STD_LOGIC;
70
                signal avs_nios_read : IN STD_LOGIC;
71
                signal avs_nios_waitrequest : OUT STD_LOGIC;
72
                signal avs_nios_readdata : OUT STD_LOGIC_VECTOR ((DATA_WIDTH-1) DOWNTO 0);
73
                signal avs_nios_readdatavalid : OUT STD_LOGIC;
74
 
75
                -- global export signals
76
                signal sdram_cke : OUT STD_LOGIC;                       -- This pin has fixed state '1'
77
                signal sdram_ba : OUT STD_LOGIC_VECTOR ((BANK_WIDTH-1) DOWNTO 0);
78
                signal sdram_addr : OUT STD_LOGIC_VECTOR ((ROW_WIDTH-1) DOWNTO 0);
79
                signal sdram_cs_n : OUT STD_LOGIC;                      -- This pin has fixed state '0'
80
                signal sdram_ras_n : OUT STD_LOGIC;
81
                signal sdram_cas_n : OUT STD_LOGIC;
82
                signal sdram_we_n : OUT STD_LOGIC;
83
                signal sdram_dq : INOUT STD_LOGIC_VECTOR ((DATA_WIDTH-1) DOWNTO 0);
84
                signal sdram_dqm : OUT STD_LOGIC_VECTOR (((DATA_WIDTH/8)-1) DOWNTO 0)
85
                );
86
end sdram_ctrl;
87
 
88
architecture behaviour of sdram_ctrl is
89
 
90
        CONSTANT FIFO_WIDTH: integer:=BANK_WIDTH+ROW_WIDTH+COLUMN_WIDTH+DATA_WIDTH+(DATA_WIDTH/8)+2;
91
 
92
        CONSTANT MODE: std_logic_vector(11 downto 0):="000000110000";    -- 1 word burst, CAS latency=3
93
        -- Only two times are configurable
94
        -- tINIT delay between powerup and load mode register = 100 us 
95
        -- tREF refresh period = 15.625 us  (64ms/4096rows)
96
        CONSTANT INIT_PAUSE_CLOCKS: integer:=(clk_MHz*10000)/91;        -- 109.9 us just to be on the save side
97
        CONSTANT REFRESH_PERIOD_CLOCKS: integer:=(clk_MHz*1000)/65;     -- 15.384 us the same purpose
98
        CONSTANT CAS_LATENCY: integer:=3;                               -- other latencies weren't been tested!
99
 
100
        COMPONENT scfifo
101
                GENERIC (
102
                        add_ram_output_register         : STRING;
103
                        intended_device_family          : STRING;
104
                        lpm_numwords            : NATURAL;
105
                        lpm_showahead           : STRING;
106
                        lpm_type                : STRING;
107
                        lpm_width               : NATURAL;
108
                        lpm_widthu              : NATURAL;
109
                        overflow_checking               : STRING;
110
                        underflow_checking              : STRING;
111
                        use_eab         : STRING
112
                        );
113
                PORT (
114
                        rdreq   : IN STD_LOGIC ;
115
                        empty   : OUT STD_LOGIC ;
116
                        aclr    : IN STD_LOGIC ;
117
                        clock   : IN STD_LOGIC ;
118
                        q       : OUT STD_LOGIC_VECTOR ((FIFO_WIDTH-1) DOWNTO 0);
119
                        wrreq   : IN STD_LOGIC ;
120
                        data    : IN STD_LOGIC_VECTOR ((FIFO_WIDTH-1) DOWNTO 0);
121
                        full    : OUT STD_LOGIC
122
                        );
123
        END COMPONENT;
124
 
125
        -- If you ask me why there are so many states, I'll answer that all times are fixed.
126
        -- The top speed for MT48LC4M32B2TG-7:G is 7 ns, therefore all times were based on it.
127
        -- tRP PRECHARGE command period = 3 clocks
128
        -- tRFC AUTO REFRESH period = 10 clocks 
129
        -- tMRD LOAD MODE REGISTER command to ACTIVE or REFRESH command = 2 clocks
130
        -- tRCD ACTIVE to READ or WRITE delay = 3 clocks
131
        -- tRAS ACTIVE to PRECHARGE command = 7 clocks 
132
        -- tRC ACTIVE to ACTIVE command period = 10 clocks
133
        -- tWR2 Write recovery time = 2 clocks
134
        type states is (
135
        INIT0,INIT1,INIT2,INIT3,INIT4,INIT5,INIT6,INIT7,
136
        INIT8,INIT9,INIT10,INIT11,INIT12,INIT13,INIT14,INIT15,
137
        INIT16,INIT17,INIT18,INIT19,INIT20,INIT21,INIT22,INIT23,INIT24,
138
        REFRESH0,REFRESH1,REFRESH2,REFRESH3,REFRESH4,REFRESH5,REFRESH6,REFRESH7,
139
        REFRESH8,REFRESH9,REFRESH10,REFRESH11,REFRESH12,REFRESH13,REFRESH14,
140
        ACTIVE0,ACTIVE1,ACTIVE2,ACTIVE3,ACTIVE4,
141
        IDLE,READ0,WRITE0);
142
        signal operation: states;
143
 
144
        signal fifo_q: std_logic_vector((FIFO_WIDTH-1) downto 0);
145
 
146
        signal init_counter: unsigned(15 downto 0):=to_unsigned(INIT_PAUSE_CLOCKS,16);
147
        signal refresh_counter: unsigned(15 downto 0);
148
        signal active_counter: unsigned(2 downto 0);
149
        signal active_address: unsigned((BANK_WIDTH+ROW_WIDTH-1) downto 0);
150
 
151
        signal bank: std_logic_vector((sdram_ba'length-1) downto 0);
152
        signal row: std_logic_vector((sdram_addr'length-1) downto 0);
153
        signal column: std_logic_vector((COLUMN_WIDTH-1) downto 0);
154
        signal be: std_logic_vector((sdram_dqm'length-1) downto 0);
155
        signal data: std_logic_vector((sdram_dq'length-1) downto 0);
156
 
157
        signal do_init,do_refresh,do_active,read_is_active,ready,tRCD_not_expired: std_logic:='0';
158
 
159
        signal fifo_rdreq,fifo_empty: std_logic;
160
 
161
        signal read_latency: std_logic_vector(CAS_LATENCY downto 0);
162
 
163
        signal fifo_data: std_logic_vector((FIFO_WIDTH-1) downto 0);
164
        signal fifo_wrreq,fifo_wrfull: std_logic;
165
 
166
        signal i_command : STD_LOGIC_VECTOR(4 downto 0);
167
        CONSTANT NOP: STD_LOGIC_VECTOR(4 downto 0):="10111";
168
        CONSTANT ACTIVE: STD_LOGIC_VECTOR(4 downto 0):="10011";
169
        CONSTANT READ: STD_LOGIC_VECTOR(4 downto 0):="10101";
170
        CONSTANT WRITE: STD_LOGIC_VECTOR(4 downto 0):="10100";
171
        CONSTANT PRECHARGE: STD_LOGIC_VECTOR(4 downto 0):="10010";
172
        CONSTANT AUTO_REFRESH: STD_LOGIC_VECTOR(4 downto 0):="10001";
173
        CONSTANT LOAD_MODE_REGISTER: STD_LOGIC_VECTOR(4 downto 0):="10000";
174
 
175
        signal i_address : STD_LOGIC_VECTOR((sdram_addr'length-1) DOWNTO 0);
176
        signal i_bank : STD_LOGIC_VECTOR((sdram_ba'length-1) DOWNTO 0);
177
        signal i_dqm : STD_LOGIC_VECTOR((sdram_dqm'length-1) DOWNTO 0);
178
        signal i_data : STD_LOGIC_VECTOR((sdram_dq'length-1) DOWNTO 0);
179
        attribute ALTERA_ATTRIBUTE : string;
180
        attribute ALTERA_ATTRIBUTE of i_command : signal is "FAST_OUTPUT_REGISTER=ON";
181
        attribute ALTERA_ATTRIBUTE of i_address : signal is "FAST_OUTPUT_REGISTER=ON";
182
        attribute ALTERA_ATTRIBUTE of i_bank : signal is "FAST_OUTPUT_REGISTER=ON";
183
        attribute ALTERA_ATTRIBUTE of i_dqm : signal is "FAST_OUTPUT_REGISTER=ON";
184
        attribute ALTERA_ATTRIBUTE of i_data : signal is "FAST_OUTPUT_REGISTER=ON";
185
        attribute ALTERA_ATTRIBUTE of avs_nios_readdata : signal is "FAST_INPUT_REGISTER=ON";
186
begin
187
        (sdram_cke,sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n) <= i_command;
188
        sdram_addr <= i_address;
189
        sdram_ba <= i_bank;
190
        sdram_dqm <= i_dqm;
191
        sdram_dq <= i_data;
192
 
193
        fifo_data<=avs_nios_address & avs_nios_writedata & avs_nios_byteenable & avs_nios_write & avs_nios_read;
194
        fifo_wrreq<=(avs_nios_write or avs_nios_read) and avs_nios_chipselect and not fifo_wrfull;
195
 
196
        avs_nios_waitrequest<=fifo_wrfull;
197
 
198
        fifo_rdreq<=not fifo_empty and not do_refresh and not do_active and not read_is_active and ready;
199
 
200
        do_active<='0' when active_address=unsigned((fifo_q((fifo_q'length-1) downto (fifo_q'length-bank'length-row'length)))) else '1';
201
        read_is_active<='1' when read_latency(CAS_LATENCY-1 downto 0)>"000" and fifo_q(1)='1' else '0';
202
        ready<='1' when operation=IDLE or operation=READ0 or operation=WRITE0 else '0';
203
 
204
        operation_machine:process(reset,clk)
205
        begin
206
                if reset='1'
207
                        then
208
                        operation<=INIT0;
209
                        active_address<=(others=>'1');
210
                elsif rising_edge(clk)
211
                        then
212
 
213
                        bank<=fifo_q((fifo_q'length-1) downto (fifo_q'length-bank'length));
214
                        row<=fifo_q((fifo_q'length-bank'length-1) downto (fifo_q'length-bank'length-row'length));
215
                        column<=fifo_q((column'length+data'length+be'length+2-1) downto (data'length+be'length+2));
216
                        data<=fifo_q((data'length+be'length+2-1) downto (be'length+2));
217
                        be<=fifo_q((be'length+2-1) downto 2);
218
 
219
                        case operation is
220
                                when INIT0=>
221
                                if do_init='1'
222
                                        then operation<=INIT1;row(10)<='1';
223
                                end if;
224
                                when INIT1=>operation<=INIT2;
225
                                when INIT2=>operation<=INIT3;
226
                                when INIT3=>operation<=INIT4;
227
                                when INIT4=>operation<=INIT5;
228
                                when INIT5=>operation<=INIT6;
229
                                when INIT6=>operation<=INIT7;
230
                                when INIT7=>operation<=INIT8;
231
                                when INIT8=>operation<=INIT9;
232
                                when INIT9=>operation<=INIT10;
233
                                when INIT10=>operation<=INIT11;
234
                                when INIT11=>operation<=INIT12;
235
                                when INIT12=>operation<=INIT13;
236
                                when INIT13=>operation<=INIT14;
237
                                when INIT14=>operation<=INIT15;
238
                                when INIT15=>operation<=INIT16;
239
                                when INIT16=>operation<=INIT17;
240
                                when INIT17=>operation<=INIT18;
241
                                when INIT18=>operation<=INIT19;
242
                                when INIT19=>operation<=INIT20;
243
                                when INIT20=>operation<=INIT21;
244
                                when INIT21=>operation<=INIT22;
245
                                when INIT22=>operation<=INIT23;
246
                                when INIT23=>operation<=INIT24;row<=MODE((row'length-1) downto 0);
247
                                when INIT24=>operation<=IDLE;
248
 
249
                                when REFRESH0=>operation<=REFRESH1;
250
                                when REFRESH1=>operation<=REFRESH2;
251
                                when REFRESH2=>operation<=REFRESH3;
252
                                when REFRESH3=>operation<=REFRESH4;
253
                                when REFRESH4=>operation<=REFRESH5;
254
                                when REFRESH5=>operation<=REFRESH6;
255
                                when REFRESH6=>operation<=REFRESH7;
256
                                when REFRESH7=>operation<=REFRESH8;
257
                                when REFRESH8=>operation<=REFRESH9;
258
                                when REFRESH9=>operation<=REFRESH10;
259
                                when REFRESH10=>operation<=REFRESH11;
260
                                when REFRESH11=>operation<=REFRESH12;
261
                                when REFRESH12=>operation<=REFRESH13;
262
                                active_address<=unsigned(fifo_q((fifo_q'length-1) downto (fifo_q'length-bank'length-row'length)));
263
                                when REFRESH13=>operation<=REFRESH14;
264
                                when REFRESH14=>operation<=IDLE;
265
 
266
                                when ACTIVE0=>operation<=ACTIVE1;
267
                                when ACTIVE1=>operation<=ACTIVE2;
268
                                when ACTIVE2=>operation<=ACTIVE3;
269
                                active_address<=unsigned(fifo_q((fifo_q'length-1) downto (fifo_q'length-bank'length-row'length)));
270
                                when ACTIVE3=>operation<=ACTIVE4;
271
                                when ACTIVE4=>operation<=IDLE;
272
 
273
                                when others=>
274
                                if do_refresh='1'
275
                                        then
276
                                        if tRCD_not_expired='0' and operation=IDLE
277
                                                then operation<=REFRESH0;row(10)<='1';
278
                                        else operation<=IDLE;
279
                                        end if;
280
                                elsif do_active='1'
281
                                        then
282
                                        if tRCD_not_expired='0' and operation=IDLE
283
                                                then operation<=ACTIVE0;row(10)<='1';
284
                                        else operation<=IDLE;
285
                                        end if;
286
                                elsif fifo_empty='1'
287
                                        then
288
                                        operation<=IDLE;
289
                                elsif fifo_q(1)='1' --write
290
                                        then
291
                                        if read_latency(CAS_LATENCY-1 downto 0)>"000"
292
                                                then operation<=IDLE;
293
                                        else operation<=WRITE0;
294
                                        end if;
295
                                elsif fifo_q(0)='1'      --read
296
                                        then
297
                                        operation<=READ0;
298
                                end if;
299
                        end case;
300
                end if;
301
        end process;
302
 
303
        control_latency:process(reset,clk)
304
        begin
305
                if reset='1'
306
                        then
307
                        read_latency<=(others=>'0');
308
                elsif rising_edge(clk)
309
                        then
310
                        read_latency<=std_logic_vector(unsigned(read_latency) SLL 1);
311
                        if operation=READ0
312
                                then read_latency(0)<='1';
313
                        else read_latency(0)<='0';
314
                        end if;
315
                end if;
316
        end process;
317
        latch_readdata:process(reset,clk)
318
        begin
319
                if reset='1'
320
                        then
321
                        avs_nios_readdata<=(others=>'0');
322
                        avs_nios_readdatavalid<='0';
323
                elsif rising_edge(clk)
324
                        then
325
                        avs_nios_readdata<=sdram_dq;
326
                        avs_nios_readdatavalid<=read_latency(CAS_LATENCY);
327
                end if;
328
        end process;
329
        initialization:process(reset,clk)
330
        begin
331
                if rising_edge(clk)
332
                        then
333
                        if init_counter>0
334
                                then
335
                                init_counter<=init_counter-1;
336
                        else do_init<='1';
337
                        end if;
338
                end if;
339
        end process;
340
        refreshing:process(clk,reset)
341
        begin
342
                if reset='1'
343
                        then
344
                        refresh_counter<=to_unsigned(REFRESH_PERIOD_CLOCKS,16);
345
                        do_refresh<='0';
346
                elsif rising_edge(clk)
347
                        then
348
                        if refresh_counter=to_unsigned(0,refresh_counter'length)
349
                                then refresh_counter<=to_unsigned(REFRESH_PERIOD_CLOCKS,16);
350
                                do_refresh<='1';
351
                        else refresh_counter<=refresh_counter-1;
352
                        end if;
353
                        if operation=REFRESH0 or operation=REFRESH5
354
                                then do_refresh<='0';
355
                        end if;
356
                end if;
357
        end process;
358
        active_period:process(reset,clk)
359
        begin
360
                if reset='1'
361
                        then
362
                        active_counter<=(others=>'0');
363
                        tRCD_not_expired<='0';
364
                elsif rising_edge(clk)
365
                        then
366
                        if operation=ACTIVE3 or operation=REFRESH13
367
                                then active_counter<=to_unsigned(5,active_counter'length);
368
                        elsif active_counter>0
369
                                then active_counter<=active_counter-1;
370
                        end if;
371
                end if;
372
                if active_counter>0
373
                        then tRCD_not_expired<='1';
374
                else tRCD_not_expired<='0';
375
                end if;
376
        end process;
377
        latch_controls:process(clk,reset)
378
        begin
379
                if reset='1'
380
                        then
381
                        i_command<=NOP;
382
                        i_address<=(others=>'0');
383
                        i_bank<=(others=>'0');
384
                        i_dqm<=(others=>'0');
385
                        i_data<=(others=>'Z');
386
                elsif rising_edge(clk)
387
                        then
388
                        i_command<=NOP;
389
                        i_bank<=bank;
390
                        i_address<=(others=>'0');
391
                        i_address((column'length-1) downto 0)<=column;
392
                        i_data<=(others=>'Z');
393
                        i_dqm<=(others=>'0');
394
 
395
                        case operation is
396
                                when INIT1|REFRESH0|ACTIVE0 =>
397
                                i_command<=PRECHARGE;
398
                                i_address<=row;
399
                                when INIT4|INIT14|REFRESH3 =>
400
                                i_command<=AUTO_REFRESH;
401
                                when INIT24=>
402
                                i_command<=LOAD_MODE_REGISTER;
403
                                i_address<=row;
404
                                when ACTIVE3|REFRESH13 =>
405
                                i_command<=ACTIVE;
406
                                i_address<=row;
407
                                when READ0 =>
408
                                i_command<=READ;
409
                                when WRITE0 =>
410
                                i_command<=WRITE;
411
                                i_dqm<=not be;
412
                                i_data<=data;
413
                                when OTHERS =>
414
                        end case;
415
                end if;
416
        end process;
417
 
418
        fifo: scfifo
419
        GENERIC MAP (
420
                add_ram_output_register => "ON",
421
                intended_device_family => "Cyclone",
422
                lpm_numwords => 4,
423
                lpm_showahead => "ON",
424
                lpm_type => "scfifo",
425
                lpm_width => FIFO_WIDTH,
426
                lpm_widthu => 2,
427
                overflow_checking => "ON",
428
                underflow_checking => "ON",
429
                use_eab => "ON"
430
                )
431
        PORT MAP (
432
                rdreq => fifo_rdreq,
433
                aclr => reset,
434
                clock => clk,
435
                wrreq => fifo_wrreq,
436
                data => fifo_data,
437
                empty => fifo_empty,
438
                q => fifo_q,
439
                full => fifo_wrfull
440
                );
441
end behaviour;

powered by: WebSVN 2.1.0

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