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

Subversion Repositories plasma

[/] [plasma/] [trunk/] [vhdl/] [ddr_ctrl.vhd] - Blame information for rev 350

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

Line No. Rev Author Line
1 259 rhoads
---------------------------------------------------------------------
2
-- TITLE: DDR SDRAM Interface
3
-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
4
-- DATE CREATED: 7/26/07
5
-- FILENAME: ddr_ctrl.vhd
6
-- PROJECT: Plasma CPU core
7
-- COPYRIGHT: Software placed into the public domain by the author.
8
--    Software 'as is' without warranty.  Author liable for nothing.
9
-- DESCRIPTION:
10
--    Double Data Rate Sychronous Dynamic Random Access Memory Interface
11 348 rhoads
--
12
--    For: 64 MB = MT46V32M16, 512Mb, 32Mb x 16 (default)
13 259 rhoads
--    ROW = address(25 downto 13)
14
--    BANK = address(12 downto 11)
15
--    COL = address(10 downto 2)
16 348 rhoads
--
17
--    Changes are needed for 32 MB = MT46V16M16, 256Mb, 16Mb x 16
18
--    ROW = address(24 downto 12)  -- 25 ignored
19
--    BANK = address(11 downto 10)
20
--    COL = address(9 downto 2)    --also change ddr_init.c
21
--
22
--    Changes are needed for 128 MB = MT46V64M16, 1Gb, 64Mb x 16
23
--    ROW = address(26 downto 14)
24
--    BANK = address(13 downto 12)
25
--    COL = address(11 downto 2)   --also change ddr_init.c
26
--
27 259 rhoads
--    Requires CAS latency=2; burst size=2.  
28
--    Requires clk changes on rising_edge(clk_2x).
29
--    Requires active, address, byte_we, data_w stable throughout transfer.
30
--    DLL mode requires 77MHz.  Non-DLL mode runs at 25 MHz.
31
--
32
-- cycle_cnt 777777770000111122223333444455556666777777777777
33
-- clk_2x    --__--__--__--__--__--__--__--__--__--__--__--__
34
-- clk       ____----____----____----____----____----____----
35
-- SD_CLK    ----____----____----____----____----____----____
36
-- cmd       ____write+++WRITE+++____________________________
37
-- SD_DQ     ~~~~~~~~~~~~~~uuuullllUUUULLLL~~~~~~~~~~~~~~~~~~
38
--
39
-- cycle_cnt 777777770000111122223333444455556666777777777777
40
-- clk_2x    --__--__--__--__--__--__--__--__--__--__--__--__
41
-- clk       ____----____----____----____----____----____----
42
-- SD_CLK    ----____----____----____----____----____----____
43
-- cmd       ____read++++________________________read++++____
44
-- SD_DQ     ~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~~~
45
-- SD_DQnDLL ~~~~~~~~~~~~~~~~~~~~~~~~~~uuuullll~~~~~~~~~~~~~~
46
-- pause     ____------------------------________------------
47
--
48
-- Must run DdrInit() to initialize DDR chip.
49
-- Read Micron DDR SDRAM MT46V32M16 data sheet for more details.
50
---------------------------------------------------------------------
51
library ieee;
52
use ieee.std_logic_1164.all;
53
use ieee.std_logic_unsigned.all;
54
use ieee.std_logic_arith.all;
55
use work.mlite_pack.all;
56
 
