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 |
|
|
|