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

Subversion Repositories mlite

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

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

powered by: WebSVN 2.1.0

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