57
entity ddr_ctrl is
58
   port(
59
      clk      : in std_logic;
60
      clk_2x   : in std_logic;
61
      reset_in : in std_logic;
62
 
63
      address  : in std_logic_vector(25 downto 2);
64
      byte_we  : in std_logic_vector(3 downto 0);
65
      data_w   : in std_logic_vector(31 downto 0);
66
      data_r   : out std_logic_vector(31 downto 0);
67
      active   : in std_logic;
68 346 rhoads
      no_start : in std_logic;
69
      no_stop  : in std_logic;
70 259 rhoads
      pause    : out std_logic;
71
 
72
      SD_CK_P  : out std_logic;     --clock_positive
73
      SD_CK_N  : out std_logic;     --clock_negative
74
      SD_CKE   : out std_logic;     --clock_enable
75
 
76
      SD_BA    : out std_logic_vector(1 downto 0);  --bank_address
77
      SD_A     : out std_logic_vector(12 downto 0); --address(row or col)
78
      SD_CS    : out std_logic;     --chip_select
79
      SD_RAS   : out std_logic;     --row_address_strobe
80
      SD_CAS   : out std_logic;     --column_address_strobe
81
      SD_WE    : out std_logic;     --write_enable
82
 
83
      SD_DQ    : inout std_logic_vector(15 downto 0); --data
84
      SD_UDM   : out std_logic;     --upper_byte_enable
85
      SD_UDQS  : inout std_logic;   --upper_data_strobe
86
      SD_LDM   : out std_logic;     --low_byte_enable
87
      SD_LDQS  : inout std_logic);  --low_data_strobe
88
end; --entity ddr
89
 
90
architecture logic of ddr_ctrl is
91
 
92
   --Commands for bits RAS & CAS & WE
93
   subtype command_type is std_logic_vector(2 downto 0);
94
   constant COMMAND_LMR          : command_type := "000";
95
   constant COMMAND_AUTO_REFRESH : command_type := "001";
96
   constant COMMAND_PRECHARGE    : command_type := "010";
97
   constant COMMAND_ACTIVE       : command_type := "011";
98
   constant COMMAND_WRITE        : command_type := "100";
99
   constant COMMAND_READ         : command_type := "101";
100
   constant COMMAND_TERMINATE    : command_type := "110";
101
   constant COMMAND_NOP          : command_type := "111";
102
 
103
   subtype ddr_state_type is std_logic_vector(3 downto 0);
104
   constant STATE_POWER_ON     : ddr_state_type := "0000";
105
   constant STATE_IDLE         : ddr_state_type := "0001";
106
   constant STATE_ROW_ACTIVATE : ddr_state_type := "0010";
107
   constant STATE_ROW_ACTIVE   : ddr_state_type := "0011";
108
   constant STATE_READ         : ddr_state_type := "0100";
109
   constant STATE_READ2        : ddr_state_type := "0101";
110
   constant STATE_READ3        : ddr_state_type := "0110";
111
   constant STATE_PRECHARGE    : ddr_state_type := "0111";
112
   constant STATE_PRECHARGE2   : ddr_state_type := "1000";
113
 
114
   signal state_prev   : ddr_state_type;
115
   signal refresh_cnt  : std_logic_vector(7 downto 0);
116
   signal data_write2  : std_logic_vector(47 downto 0); --write pipeline
117
   signal byte_we_reg2 : std_logic_vector(5 downto 0);  --write pipeline
118
   signal write_active : std_logic;
119
   signal write_prev   : std_logic;
120
   signal cycle_count  : std_logic_vector(2 downto 0);  --half clocks since op
121
   signal cycle_count2 : std_logic_vector(2 downto 0);  --delayed by quarter clock
122
   signal cke_reg      : std_logic;
123
   signal clk_p        : std_logic;
124
   signal bank_open    : std_logic_vector(3 downto 0);
125
   signal data_read    : std_logic_vector(31 downto 0);
126
 
127
begin
128
   ddr_proc: process(clk, clk_p, clk_2x, reset_in,
129 346 rhoads
                     address, byte_we, data_w, active, no_start, no_stop,
130 259 rhoads
                     SD_DQ, SD_UDQS, SD_LDQS,
131
                     state_prev, refresh_cnt,
132
                     byte_we_reg2, data_write2,
133
                     cycle_count, cycle_count2, write_prev,
134
                     write_active, cke_reg, bank_open,
135
                     data_read)
136
   type address_array_type is array(3 downto 0) of std_logic_vector(12 downto 0);
137
   variable address_row    : address_array_type;
138
   variable command        : std_logic_vector(2 downto 0); --RAS & CAS & WE
139
   variable bank_index     : integer;
140
   variable state_current  : ddr_state_type;
141
 
142
   begin
143
 
144
      command := COMMAND_NOP;
145
      bank_index := conv_integer(address(12 downto 11));
146
      state_current := state_prev;
147
 
148
      --DDR state machine to determine state_current and command
