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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [System09_base/] [xsasdramcntl.vhd] - Blame information for rev 194

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

Line No. Rev Author Line
1 128 davidgb
--------------------------------------------------------------------
2
-- Company       : XESS Corp.
3
-- Engineer      : Dave Vanden Bout
4
-- Creation Date : 05/17/2005
5
-- Copyright     : 2005, XESS Corp
6
-- Tool Versions : WebPACK 6.3.03i
7
--
8
-- Description:
9
--    Customizes the generic SDRAM controller module for the XSA Board.
10
--
11
-- Revision:
12
--    1.2.0
13
--
14
-- Additional Comments:
15
--    1.2.0:
16
--        added upper and lower data strobe signals
17
--        John Kent 2008-03-23
18
--    1.1.0:
19
--        Added CLK_DIV generic parameter to allow stepping-down the clock frequency.
20
--        Added MULTIPLE_ACTIVE_ROWS generic parameter to enable/disable keeping an active row in each bank.
21
--    1.0.0:
22
--        Initial release.
23
--
24
-- License:
25
--    This code can be freely distributed and modified as long as
26
--    this header is not removed.
27
--------------------------------------------------------------------
28
 
29
 
30
 
31
library IEEE, UNISIM;
32
use IEEE.std_logic_1164.all;
33
use IEEE.numeric_std.all;
34
use UNISIM.VComponents.all;
35
use WORK.common.all;
36
use WORK.sdram.all;
37
 
38
 
39
package XSASDRAM is
40
 
41
  component XSASDRAMCntl
42
    generic(
43
      FREQ                 :     natural := 100_000;  -- operating frequency in KHz
44
      CLK_DIV              :     real    := 2.0;  -- divisor for FREQ (can only be 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 8.0 or 16.0)
45
      PIPE_EN              :     boolean := false;  -- if true, enable pipelined read operations
46
      MAX_NOP              :     natural := 10000;  -- number of NOPs before entering self-refresh
47
      MULTIPLE_ACTIVE_ROWS :     boolean := false;  -- if true, allow an active row in each bank
48
      DATA_WIDTH           :     natural := 16;  -- host & SDRAM data width
49
      NROWS                :     natural := 8096;  -- number of rows in SDRAM array
50
      NCOLS                :     natural := 512;  -- number of columns in SDRAM array
51
      HADDR_WIDTH          :     natural := 24;  -- host-side address width
52
      SADDR_WIDTH          :     natural := 13  -- SDRAM-side address width
53
      );
54
    port(
55
      -- host side
56
      clk                  : in  std_logic;  -- master clock
57
      bufclk               : out std_logic;  -- buffered master clock
58
      clk1x                : out std_logic;  -- host clock sync'ed to master clock (and divided if CLK_DIV>1)
59
      clk2x                : out std_logic;  -- double-speed host clock
60
      lock                 : out std_logic;  -- true when host clock is locked to master clock
61
      rst                  : in  std_logic;  -- reset
62
      rd                   : in  std_logic;  -- initiate read operation
63
      wr                   : in  std_logic;  -- initiate write operation
64
      uds                  : in  std_logic;  -- upper data strobe
65
      lds                  : in  std_logic;  -- lower data strobe
66
      earlyOpBegun         : out std_logic;  -- read/write/self-refresh op begun     (async)
67
      opBegun              : out std_logic;  -- read/write/self-refresh op begun (clocked)
68
      rdPending            : out std_logic;  -- read operation(s) are still in the pipeline
69
      done                 : out std_logic;  -- read or write operation is done
70
      rdDone               : out std_logic;  -- read done and data is available
71
      hAddr                : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host
72
      hDIn                 : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host
73
      hDOut                : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data to host
74
      status               : out std_logic_vector(3 downto 0);  -- diagnostic status of the FSM         
75
 
76
      -- SDRAM side
77
      sclkfb : in    std_logic;         -- clock from SDRAM after PCB delays
78
      sclk   : out   std_logic;         -- SDRAM clock sync'ed to master clock
79
      cke    : out   std_logic;         -- clock-enable to SDRAM
80
      cs_n   : out   std_logic;         -- chip-select to SDRAM
81
      ras_n  : out   std_logic;         -- SDRAM row address strobe
82
      cas_n  : out   std_logic;         -- SDRAM column address strobe
83
      we_n   : out   std_logic;         -- SDRAM write enable
84
      ba     : out   std_logic_vector(1 downto 0);  -- SDRAM bank address bits
85
      sAddr  : out   std_logic_vector(SADDR_WIDTH-1 downto 0);  -- SDRAM row/column address
86
      sData  : inout std_logic_vector(DATA_WIDTH-1 downto 0);  -- SDRAM in/out databus
87
      dqmh   : out   std_logic;         -- high databits I/O mask
88
      dqml   : out   std_logic          -- low databits I/O mask
89
      );
