Root/plasma/logic/ddr_ctrl.vhd

1---------------------------------------------------------------------
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--
12-- For: 64 MB = MT46V32M16, 512Mb, 32Mb x 16 (default)
13-- ROW = address(25 downto 13)
14-- BANK = address(12 downto 11)
15-- COL = address(10 downto 2)
16--
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-- 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---------------------------------------------------------------------
51library ieee;
52use ieee.std_logic_1164.all;
53use ieee.std_logic_unsigned.all;
54use ieee.std_logic_arith.all;
55use work.mlite_pack.all;
56
57entity 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      no_start : in std_logic;
69      no_stop : in std_logic;
70      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
88end; --entity ddr
89
90architecture 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
127begin
128   ddr_proc: process(clk, clk_p, clk_2x, reset_in,
129                     address, byte_we, data_w, active, no_start, no_stop,
130                     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               state_current := STATE_PRECHARGE;
162               command := COMMAND_AUTO_REFRESH;
163            elsif active = '1' and no_start = '0' then
164               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            elsif active = '1' and no_start = '0' then
178               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            if no_stop = '0' then
204               state_current := STATE_ROW_ACTIVE;
205            end if;
206
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         if command = COMMAND_ACTIVE then
244            bank_open(bank_index) <= '1';
245            address_row(bank_index) := address(25 downto 13);
246         end if;
247         
248         if command = COMMAND_PRECHARGE then
249            bank_open <= "0000";
250         end if;
251         
252         if command = COMMAND_AUTO_REFRESH then
253            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   
353end; --architecture logic
354
355

Archive Download this file

Branches:
master



interactive