149
      case state_prev is
150
         when STATE_POWER_ON =>
151
            if active = '1' then
152
               if byte_we /= "0000" then
153
                  command := address(6 downto 4); --LMR="000"
154
               else
155
                  state_current := STATE_IDLE;  --read transistions to STATE_IDLE
156
               end if;
157
            end if;
158
 
159
         when STATE_IDLE =>
160
            if refresh_cnt(7) = '1' then
161 278 rhoads
               state_current := STATE_PRECHARGE;
162
               command := COMMAND_AUTO_REFRESH;
163 346 rhoads
            elsif active = '1' and no_start = '0' then
164 259 rhoads
               state_current := STATE_ROW_ACTIVATE;
165
               command := COMMAND_ACTIVE;
166
            end if;
167
 
168
         when STATE_ROW_ACTIVATE =>
169
            state_current := STATE_ROW_ACTIVE;
170
 
171
         when STATE_ROW_ACTIVE =>
172
            if refresh_cnt(7) = '1' then
173
               if write_prev = '0' then
174
                  state_current := STATE_PRECHARGE;
175
                  command := COMMAND_PRECHARGE;
176
               end if;
177 346 rhoads
            elsif active = '1' and no_start = '0' then
178 259 rhoads
               if bank_open(bank_index) = '0' then
179
                  state_current := STATE_ROW_ACTIVATE;
180
                  command := COMMAND_ACTIVE;
181
               elsif address(25 downto 13) /= address_row(bank_index) then
182
                  if write_prev = '0' then
183
                     state_current := STATE_PRECHARGE;
184
                     command := COMMAND_PRECHARGE;
185
                  end if;
186
               else
187
                  if byte_we /= "0000" then
188
                     command := COMMAND_WRITE;
189
                  elsif write_prev = '0' then
190
                     state_current := STATE_READ;
191
                     command := COMMAND_READ;
192
                  end if;
193
               end if;
194
            end if;
195
 
196
         when STATE_READ =>
197
            state_current := STATE_READ2;
198
 
199
         when STATE_READ2 =>
200
            state_current := STATE_READ3;
201
 
202
         when STATE_READ3 =>
203 346 rhoads
            if no_stop = '0' then
204
               state_current := STATE_ROW_ACTIVE;
205
            end if;
206 259 rhoads
 
207
         when STATE_PRECHARGE =>
208
            state_current := STATE_PRECHARGE2;
209
 
210
         when STATE_PRECHARGE2 =>
211
            state_current := STATE_IDLE;
212
 
213
         when others =>
214
            state_current := STATE_IDLE;
215
      end case; --state_prev
216
 
217
      --rising_edge(clk) domain registers
218
      if reset_in = '1' then
219
         state_prev   <= STATE_POWER_ON;
220
         cke_reg      <= '0';
221
         refresh_cnt  <= ZERO(7 downto 0);
222
         write_prev   <= '0';
223
         write_active <= '0';
224
         bank_open    <= "0000";
225
      elsif rising_edge(clk) then
226
 
227
         if active = '1' then
228
            cke_reg <= '1';
229
         end if;
230
 
231
         if command = COMMAND_WRITE then
232
            write_prev <= '1';
233
         elsif cycle_count2(2 downto 1) = "11" then
234
            write_prev <= '0';
235
         end if;
236
 
237
         if command = COMMAND_WRITE then
238
            write_active <= '1';
239
         elsif cycle_count2 = "100" then
240
            write_active <= '0';
241
         end if;
242
 
243 278 rhoads
         if command = COMMAND_ACTIVE then
244 259 rhoads
            bank_open(bank_index) <= '1';
245
            address_row(bank_index) := address(25 downto 13);
246
         end if;
247
 
248 278 rhoads
         if command = COMMAND_PRECHARGE then
249 259 rhoads
            bank_open <= "0000";
250 278 rhoads
         end if;
251
 
252
         if command = COMMAND_AUTO_REFRESH then
253 259 rhoads
            refresh_cnt <= ZERO(7 downto 0);
254
         else
255
            refresh_cnt <= refresh_cnt + 1;
256
         end if;
257
 
258
         state_prev <= state_current;