90
  end component;
91
 
92
end package XSASDRAM;
93
 
94
 
95
 
96
library IEEE, UNISIM;
97
use IEEE.std_logic_1164.all;
98
use IEEE.numeric_std.all;
99
use UNISIM.VComponents.all;
100
use WORK.common.all;
101
use WORK.sdram.all;
102
 
103
entity XSASDRAMCntl is
104
  generic(
105
    FREQ                 :     natural := 100_000; -- operating frequency in KHz
106
    CLK_DIV              :     real    := 2.0;     -- divisor for FREQ (can only be 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 8.0 or 16.0)
107
    PIPE_EN              :     boolean := false;   -- if true, enable pipelined read operations
108
    MAX_NOP              :     natural := 10000;   -- number of NOPs before entering self-refresh
109
    MULTIPLE_ACTIVE_ROWS :     boolean := false;   -- if true, allow an active row in each bank
110
    DATA_WIDTH           :     natural := 16;      -- host & SDRAM data width
111
    NROWS                :     natural := 8192;    -- number of rows in SDRAM array
112
    NCOLS                :     natural := 512;     -- number of columns in SDRAM array
113
    HADDR_WIDTH          :     natural := 24;      -- host-side address width
114
    SADDR_WIDTH          :     natural := 13       -- SDRAM-side address width
115
    );
116
  port(
117
    -- host side
118
    clk                  : in  std_logic;  -- master clock
119
    bufclk               : out std_logic;  -- buffered master clock
120
    clk1x                : out std_logic;  -- host clock sync'ed to master clock (and divided if CLK_DIV>1)
121
    clk2x                : out std_logic;  -- double-speed host clock
122
    lock                 : out std_logic;  -- true when host clock is locked to master clock
123
    rst                  : in  std_logic;  -- reset
124
    rd                   : in  std_logic;  -- initiate read operation
125
    wr                   : in  std_logic;  -- initiate write operation
126
    uds                  : in  std_logic;  -- upper data strobe
127
    lds                  : in  std_logic;  -- lower data strobe
128
    earlyOpBegun         : out std_logic;  -- read/write/self-refresh op begun     (async)
129
    opBegun              : out std_logic;  -- read/write/self-refresh op begun (clocked)
130
    rdPending            : out std_logic;  -- read operation(s) are still in the pipeline
131
    done                 : out std_logic;  -- read or write operation is done
132
    rdDone               : out std_logic;  -- read done and data is available
133
    hAddr                : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host
134
    hDIn                 : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host
135
    hDOut                : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data to host
136
    status               : out std_logic_vector(3 downto 0);  -- diagnostic status of the FSM         
137
 
138
    -- SDRAM side
139
    sclkfb : in    std_logic;           -- clock from SDRAM after PCB delays
140
    sclk   : out   std_logic;           -- SDRAM clock sync'ed to master clock
141
    cke    : out   std_logic;           -- clock-enable to SDRAM
142
    cs_n   : out   std_logic;           -- chip-select to SDRAM
143
    ras_n  : out   std_logic;           -- SDRAM row address strobe
144
    cas_n  : out   std_logic;           -- SDRAM column address strobe
145
    we_n   : out   std_logic;           -- SDRAM write enable
146
    ba     : out   std_logic_vector(1 downto 0);  -- SDRAM bank address bits
147
    sAddr  : out   std_logic_vector(SADDR_WIDTH-1 downto 0);  -- SDRAM row/column address
148
    sData  : inout std_logic_vector(DATA_WIDTH-1 downto 0);  -- SDRAM in/out databus
149
    dqmh   : out   std_logic;           -- high databits I/O mask
150
    dqml   : out   std_logic            -- low databits I/O mask
151
    );
152
end XSASDRAMCntl;
153
 
154
 
155
 
156
architecture arch of XSASDRAMCntl is
157
 
158
  -- The SDRAM controller and external SDRAM chip will clock on the same edge
159
  -- if the frequency and divided frequency are both greater than the minimum DLL lock frequency.
160
  -- Otherwise the DLLs cannot be used so the SDRAM controller and external SDRAM clock on opposite edges
161
  -- to try and mitigate the clock skew between the internal FPGA logic and the external SDRAM.
162
  constant MIN_LOCK_FREQ : real    := 25_000.0;
163
  constant IN_PHASE      : boolean := real(FREQ)/CLK_DIV >= MIN_LOCK_FREQ;
164
  -- Calculate the frequency of the clock for the SDRAM.
