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

Subversion Repositories mlite

[/] [mlite/] [trunk/] [vhdl/] [ddr_ctrl.vhd] - Blame information for rev 346

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

powered by: WebSVN 2.1.0

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