259
 
260
      end if; --rising_edge(clk)
261
 
262
      --rising_edge(clk_2x) domain registers
263
      if reset_in = '1' then
264
         cycle_count <= "000";
265
      elsif rising_edge(clk_2x) then
266
         --Cycle_count
267
         if (command = COMMAND_READ or command = COMMAND_WRITE) and clk = '1' then
268
            cycle_count <= "000";
269
         elsif cycle_count /= "111" then
270
            cycle_count <= cycle_count + 1;
271
         end if;
272
 
273
         clk_p <= clk;  --earlier version of not clk         
274
 
275
         --Read data (DLL disabled)
276
         if cycle_count = "100" then
277
            data_read(31 downto 16) <= SD_DQ; --data
278
         elsif cycle_count = "101" then
279
            data_read(15 downto 0) <= SD_DQ;
280
         end if;
281
      end if;
282
 
283
      --falling_edge(clk_2x) domain registers
284
      if reset_in = '1' then
285
         cycle_count2 <= "000";
286
         data_write2 <= ZERO(15 downto 0) & ZERO;
287
         byte_we_reg2 <= "000000";
288
      elsif falling_edge(clk_2x) then
289
         cycle_count2 <= cycle_count;
290
 
291
         --Write pipeline
292
         if clk = '0' then
293
            data_write2 <= data_write2(31 downto 16) & data_w;
294
            byte_we_reg2 <= byte_we_reg2(3 downto 2) & byte_we;
295
         else
296
            data_write2(47 downto 16) <= data_write2(31 downto 0);
297
            byte_we_reg2(5 downto 2) <= byte_we_reg2(3 downto 0);
298
         end if;
299
 
300
         --Read data (DLL enabled)
301
         --if cycle_count = "100" then
302
         --   data_read(31 downto 16) <= SD_DQ; --data
303
         --elsif cycle_count = "101" then
304
         --   data_read(15 downto 0) <= SD_DQ;
305
         --end if;
306
      end if;
307
 
308
      data_r <= data_read;
309
 
310
      --Write data
311
      if write_active = '1' then
312
         SD_UDQS <= clk_p;                   --upper_data_strobe 
313
         SD_LDQS <= clk_p;                   --low_data_strobe
314
         SD_DQ <= data_write2(47 downto 32); --data
315
         SD_UDM <= not byte_we_reg2(5);      --upper_byte_enable
316
         SD_LDM <= not byte_we_reg2(4);      --low_byte_enable
317
      else
318
         SD_UDQS <= 'Z';               --upper_data_strobe 
319
         SD_LDQS <= 'Z';               --low_data_strobe
320
         SD_DQ <= "ZZZZZZZZZZZZZZZZ";  --data
321
         SD_UDM <= 'Z';
322
         SD_LDM <= 'Z';
323
      end if;
324
 
325
      --DDR control signals
326
      SD_CK_P <= clk_p;                --clock_positive
327
      SD_CK_N <= not clk_p;            --clock_negative
328
      SD_CKE  <= cke_reg;              --clock_enable
329
 
330
      SD_BA   <= address(12 downto 11);  --bank_address
331
      if command = COMMAND_ACTIVE or state_current = STATE_POWER_ON then
332
         SD_A <= address(25 downto 13);  --address row
333
      elsif command = COMMAND_READ or command = COMMAND_WRITE then
334
         SD_A <= "000" & address(10 downto 2) & "0"; --address col
335
      else
336
         SD_A <= "0010000000000";      --PERCHARGE all banks
337
      end if;
338
 
339
      SD_CS   <= not cke_reg;          --chip_select
340
      SD_RAS  <= command(2);           --row_address_strobe
341
      SD_CAS  <= command(1);           --column_address_strobe
342
      SD_WE   <= command(0);           --write_enable
343
 
344
      if active = '1' and state_current /= STATE_POWER_ON and
345
         command /= COMMAND_WRITE and state_prev /= STATE_READ3 then
346
         pause <= '1';
347
      else
348
         pause <= '0';
349
      end if;
350
 
351
   end process; --ddr_proc
352
 
353
end; --architecture logic
354
 

powered by: WebSVN 2.1.0

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