165
--  constant SDRAM_FREQ    : natural := int_select(IN_PHASE, (FREQ*integer(2.0*CLK_DIV))/2, FREQ);
166
  constant SDRAM_FREQ    : natural := int_select(IN_PHASE, (FREQ*2)/integer(2.0*CLK_DIV), FREQ);
167
  -- Compute the CLKDV_DIVIDE generic paramter for the DLL modules.  It defaults to 2 when CLK_DIV=1
168
  -- because the DLL does not support a divisor of 1 on the CLKDV output.  We use the CLK0 output
169
  -- when CLK_DIV=1 so we don't care what is output on thr CLK_DIV output of the DLL.
170
  constant CLKDV_DIVIDE  : real    := real_select(CLK_DIV = 1.0, 2.0, CLK_DIV);
171
 
172
  signal int_clkin,                     -- signals for internal logic clock DLL
173
    int_clk1x, int_clk1x_b,
174
    int_clk2x, int_clk2x_b,
175
    int_clkdv, int_clkdv_b              : std_logic;
176
  signal ext_clkin, sclkfb_b, ext_clk1x : std_logic;  -- signals for external logic clock DLL
177
  signal dllext_rst, dllext_rst_n       : std_logic;  -- external DLL reset signal
178
  signal clk_i                          : std_logic;  -- clock for SDRAM controller logic
179
  signal int_lock, ext_lock, lock_i     : std_logic;  -- DLL lock signals
180
 
181
  -- bus for holding output data from SDRAM
182
  signal sDOut   : std_logic_vector(sData'range);
183
  signal sDOutEn : std_logic;
184
 
185
begin
186
 
187
  -----------------------------------------------------------
188
  -- setup the DLLs for clock generation 
189
  -----------------------------------------------------------
190
 
191
  -- master clock must come from a dedicated clock pin
192
  clkin_buf : BUFG port map (I => clk, O => int_clkin);
193
 
194
  -- The external DLL is driven from the same source as the internal DLL
195
  -- if the clock divisor is 1.  If CLK_DIV is greater than 1, then the external DLL 
196
  -- is driven by the divided clock from the internal DLL.  Otherwise, the SDRAM will be
197
  -- clocked on the opposite edge if the internal and external logic are not in-phase.
198
  ext_clkin <= int_clkin    when (IN_PHASE and (CLK_DIV = 1.0)) else
199
                int_clkdv_b when (IN_PHASE and (CLK_DIV/=1.0))  else
200
                not int_clkin;
201
 
202
  -- Generate the DLLs for sync'ing the clocks as long as the clocks
203
  -- have a frequency high enough for the DLLs to lock
204
  gen_dlls : if IN_PHASE generate
205
 
206
    -- generate an internal clock sync'ed to the master clock
207
    dllint : CLKDLL
208
      generic map(
209
        CLKDV_DIVIDE => CLKDV_DIVIDE
210
        )
211
      port map(
212
        CLKIN        => int_clkin,
213
        CLKFB        => int_clk1x_b,
214
        CLK0         => int_clk1x,
215
        RST          => ZERO,
216
        CLK90        => open,
217
        CLK180       => open,
218
        CLK270       => open,
219
        CLK2X        => int_clk2x,
220
        CLKDV        => int_clkdv,
221
        LOCKED       => int_lock
222
        );
223
 
224
    -- sync'ed single, doubled and divided clocks for use by internal logic
225
    int_clk1x_buf : BUFG port map(I => int_clk1x, O => int_clk1x_b);
226
    int_clk2x_buf : BUFG port map(I => int_clk2x, O => int_clk2x_b);
227
    int_clkdv_buf : BUFG port map(I => int_clkdv, O => int_clkdv_b);
228
 
229
    -- The external DLL is held in a reset state until the internal DLL locks.
230
    -- Then the external DLL reset is released after a delay set by this shift register.
231
    -- This keeps the external DLL from locking onto the internal DLL clock signal
232
    -- until it is stable.
233
    SRL16_inst : SRL16
234
      generic map (
235
        INIT => X"0000"
236
        )
237
      port map (
238
        CLK  => clk_i,
239
        A0   => '1',
240
        A1   => '1',
241
        A2   => '1',
242
        A3   => '1',
243
        D    => int_lock,
244
        Q    => dllext_rst_n
245
        );
246
--    Error ???
247
--    dllext_rst <= not dllext_rst when CLK_DIV/=1.0 else ZERO;
248
    dllext_rst <= not dllext_rst_n when CLK_DIV/=1.0 else ZERO;
249
 
250
    -- generate an external SDRAM clock sync'ed to the master clock
251
    sclkfb_buf : IBUFG port map(I => sclkfb, O => sclkfb_b);  -- SDRAM clock with PCB delays
252
 
253
    dllext     : CLKDLL port map(
254
      CLKIN                       => ext_clkin,  -- this is either the master clock or the divided clock from the internal DLL
255
      CLKFB                       => sclkfb_b,
256
      CLK0                        => ext_clk1x,
257
      RST                         => dllext_rst,
258
      CLK90                       => open,
259
      CLK180                      => open,
260
      CLK270                      => open,
261
      CLK2X                       => open,
262
      CLKDV                       => open,
263
      LOCKED                      => ext_lock
264
      );
265
 
266
  end generate;
267
 
268
  -- The buffered clock is just a buffered version of the master clock.
269
  bufclk_bufg : BUFG port map (I => int_clkin, O => bufclk);
270
  -- The host-side clock comes from the CLK0 output of the internal DLL if the clock divisor is 1.
271
  -- Otherwise it comes from the CLKDV output if the clock divisor is greater than 1.
272
  -- Otherwise it is just a copy of the master clock if the DLLs aren't being used.
273
  clk_i  <= int_clk1x_b when (IN_PHASE and (CLK_DIV = 1.0)) else
274
            int_clkdv_b when (IN_PHASE and (CLK_DIV/=1.0))  else
275
            int_clkin;
276
  clk1x  <= clk_i;                      -- This is the output of the host-side clock
277
  clk2x  <= int_clk2x_b when IN_PHASE                       else int_clkin;  -- this is the doubled master clock
278
  sclk   <= ext_clk1x   when IN_PHASE                       else ext_clkin;  -- this is the clock for the external SDRAM
279
 
280
  -- indicate the lock status of the internal and external DLL
281
  lock_i <= int_lock and ext_lock when IN_PHASE else YES;
282
  lock   <= lock_i;                     -- lock signal for the host logic
283
 
284
  -- SDRAM memory controller module
285
  u1 : sdramCntl
286
    generic map(
287
      FREQ                 => SDRAM_FREQ,
288
      IN_PHASE             => IN_PHASE,
289
      PIPE_EN              => PIPE_EN,
290
      MAX_NOP              => MAX_NOP,
291
      MULTIPLE_ACTIVE_ROWS => MULTIPLE_ACTIVE_ROWS,
292
      DATA_WIDTH           => DATA_WIDTH,
293
      NROWS                => NROWS,
294
      NCOLS                => NCOLS,
295
      HADDR_WIDTH          => HADDR_WIDTH,
296
      SADDR_WIDTH          => SADDR_WIDTH
297
      )
298
    port map(
299
      clk                  => clk_i,    -- master clock from external clock source (unbuffered)
300
      lock                 => lock_i,   -- valid synchronized clocks indicator
301
      rst                  => rst,      -- reset
302
      rd                   => rd,       -- host-side SDRAM read control from memory tester
303
      wr                   => wr,       -- host-side SDRAM write control from memory tester
304
      uds                  => uds,      -- host-side SDRAM upper data strobe
305
      lds                  => lds,      -- host-side SDRAM lower data strobe
306
      rdPending            => rdPending,
307
      opBegun              => opBegun,  -- SDRAM memory read/write done indicator
308
      earlyOpBegun         => earlyOpBegun,  -- SDRAM memory read/write done indicator
309
      rdDone               => rdDone,   -- SDRAM memory read/write done indicator
310
      done                 => done,
311
      hAddr                => hAddr,    -- host-side address from memory tester
312
      hDIn                 => hDIn,     -- test data pattern from memory tester
313
      hDOut                => hDOut,    -- SDRAM data output to memory tester
314
      status               => status,   -- SDRAM controller state (for diagnostics)
315
      cke                  => cke,      -- SDRAM clock enable
316
      ce_n                 => cs_n,     -- SDRAM chip-select
317
      ras_n                => ras_n,    -- SDRAM RAS
318
      cas_n                => cas_n,    -- SDRAM CAS
319
      we_n                 => we_n,     -- SDRAM write-enable
320
      ba                   => ba,       -- SDRAM bank address
321
      sAddr                => sAddr,    -- SDRAM address
322
      sDIn                 => sData,    -- input data from SDRAM
323
      sDOut                => sDOut,    -- output data to SDRAM
324
      sDOutEn              => sDOutEn,  -- enable drivers to send data to SDRAM
325
      dqmh                 => dqmh,     -- SDRAM DQMH
326
      dqml                 => dqml      -- SDRAM DQML
327
      );
328
 
329
  sData <= sDOut when sDOutEn = YES else (others => 'Z');
330
 
331
end arch;

powered by: WebSVN 2.1.0

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