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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [System09_base/] [sdramcntl.vhd] - Blame information for rev 128

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 128 davidgb
library IEEE, UNISIM;
2
use IEEE.std_logic_1164.all;
3
 
4
package sdram is
5
 
6
  -- SDRAM controller
7
  component sdramCntl
8
    generic(
9
      FREQ                 :     natural := 100_000;  -- operating frequency in KHz
10
      IN_PHASE             :     boolean := true;  -- SDRAM and controller work on same or opposite clock edge
11
      PIPE_EN              :     boolean := false;  -- if true, enable pipelined read operations
12
      MAX_NOP              :     natural := 10000;  -- number of NOPs before entering self-refresh
13
      MULTIPLE_ACTIVE_ROWS :     boolean := false;  -- if true, allow an active row in each bank
14
      DATA_WIDTH           :     natural := 16;  -- host & SDRAM data width
15
      NROWS                :     natural := 8192;  -- number of rows in SDRAM array
16
      NCOLS                :     natural := 512;  -- number of columns in SDRAM array
17
      HADDR_WIDTH          :     natural := 24;  -- host-side address width
18
      SADDR_WIDTH          :     natural := 13  -- SDRAM-side address width
19
      );
20
    port(
21
      -- host side
22
      clk                  : in  std_logic;  -- master clock
23
      lock                 : in  std_logic;  -- true if clock is stable
24
      rst                  : in  std_logic;  -- reset
25
      rd                   : in  std_logic;  -- initiate read operation
26
      wr                   : in  std_logic;  -- initiate write operation
27
      uds                  : in  std_logic;  -- upper byte data strobe
28
      lds                  : in  std_logic;  -- lower byte data strobe
29
      earlyOpBegun         : out std_logic;  -- read/write/self-refresh op has begun (async)
30
      opBegun              : out std_logic;  -- read/write/self-refresh op has begun (clocked)
31
      rdPending            : out std_logic;  -- true if read operation(s) are still in the pipeline
32
      done                 : out std_logic;  -- read or write operation is done
33
      rdDone               : out std_logic;  -- read operation is done and data is available
34
      hAddr                : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host to SDRAM
35
      hDIn                 : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host       to SDRAM
36
      hDOut                : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM to host
37
      status               : out std_logic_vector(3 downto 0);  -- diagnostic status of the FSM         
38
      -- SDRAM side
39
      cke                  : out std_logic;  -- clock-enable to SDRAM
40
      ce_n                 : out std_logic;  -- chip-select to SDRAM
41
      ras_n                : out std_logic;  -- SDRAM row address strobe
42
      cas_n                : out std_logic;  -- SDRAM column address strobe
43
      we_n                 : out std_logic;  -- SDRAM write enable
44
      ba                   : out std_logic_vector(1 downto 0);  -- SDRAM bank address
45
      sAddr                : out std_logic_vector(SADDR_WIDTH-1 downto 0);  -- SDRAM row/column address
46
      sDIn                 : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data to SDRAM
47
      sDOut                : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM
48
      sDOutEn              : out std_logic;  -- true if data is output to SDRAM on sDOut
49
      dqmh                 : out std_logic;  -- enable upper-byte of SDRAM databus if true
50
      dqml                 : out std_logic  -- enable lower-byte of SDRAM databus if true
51
      );
52
  end component;
53
 
54
  -- dual-port interface to the SDRAM controller
55
  component dualport
56
    generic(
57
      PIPE_EN         :    boolean                       := false;  -- enable pipelined read operations
58
      PORT_TIME_SLOTS :    std_logic_vector(15 downto 0) := "1111000011110000";
59
      DATA_WIDTH      :    natural                       := 16;  -- host & SDRAM data width
60
      HADDR_WIDTH     :    natural                       := 23  -- host-side address width
61
      );
62
    port(
63
      clk             : in std_logic;   -- master clock
64
 
65
      -- host-side port 0
66
      rst0          : in  std_logic;    -- reset
67
      rd0           : in  std_logic;    -- initiate read operation
68
      wr0           : in  std_logic;    -- initiate write operation
69
      uds0          : in  std_logic;     -- upper data strobe
70
      lds0          : in  std_logic;     -- lower data strobe
71
      earlyOpBegun0 : out std_logic;    -- read/write op has begun (async)
72
      opBegun0      : out std_logic;    -- read/write op has begun (clocked)
73
      rdPending0    : out std_logic;    -- true if read operation(s) are still in the pipeline
74
      done0         : out std_logic;    -- read or write operation is done
75
      rdDone0       : out std_logic;    -- read operation is done and data is available
76
      hAddr0        : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host to SDRAM
77
      hDIn0         : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host to SDRAM
78
      hDOut0        : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM to host
79
      status0       : out std_logic_vector(3 downto 0);  -- diagnostic status of the SDRAM controller FSM         
80
 
81
      -- host-side port 1
82
      rst1          : in  std_logic;
83
      rd1           : in  std_logic;
84
      wr1           : in  std_logic;
85
      uds1          : in  std_logic;
86
      lds1          : in  std_logic;
87
      earlyOpBegun1 : out std_logic;
88
      opBegun1      : out std_logic;
89
      rdPending1    : out std_logic;
90
      done1         : out std_logic;
91
      rdDone1       : out std_logic;
92
      hAddr1        : in  std_logic_vector(HADDR_WIDTH-1 downto 0);
93
      hDIn1         : in  std_logic_vector(DATA_WIDTH-1 downto 0);
94
      hDOut1        : out std_logic_vector(DATA_WIDTH-1 downto 0);
95
      status1       : out std_logic_vector(3 downto 0);
96
 
97
      -- SDRAM controller port
98
      rst          : out std_logic;
99
      rd           : out std_logic;
100
      wr           : out std_logic;
101
      earlyOpBegun : in  std_logic;
102
      opBegun      : in  std_logic;
103
      rdPending    : in  std_logic;
104
      done         : in  std_logic;
105
      rdDone       : in  std_logic;
106
      hAddr        : out std_logic_vector(HADDR_WIDTH-1 downto 0);
107
      hDIn         : out std_logic_vector(DATA_WIDTH-1 downto 0);
108
      hDOut        : in  std_logic_vector(DATA_WIDTH-1 downto 0);
109
      status       : in  std_logic_vector(3 downto 0)
110
      );
111
  end component;
112
 
113
end package sdram;
114
 
115
 
116
 
117
 
118
--------------------------------------------------------------------
119
-- Company : XESS Corp.
120
-- Engineer : Dave Vanden Bout
121
-- Creation Date : 05/17/2005
122
-- Copyright : 2005, XESS Corp
123
-- Tool Versions : WebPACK 6.3.03i
124
--
125
-- Description:
126
-- SDRAM controller
127
--
128
-- Revision:
129
-- 1.5.0
130
--
131
-- Additional Comments:
132
-- 1.5.0:
133
-- John Kent 2008-03-28
134
-- added upper and lower data strobes.
135
-- 1.4.0:
136
-- Added generic parameter to enable/disable independent active rows in each bank.
137
-- 1.3.0:
138
-- Modified to allow independently active rows in each bank.
139
-- 1.2.0:
140
-- Modified to allow pipelining of read/write operations.
141
-- 1.1.0:
142
-- Initial release.
143
--
144
-- License:
145
-- This code can be freely distributed and modified as long as
146
-- this header is not removed.
147
--------------------------------------------------------------------
148
 
149
library IEEE, UNISIM;
150
use IEEE.std_logic_1164.all;
151
use IEEE.std_logic_unsigned.all;
152
use IEEE.numeric_std.all;
153
use WORK.common.all;
154
 
155
entity sdramCntl is
156
  generic(
157
    FREQ                 :     natural := 100_000;  -- operating frequency in KHz
158
    IN_PHASE             :     boolean := true;  -- SDRAM and controller work on same or opposite clock edge
159
    PIPE_EN              :     boolean := false;  -- if true, enable pipelined read operations
160
    MAX_NOP              :     natural := 10000;  -- number of NOPs before entering self-refresh
161
    MULTIPLE_ACTIVE_ROWS :     boolean := false;  -- if true, allow an active row in each bank
162
    DATA_WIDTH           :     natural := 16;  -- host & SDRAM data width
163
    NROWS                :     natural := 8192;  -- number of rows in SDRAM array
164
    NCOLS                :     natural := 512;  -- number of columns in SDRAM array
165
    HADDR_WIDTH          :     natural := 24;  -- host-side address width
166
    SADDR_WIDTH          :     natural := 13  -- SDRAM-side address width
167
    );
168
  port(
169
    -- host side
170
    clk                  : in  std_logic;  -- master clock
171
    lock                 : in  std_logic;  -- true if clock is stable
172
    rst                  : in  std_logic;  -- reset
173
    rd                   : in  std_logic;  -- initiate read operation
174
    wr                   : in  std_logic;  -- initiate write operation
175
    uds                  : in  std_logic;  -- upper data strobe
176
    lds                  : in  std_logic;  -- lower data strobe
177
    earlyOpBegun         : out std_logic;  -- read/write/self-refresh op has begun (async)
178
    opBegun              : out std_logic;  -- read/write/self-refresh op has begun (clocked)
179
    rdPending            : out std_logic;  -- true if read operation(s) are still in the pipeline
180
    done                 : out std_logic;  -- read or write operation is done
181
    rdDone               : out std_logic;  -- read operation is done and data is available
182
    hAddr                : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host to SDRAM
183
    hDIn                 : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host       to SDRAM
184
    hDOut                : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM to host
185
    status               : out std_logic_vector(3 downto 0);  -- diagnostic status of the FSM         
186
 
187
    -- SDRAM side
188
    cke     : out std_logic;            -- clock-enable to SDRAM
189
    ce_n    : out std_logic;            -- chip-select to SDRAM
190
    ras_n   : out std_logic;            -- SDRAM row address strobe
191
    cas_n   : out std_logic;            -- SDRAM column address strobe
192
    we_n    : out std_logic;            -- SDRAM write enable
193
    ba      : out std_logic_vector(1 downto 0);  -- SDRAM bank address
194
    sAddr   : out std_logic_vector(SADDR_WIDTH-1 downto 0);  -- SDRAM row/column address
195
    sDIn    : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM
196
    sDOut   : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data to SDRAM
197
    sDOutEn : out std_logic;            -- true if data is output to SDRAM on sDOut
198
    dqmh    : out std_logic;            -- enable upper-byte of SDRAM databus if true
199
    dqml    : out std_logic             -- enable lower-byte of SDRAM databus if true
200
    );
201
end sdramCntl;
202
 
203
 
204
 
205
architecture arch of sdramCntl is
206
 
207
  constant OUTPUT : std_logic := '1';   -- direction of dataflow w.r.t. this controller
208
  constant INPUT  : std_logic := '0';
209
  constant NOP    : std_logic := '0';   -- no operation
210
  constant READ   : std_logic := '1';   -- read operation
211
  constant WRITE  : std_logic := '1';   -- write operation
212
 
213
  -- SDRAM timing parameters
214
  constant Tinit : natural := 200;      -- min initialization interval (us)
215
  constant Tras  : natural := 45;       -- min interval between active to precharge commands (ns)
216
  constant Trcd  : natural := 20;       -- min interval between active and R/W commands (ns)
217
  constant Tref  : natural := 64_000_000;  -- maximum refresh interval (ns)
218
  constant Trfc  : natural := 66;       -- duration of refresh operation (ns)
219
  constant Trp   : natural := 20;       -- min precharge command duration (ns)
220
  constant Twr   : natural := 15;       -- write recovery time (ns)
221
  constant Txsr  : natural := 75;       -- exit self-refresh time (ns)
222
 
223
  -- SDRAM timing parameters converted into clock cycles (based on FREQ)
224
  constant NORM        : natural := 1_000_000;  -- normalize ns * KHz
225
  constant INIT_CYCLES : natural := 1+((Tinit*FREQ)/1000);  -- SDRAM power-on initialization interval
226
  constant RAS_CYCLES  : natural := 1+((Tras*FREQ)/NORM);  -- active-to-precharge interval
227
  constant RCD_CYCLES  : natural := 1+((Trcd*FREQ)/NORM);  -- active-to-R/W interval
228
  constant REF_CYCLES  : natural := 1+(((Tref/NROWS)*FREQ)/NORM);  -- interval between row refreshes
229
  constant RFC_CYCLES  : natural := 1+((Trfc*FREQ)/NORM);  -- refresh operation interval
230
  constant RP_CYCLES   : natural := 1+((Trp*FREQ)/NORM);  -- precharge operation interval
231
  constant WR_CYCLES   : natural := 1+((Twr*FREQ)/NORM);  -- write recovery time
232
  constant XSR_CYCLES  : natural := 1+((Txsr*FREQ)/NORM);  -- exit self-refresh time
233
  constant MODE_CYCLES : natural := 2;  -- mode register setup time
234
  constant CAS_CYCLES  : natural := 3;  -- CAS latency
235
  constant RFSH_OPS    : natural := 8;  -- number of refresh operations needed to init SDRAM
236
 
237
  -- timer registers that count down times for various SDRAM operations
238
  signal timer_r, timer_x       : natural range 0 to INIT_CYCLES;  -- current SDRAM op time
239
  signal rasTimer_r, rasTimer_x : natural range 0 to RAS_CYCLES;  -- active-to-precharge time
240
  signal wrTimer_r, wrTimer_x   : natural range 0 to WR_CYCLES;  -- write-to-precharge time
241
  signal refTimer_r, refTimer_x : natural range 0 to REF_CYCLES;  -- time between row refreshes
242
  signal rfshCntr_r, rfshCntr_x : natural range 0 to NROWS;  -- counts refreshes that are neede
243
  signal nopCntr_r, nopCntr_x   : natural range 0 to MAX_NOP;  -- counts consecutive NOP operations
244
 
245
  signal doSelfRfsh : std_logic;        -- active when the NOP counter hits zero and self-refresh can start
246
 
247
  -- states of the SDRAM controller state machine
248
  type cntlState is (
249
    INITWAIT,                           -- initialization - waiting for power-on initialization to complete
250
    INITPCHG,                           -- initialization - initial precharge of SDRAM banks
251
    INITSETMODE,                        -- initialization - set SDRAM mode
252
    INITRFSH,                           -- initialization - do initial refreshes
253
    RW,                                 -- read/write/refresh the SDRAM
254
    ACTIVATE,                           -- open a row of the SDRAM for reading/writing
255
    REFRESHROW,                         -- refresh a row of the SDRAM
256
    SELFREFRESH                         -- keep SDRAM in self-refresh mode with CKE low
257
    );
258
  signal state_r, state_x : cntlState;  -- state register and next state
259
 
260
  -- commands that are sent to the SDRAM to make it perform certain operations
261
  -- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n,dqmh,dqml)
262
--  subtype sdramCmd is unsigned(5 downto 0);
263
--  constant NOP_CMD    : sdramCmd := "011100";
264
--  constant ACTIVE_CMD : sdramCmd := "001100";
265
--  constant READ_CMD   : sdramCmd := "010100";
266
--  constant WRITE_CMD  : sdramCmd := "010000";
267
--  constant PCHG_CMD   : sdramCmd := "001011";
268
--  constant MODE_CMD   : sdramCmd := "000011";
269
--  constant RFSH_CMD   : sdramCmd := "000111";
270
 
271
  -- commands that are sent to the SDRAM to make it perform certain operations
272
  -- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n)
273
  subtype sdramCmd is unsigned(3 downto 0);
274
  constant NOP_CMD    : sdramCmd := "0111";
275
  constant ACTIVE_CMD : sdramCmd := "0011";
276
  constant READ_CMD   : sdramCmd := "0101";
277
  constant WRITE_CMD  : sdramCmd := "0100";
278
  constant PCHG_CMD   : sdramCmd := "0010";
279
  constant MODE_CMD   : sdramCmd := "0000";
280
  constant RFSH_CMD   : sdramCmd := "0001";
281
 
282
  -- SDRAM mode register
283
  -- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS
284
  subtype sdramMode is std_logic_vector(12 downto 0);
285
  constant MODE : sdramMode := "000" & "0" & "00" & "011" & "0" & "000";
286
 
287
  -- the host address is decomposed into these sets of SDRAM address components
288
  constant ROW_LEN : natural := log2(NROWS);  -- number of row address bits
289
  constant COL_LEN : natural := log2(NCOLS);  -- number of column address bits
290
  signal   bank    : std_logic_vector(ba'range);  -- bank address bits
291
  signal   row     : std_logic_vector(ROW_LEN - 1 downto 0);  -- row address within bank
292
  signal   col     : std_logic_vector(sAddr'range);  -- column address within row
293
 
294
  -- registers that store the currently active row in each bank of the SDRAM
295
  constant NUM_ACTIVE_ROWS            : integer := int_select(MULTIPLE_ACTIVE_ROWS = false, 1, 2**ba'length);
296
  type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range);
297
  signal   activeRow_r, activeRow_x   : activeRowType;
298
  signal   activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1);  -- indicates that some row in a bank is active
299
  signal   bankIndex                  : natural range 0 to NUM_ACTIVE_ROWS-1;  -- bank address bits
300
  signal   activeBank_r, activeBank_x : std_logic_vector(ba'range);  -- indicates the bank with the active row
301
  signal   doActivate                 : std_logic;  -- indicates when a new row in a bank needs to be activated
302
 
303
  -- there is a command bit embedded within the SDRAM column address
304
  constant CMDBIT_POS    : natural   := 10;  -- position of command bit
305
  constant AUTO_PCHG_ON  : std_logic := '1';  -- CMDBIT value to auto-precharge the bank
306
  constant AUTO_PCHG_OFF : std_logic := '0';  -- CMDBIT value to disable auto-precharge
307
  constant ONE_BANK      : std_logic := '0';  -- CMDBIT value to select one bank
308
  constant ALL_BANKS     : std_logic := '1';  -- CMDBIT value to select all banks
309
 
310
  -- status signals that indicate when certain operations are in progress
311
  signal wrInProgress       : std_logic;  -- write operation in progress
312
  signal rdInProgress       : std_logic;  -- read operation in progress
313
  signal activateInProgress : std_logic;  -- row activation is in progress
314
 
315
  -- these registers track the progress of read and write operations
316
  signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0);  -- pipeline of read ops in progress
317
  signal wrPipeline_r, wrPipeline_x : std_logic_vector(0 downto 0);  -- pipeline of write ops (only need 1 cycle)
318
 
319
  -- registered outputs to host
320
  signal opBegun_r, opBegun_x             : std_logic;  -- true when SDRAM read or write operation is started
321
  signal hDOut_r, hDOut_x                 : std_logic_vector(hDOut'range);  -- holds data read from SDRAM and sent to the host
322
  signal hDOutOppPhase_r, hDOutOppPhase_x : std_logic_vector(hDOut'range);  -- holds data read from SDRAM   on opposite clock edge
323
 
324
  -- registered outputs to SDRAM
325
  signal cke_r, cke_x           : std_logic;  -- clock enable 
326
  signal cmd_r, cmd_x           : sdramCmd;  -- SDRAM command bits
327
  signal ba_r, ba_x             : std_logic_vector(ba'range);  -- SDRAM bank address bits
328
  signal sAddr_r, sAddr_x       : std_logic_vector(sAddr'range);  -- SDRAM row/column address
329
  signal sData_r, sData_x       : std_logic_vector(sDOut'range);  -- SDRAM out databus
330
  signal dqmh_r, dqmh_x         : std_logic;  -- SDRAM upper data mask
331
  signal dqml_r, dqml_x         : std_logic;  -- SDRAM lower data mask
332
  signal sDataDir_r, sDataDir_x : std_logic;  -- SDRAM databus direction control bit
333
 
334
begin
335
 
336
assign_single_port : process( cmd_r, dqmh_r, dqml_r, cke_r,
337
                              ba_r, sAddr_r,
338
                                                                 sData_r, sDataDir_r,
339
                              hDOut_r, opBegun_r )
340
begin
341
  -----------------------------------------------------------
342
  -- attach some internal signals to the I/O ports 
343
  -----------------------------------------------------------
344
 
345
  -- attach registered SDRAM control signals to SDRAM input pins
346
  (ce_n, ras_n, cas_n, we_n) <= cmd_r;  -- SDRAM operation control bits
347
  dqmh                                     <= dqmh_r;
348
  dqml                       <= dqml_r;
349
  cke                        <= cke_r;  -- SDRAM clock enable
350
  ba                         <= ba_r;  -- SDRAM bank address
351
  sAddr                      <= sAddr_r;  -- SDRAM address
352
  sDOut                      <= sData_r;  -- SDRAM output data bus
353
  if sDataDir_r = OUTPUT then
354
     sDOutEn                 <= YES;
355
  else
356
     sDOutEn                 <= NO;  -- output databus enable
357
  end if;
358
  -- attach some port signals
359
  hDOut   <= hDOut_r;                   -- data back to host
360
  opBegun <= opBegun_r;                 -- true if requested operation has begun
361
end process;
362
 
363
 
364
  -----------------------------------------------------------
365
  -- compute the next state and outputs 
366
  -----------------------------------------------------------
367
 
368
  combinatorial : process(rd, wr, hAddr, hDIn, hDOut_r, sDIn, state_r, opBegun_x,
369
                          activeFlag_r, activeRow_r, rdPipeline_r, wrPipeline_r,
370
                          hDOutOppPhase_r, nopCntr_r, lock, rfshCntr_r, timer_r, rasTimer_r,
371
                          wrTimer_r, refTimer_r, cmd_r, uds, lds, cke_r, activeBank_r, ba_r )
372
  begin
373
 
374
    -----------------------------------------------------------
375
    -- setup default values for signals 
376
    -----------------------------------------------------------
377
 
378
    opBegun_x    <= NO;                 -- no operations have begun
379
    earlyOpBegun <= opBegun_x;
380
    cke_x        <= YES;                -- enable SDRAM clock
381
    cmd_x        <= NOP_CMD;            -- set SDRAM command to no-operation
382
    dqmh_x       <= '0';
383
         dqml_x       <= '0';
384
    sDataDir_x   <= INPUT;              -- accept data from the SDRAM
385
    sData_x      <= hDIn(sData_x'range);  -- output data from host to SDRAM
386
    state_x      <= state_r;            -- reload these registers and flags
387
    activeFlag_x <= activeFlag_r;       --              with their existing values
388
    activeRow_x  <= activeRow_r;
389
    activeBank_x <= activeBank_r;
390
    rfshCntr_x   <= rfshCntr_r;
391
 
392
    -----------------------------------------------------------
393
    -- setup default value for the SDRAM address 
394
    -----------------------------------------------------------
395
 
396
    -- extract bank field from host address
397
    ba_x                    <= hAddr(ba'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN);
398
    if MULTIPLE_ACTIVE_ROWS = true then
399
      bank                  <= (others => '0');
400
      bankIndex             <= CONV_INTEGER(ba_x);
401
    else
402
      bank                  <= ba_x;
403
      bankIndex             <= 0;
404
    end if;
405
    -- extract row, column fields from host address
406
    row                     <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN);
407
    -- extend column (if needed) until it is as large as the (SDRAM address bus - 1)
408
    col                     <= (others => '0');  -- set it to all zeroes
409
    col(COL_LEN-1 downto 0) <= hAddr(COL_LEN-1 downto 0);
410
    -- by default, set SDRAM address to the column address with interspersed
411
    -- command bit set to disable auto-precharge
412
    sAddr_x                 <= col(col'high downto CMDBIT_POS+1) & AUTO_PCHG_OFF
413
                               & col(CMDBIT_POS-1 downto 0);
414
 
415
    -----------------------------------------------------------
416
    -- manage the read and write operation pipelines
417
    -----------------------------------------------------------
418
 
419
    -- determine if read operations are in progress by the presence of
420
    -- READ flags in the read pipeline 
421
    if rdPipeline_r(rdPipeline_r'high downto 1) /= 0 then
422
      rdInProgress <= YES;
423
    else
424
      rdInProgress <= NO;
425
    end if;
426
    rdPending      <= rdInProgress;     -- tell the host if read operations are in progress
427
 
428
    -- enter NOPs into the read and write pipeline shift registers by default
429
    rdPipeline_x    <= NOP & rdPipeline_r(rdPipeline_r'high downto 1);
430
    wrPipeline_x(0) <= NOP;
431
 
432
    -- transfer data from SDRAM to the host data register if a read flag has exited the pipeline
433
    -- (the transfer occurs 1 cycle before we tell the host the read operation is done)
434
    if rdPipeline_r(1) = READ then
435
      hDOutOppPhase_x <= sDIn(hDOut'range);  -- gets value on the SDRAM databus on the opposite phase
436
      if IN_PHASE then
437
        -- get the SDRAM data for the host directly from the SDRAM if the controller and SDRAM are in-phase
438
        hDOut_x       <= sDIn(hDOut'range);
439
      else
440
        -- otherwise get the SDRAM data that was gathered on the previous opposite clock edge
441
        hDOut_x       <= hDOutOppPhase_r(hDOut'range);
442
      end if;
443
    else
444
      -- retain contents of host data registers if no data from the SDRAM has arrived yet
445
      hDOutOppPhase_x <= hDOutOppPhase_r;
446
      hDOut_x         <= hDOut_r;
447
    end if;
448
 
449
    done   <= rdPipeline_r(0) or wrPipeline_r(0);  -- a read or write operation is done
450
    rdDone <= rdPipeline_r(0);          -- SDRAM data available when a READ flag exits the pipeline 
451
 
452
    -----------------------------------------------------------
453
    -- manage row activation
454
    -----------------------------------------------------------
455
 
456
    -- request a row activation operation if the row of the current address
457
    -- does not match the currently active row in the bank, or if no row
458
    -- in the bank is currently active
459
    if (bank /= activeBank_r) or (row /= activeRow_r(bankIndex)) or (activeFlag_r(bankIndex) = NO) then
460
      doActivate <= YES;
461
    else
462
      doActivate <= NO;
463
    end if;
464
 
465
    -----------------------------------------------------------
466
    -- manage self-refresh
467
    -----------------------------------------------------------
468
 
469
    -- enter self-refresh if neither a read or write is requested for MAX_NOP consecutive cycles.
470
    if (rd = YES) or (wr = YES) then
471
      -- any read or write resets NOP counter and exits self-refresh state
472
      nopCntr_x  <= 0;
473
      doSelfRfsh <= NO;
474
    elsif nopCntr_r /= MAX_NOP then
475
      -- increment NOP counter whenever there is no read or write operation 
476
      nopCntr_x  <= nopCntr_r + 1;
477
      doSelfRfsh <= NO;
478
    else
479
      -- start self-refresh when counter hits maximum NOP count and leave counter unchanged
480
      nopCntr_x  <= nopCntr_r;
481
      doSelfRfsh <= YES;
482
    end if;
483
 
484
    -----------------------------------------------------------
485
    -- update the timers 
486
    -----------------------------------------------------------
487
 
488
    -- row activation timer
489
    if rasTimer_r /= 0 then
490
      -- decrement a non-zero timer and set the flag
491
      -- to indicate the row activation is still inprogress
492
      rasTimer_x         <= rasTimer_r - 1;
493
      activateInProgress <= YES;
494
    else
495
      -- on timeout, keep the timer at zero     and reset the flag
496
      -- to indicate the row activation operation is done
497
      rasTimer_x         <= rasTimer_r;
498
      activateInProgress <= NO;
499
    end if;
500
 
501
    -- write operation timer            
502
    if wrTimer_r /= 0 then
503
      -- decrement a non-zero timer and set the flag
504
      -- to indicate the write operation is still inprogress
505
      wrTimer_x    <= wrTimer_r - 1;
506
      wrInPRogress <= YES;
507
    else
508
      -- on timeout, keep the timer at zero and reset the flag that
509
      -- indicates a write operation is in progress
510
      wrTimer_x    <= wrTimer_r;
511
      wrInPRogress <= NO;
512
    end if;
513
 
514
    -- refresh timer            
515
    if refTimer_r /= 0 then
516
      refTimer_x <= refTimer_r - 1;
517
    else
518
      -- on timeout, reload the timer with the interval between row refreshes
519
      -- and increment the counter for the number of row refreshes that are needed
520
      refTimer_x <= REF_CYCLES;
521
      rfshCntr_x <= rfshCntr_r + 1;
522
    end if;
523
 
524
    -- main timer for sequencing SDRAM operations               
525
    if timer_r /= 0 then
526
      -- decrement the timer and do nothing else since the previous operation has not completed yet.
527
      timer_x <= timer_r - 1;
528
      status  <= "0000";
529
    else
530
      -- the previous operation has completed once the timer hits zero
531
      timer_x <= timer_r;               -- by default, leave the timer at zero
532
 
533
      -----------------------------------------------------------
534
      -- compute the next state and outputs 
535
      -----------------------------------------------------------
536
      case state_r is
537
 
538
        -----------------------------------------------------------
539
        -- let clock stabilize and then wait for the SDRAM to initialize 
540
        -----------------------------------------------------------
541
        when INITWAIT =>
542
          if lock = YES then
543
                                        -- wait for SDRAM power-on initialization once the clock is stable
544
            timer_x <= INIT_CYCLES;     -- set timer for initialization duration
545
            state_x <= INITPCHG;
546
          else
547
                                        -- disable SDRAM clock and return to this state if the clock is not stable
548
                                        -- this insures the clock is stable before enabling the SDRAM
549
                                        -- it also insures a clean startup if the SDRAM is currently in self-refresh mode
550
            cke_x   <= NO;
551
          end if;
552
          status    <= "0001";
553
 
554
          -----------------------------------------------------------
555
          -- precharge all SDRAM banks after power-on initialization 
556
          -----------------------------------------------------------
557
        when INITPCHG =>
558
          cmd_x               <= PCHG_CMD;
559
                         dqmh_x              <= '1';
560
                         dqml_x              <= '1';
561
          sAddr_x(CMDBIT_POS) <= ALL_BANKS;  -- precharge all banks
562
          timer_x             <= RP_CYCLES;  -- set timer for precharge operation duration
563
          rfshCntr_x          <= RFSH_OPS;  -- set counter for refresh ops needed after precharge
564
          state_x             <= INITRFSH;
565
          status              <= "0010";
566
 
567
          -----------------------------------------------------------
568
          -- refresh the SDRAM a number of times after initial precharge 
569
          -----------------------------------------------------------
570
        when INITRFSH =>
571
          cmd_x      <= RFSH_CMD;
572
                         dqmh_x     <= '1';
573
                         dqml_x     <= '1';
574
          timer_x    <= RFC_CYCLES;     -- set timer to refresh operation duration
575
          rfshCntr_x <= rfshCntr_r - 1;  -- decrement refresh operation counter
576
          if rfshCntr_r = 1 then
577
            state_x  <= INITSETMODE;    -- set the SDRAM mode once all refresh ops are done
578
          end if;
579
          status     <= "0011";
580
 
581
          -----------------------------------------------------------
582
          -- set the mode register of the SDRAM 
583
          -----------------------------------------------------------
584
        when INITSETMODE =>
585
          cmd_x   <= MODE_CMD;
586
                         dqmh_x  <= '1';
587
                         dqml_x  <= '1';
588
          sAddr_x <= MODE;              -- output mode register bits on the SDRAM address bits
589
          timer_x <= MODE_CYCLES;       -- set timer for mode setting operation duration
590
          state_x <= RW;
591
          status  <= "0100";
592
 
593
          -----------------------------------------------------------
594
          -- process read/write/refresh operations after initialization is done 
595
          -----------------------------------------------------------
596
        when RW                                      =>
597
          -----------------------------------------------------------
598
          -- highest priority operation: row refresh 
599
          -- do a refresh operation if the refresh counter is non-zero
600
          -----------------------------------------------------------
601
          if rfshCntr_r /= 0 then
602
                                        -- wait for any row activations, writes or reads to finish before doing a precharge
603
            if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
604
              cmd_x                       <= PCHG_CMD;  -- initiate precharge of the SDRAM
605
              dqmh_x                      <= '1';
606
              dqml_x                      <= '1';
607
              sAddr_x(CMDBIT_POS)         <= ALL_BANKS;  -- precharge all banks
608
              timer_x                     <= RP_CYCLES;  -- set timer for this operation
609
              activeFlag_x                <= (others => NO);  -- all rows are inactive after a precharge operation
610
              state_x                     <= REFRESHROW;  -- refresh the SDRAM after the precharge
611
            end if;
612
            status                        <= "0101";
613
            -----------------------------------------------------------
614
            -- do a host-initiated read operation 
615
            -----------------------------------------------------------
616
          elsif rd = YES then
617
                                          -- Wait one clock cycle if the bank address has just changed and each bank has its own active row.
618
            -- This gives extra time for the row activation circuitry.
619
            if (ba_x = ba_r) or (MULTIPLE_ACTIVE_ROWS=false) then
620
                                        -- activate a new row if the current read is outside the active row or bank
621
              if doActivate = YES then
622
                                        -- activate new row only if all previous activations, writes, reads are done
623
                if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
624
                  cmd_x                   <= PCHG_CMD;  -- initiate precharge of the SDRAM
625
                  dqmh_x                  <= '1';
626
                  dqml_x                  <= '1';
627
                  sAddr_x(CMDBIT_POS)     <= ONE_BANK;  -- precharge this bank
628
                  timer_x                 <= RP_CYCLES;  -- set timer for this operation
629
                  activeFlag_x(bankIndex) <= NO;  -- rows in this bank are inactive after a precharge operation
630
                  state_x                 <= ACTIVATE;  -- activate the new row after the precharge is done
631
                end if;
632
                                        -- read from the currently active row if no previous read operation
633
                                        -- is in progress or if pipeline reads are enabled
634
                                        -- we can always initiate a read even if a write is already in progress
635
              elsif (rdInProgress = NO) or PIPE_EN then
636
                cmd_x                     <= READ_CMD;  -- initiate a read of the SDRAM
637
                                        -- insert a flag into the pipeline shift register that will exit the end
638
                                        -- of the shift register when the data from the SDRAM is available
639
                dqmh_x                    <= not uds;
640
                dqml_x                    <= not lds;
641
                rdPipeline_x              <= READ & rdPipeline_r(rdPipeline_r'high downto 1);
642
                opBegun_x                 <= YES;  -- tell the host the requested operation has begun
643
              end if;
644
            end if;
645
            status                        <= "0110";
646
            -----------------------------------------------------------
647
            -- do a host-initiated write operation 
648
            -----------------------------------------------------------
649
          elsif wr = YES then
650
                                          -- Wait one clock cycle if the bank address has just changed and each bank has its own active row.
651
            -- This gives extra time for the row activation circuitry.
652
            if (ba_x = ba_r) or (MULTIPLE_ACTIVE_ROWS=false) then
653
                                        -- activate a new row if the current write is outside the active row or bank
654
              if doActivate = YES then
655
                                        -- activate new row only if all previous activations, writes, reads are done
656
                if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
657
                  cmd_x                   <= PCHG_CMD;  -- initiate precharge of the SDRAM
658
                  dqmh_x                  <= '1';
659
                  dqml_x                  <= '1';
660
                  sAddr_x(CMDBIT_POS)     <= ONE_BANK;  -- precharge this bank
661
                  timer_x                 <= RP_CYCLES;  -- set timer for this operation
662
                  activeFlag_x(bankIndex) <= NO;  -- rows in this bank are inactive after a precharge operation
663
                  state_x                 <= ACTIVATE;  -- activate the new row after the precharge is done
664
                end if;
665
                                        -- write to the currently active row if no previous read operations are in progress
666
              elsif rdInProgress = NO then
667
                cmd_x                     <= WRITE_CMD;  -- initiate the write operation
668
                dqmh_x                    <= not uds;
669
                dqml_x                    <= not lds;
670
                sDataDir_x                <= OUTPUT;  -- turn on drivers to send data to SDRAM
671
                                        -- set timer so precharge doesn't occur too soon after write operation
672
                wrTimer_x                 <= WR_CYCLES;
673
                                        -- insert a flag into the 1-bit pipeline shift register that will exit on the
674
                                        -- next cycle.  The write into SDRAM is not actually done by that time, but
675
                                        -- this doesn't matter to the host
676
                wrPipeline_x(0)           <= WRITE;
677
                opBegun_x                 <= YES;  -- tell the host the requested operation has begun
678
              end if;
679
            end if;
680
            status                        <= "0111";
681
            -----------------------------------------------------------
682
            -- do a host-initiated self-refresh operation 
683
            -----------------------------------------------------------
684
          elsif doSelfRfsh = YES then
685
                                        -- wait until all previous activations, writes, reads are done
686
            if (activateInProgress = NO) and (wrInProgress = NO) and (rdInProgress = NO) then
687
              cmd_x                       <= PCHG_CMD;  -- initiate precharge of the SDRAM
688
              dqmh_x                       <= '1';
689
              dqml_x                       <= '1';
690
              sAddr_x(CMDBIT_POS)         <= ALL_BANKS;  -- precharge all banks
691
              timer_x                     <= RP_CYCLES;  -- set timer for this operation
692
              activeFlag_x                <= (others => NO);  -- all rows are inactive after a precharge operation
693
              state_x                     <= SELFREFRESH;  -- self-refresh the SDRAM after the precharge
694
            end if;
695
            status                        <= "1000";
696
            -----------------------------------------------------------
697
            -- no operation
698
            -----------------------------------------------------------
699
          else
700
            state_x                       <= RW;  -- continue to look for SDRAM operations to execute
701
            status                        <= "1001";
702
          end if;
703
 
704
          -----------------------------------------------------------
705
          -- activate a row of the SDRAM 
706
          -----------------------------------------------------------
707
        when ACTIVATE                        =>
708
          cmd_x                   <= ACTIVE_CMD;
709
          dqmh_x                  <= '0';
710
          dqml_x                  <= '0';
711
          sAddr_x                 <= (others => '0');  -- output the address for the row to be activated
712
          sAddr_x(row'range)      <= row;
713
          activeBank_x            <= bank;
714
          activeRow_x(bankIndex)  <= row;  -- store the new active SDRAM row address
715
          activeFlag_x(bankIndex) <= YES;  -- the SDRAM is now active
716
          rasTimer_x              <= RAS_CYCLES;  -- minimum time before another precharge can occur 
717
          timer_x                 <= RCD_CYCLES;  -- minimum time before a read/write operation can occur
718
          state_x                 <= RW;  -- return to do read/write operation that initiated this activation
719
          status                  <= "1010";
720
 
721
          -----------------------------------------------------------
722
          -- refresh a row of the SDRAM         
723
          -----------------------------------------------------------
724
        when REFRESHROW =>
725
          cmd_x      <= RFSH_CMD;
726
          dqmh_x     <= '1';
727
          dqml_x     <= '1';
728
          timer_x    <= RFC_CYCLES;     -- refresh operation interval
729
          rfshCntr_x <= rfshCntr_r - 1;  -- decrement the number of needed row refreshes
730
          state_x    <= RW;             -- process more SDRAM operations after refresh is done
731
          status     <= "1011";
732
 
733
          -----------------------------------------------------------
734
          -- place the SDRAM into self-refresh and keep it there until further notice           
735
          -----------------------------------------------------------
736
        when SELFREFRESH            =>
737
          if (doSelfRfsh = YES) or (lock = NO) then
738
                                        -- keep the SDRAM in self-refresh mode as long as requested and until there is a stable clock
739
            cmd_x        <= RFSH_CMD;   -- output the refresh command; this is only needed on the first clock cycle
740
            dqmh_x       <= '1';
741
            dqml_x       <= '1';
742
            cke_x        <= NO;         -- disable the SDRAM clock
743
          else
744
                                        -- else exit self-refresh mode and start processing read and write operations
745
            cke_x        <= YES;        -- restart the SDRAM clock
746
            rfshCntr_x   <= 0;          -- no refreshes are needed immediately after leaving self-refresh
747
            activeFlag_x <= (others => NO);  -- self-refresh deactivates all rows
748
            timer_x      <= XSR_CYCLES;  -- wait this long until read and write operations can resume
749
            state_x      <= RW;
750
          end if;
751
          status         <= "1100";
752
 
753
          -----------------------------------------------------------
754
          -- unknown state
755
          -----------------------------------------------------------
756
        when others =>
757
          state_x <= INITWAIT;          -- reset state if in erroneous state
758
          status  <= "1101";
759
 
760
      end case;
761
    end if;
762
  end process combinatorial;
763
 
764
 
765
  -----------------------------------------------------------
766
  -- update registers on the appropriate clock edge     
767
  -----------------------------------------------------------
768
 
769
  update : process(rst, clk)
770
  begin
771
 
772
    if rst = YES then
773
      -- asynchronous reset
774
      state_r      <= INITWAIT;
775
      activeFlag_r <= (others => NO);
776
      rfshCntr_r   <= 0;
777
      timer_r      <= 0;
778
      refTimer_r   <= REF_CYCLES;
779
      rasTimer_r   <= 0;
780
      wrTimer_r    <= 0;
781
      nopCntr_r    <= 0;
782
      opBegun_r    <= NO;
783
      rdPipeline_r <= (others => '0');
784
      wrPipeline_r <= (others => '0');
785
      cke_r        <= NO;
786
      cmd_r        <= NOP_CMD;
787
                dqmh_r       <= '1';
788
                dqml_r       <= '1';
789
      ba_r         <= (others => '0');
790
      sAddr_r      <= (others => '0');
791
      sData_r      <= (others => '0');
792
      sDataDir_r   <= INPUT;
793
      hDOut_r      <= (others => '0');
794
    elsif rising_edge(clk) then
795
      state_r      <= state_x;
796
      activeBank_r <= activeBank_x;
797
      activeRow_r  <= activeRow_x;
798
      activeFlag_r <= activeFlag_x;
799
      rfshCntr_r   <= rfshCntr_x;
800
      timer_r      <= timer_x;
801
      refTimer_r   <= refTimer_x;
802
      rasTimer_r   <= rasTimer_x;
803
      wrTimer_r    <= wrTimer_x;
804
      nopCntr_r    <= nopCntr_x;
805
      opBegun_r    <= opBegun_x;
806
      rdPipeline_r <= rdPipeline_x;
807
      wrPipeline_r <= wrPipeline_x;
808
      cke_r        <= cke_x;
809
      cmd_r        <= cmd_x;
810
                dqmh_r       <= dqmh_x;
811
                dqml_r       <= dqml_x;
812
      ba_r         <= ba_x;
813
      sAddr_r      <= sAddr_x;
814
      sData_r      <= sData_x;
815
      sDataDir_r   <= sDataDir_x;
816
      hDOut_r      <= hDOut_x;
817
    end if;
818
 
819
    -- the register that gets data from the SDRAM and holds it for the host
820
    -- is clocked on the opposite edge.  We don't use this register if IN_PHASE=TRUE.
821
    if rst = YES then
822
      hDOutOppPhase_r <= (others => '0');
823
    elsif falling_edge(clk) then
824
      hDOutOppPhase_r <= hDOutOppPhase_x;
825
    end if;
826
 
827
  end process update;
828
 
829
end arch;
830
 
831
 
832
 
833
 
834
--------------------------------------------------------------------
835
-- Company : XESS Corp.
836
-- Engineer : Dave Vanden Bout
837
-- Creation Date : 06/01/2005
838
-- Copyright : 2005, XESS Corp
839
-- Tool Versions : WebPACK 6.3.03i
840
--
841
-- Description:
842
-- Dual-port front-end for SDRAM controller. Supports two
843
-- independent I/O ports to the SDRAM.
844
--
845
-- Revision:
846
-- 1.2.0:
847
--     added upper and lower data strobe
848
--     John Kent - 2008-03-23
849
--
850
-- 1.0.0
851
--     Dave Vanden Bout - 2005-01-06
852
--
853
-- Additional Comments:
854
--
855
-- License:
856
-- This code can be freely distributed and modified as long as
857
-- this header is not removed.
858
--------------------------------------------------------------------
859
 
860
library IEEE, UNISIM;
861
use IEEE.std_logic_1164.all;
862
use IEEE.std_logic_unsigned.all;
863
use IEEE.numeric_std.all;
864
use WORK.common.all;
865
 
866
entity dualport is
867
  generic(
868
    PIPE_EN         :    boolean                       := false;  -- enable pipelined read operations
869
    PORT_TIME_SLOTS :    std_logic_vector(15 downto 0) := "1111000011110000";
870
    DATA_WIDTH      :    natural                       := 16;  -- host & SDRAM data width
871
    HADDR_WIDTH     :    natural                       := 23  -- host-side address width
872
    );
873
  port(
874
    clk             : in std_logic;     -- master clock
875
 
876
    -- host-side port 0
877
    rst0          : in  std_logic;      -- reset
878
    rd0           : in  std_logic;      -- initiate read operation
879
    wr0           : in  std_logic;      -- initiate write operation
880
    uds0          : in  std_logic;      -- upper data strobe
881
    lds0          : in  std_logic;      -- lower data strobe
882
    earlyOpBegun0 : out std_logic;      -- read/write op has begun (async)
883
    opBegun0      : out std_logic;      -- read/write op has begun (clocked)
884
    rdPending0    : out std_logic;      -- true if read operation(s) are still in the pipeline
885
    done0         : out std_logic;      -- read or write operation is done
886
    rdDone0       : out std_logic;      -- read operation is done and data is available
887
    hAddr0        : in  std_logic_vector(HADDR_WIDTH-1 downto 0);  -- address from host to SDRAM
888
    hDIn0         : in  std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from host to SDRAM
889
    hDOut0        : out std_logic_vector(DATA_WIDTH-1 downto 0);  -- data from SDRAM to host
890
    status0       : out std_logic_vector(3 downto 0);  -- diagnostic status of the SDRAM controller FSM         
891
 
892
    -- host-side port 1
893
    rst1          : in  std_logic;
894
    rd1           : in  std_logic;
895
    wr1           : in  std_logic;
896
    uds1          : in  std_logic;      -- upper data strobe
897
    lds1          : in  std_logic;      -- lower data strobe
898
    earlyOpBegun1 : out std_logic;
899
    opBegun1      : out std_logic;
900
    rdPending1    : out std_logic;
901
    done1         : out std_logic;
902
    rdDone1       : out std_logic;
903
    hAddr1        : in  std_logic_vector(HADDR_WIDTH-1 downto 0);
904
    hDIn1         : in  std_logic_vector(DATA_WIDTH-1 downto 0);
905
    hDOut1        : out std_logic_vector(DATA_WIDTH-1 downto 0);
906
    status1       : out std_logic_vector(3 downto 0);
907
 
908
    -- SDRAM controller port
909
    rst          : out std_logic;
910
    rd           : out std_logic;
911
    wr           : out std_logic;
912
    uds          : out std_logic;      -- upper data strobe
913
    lds          : out std_logic;      -- lower data strobe
914
    earlyOpBegun : in  std_logic;
915
    opBegun      : in  std_logic;
916
    rdPending    : in  std_logic;
917
    done         : in  std_logic;
918
    rdDone       : in  std_logic;
919
    hAddr        : out std_logic_vector(HADDR_WIDTH-1 downto 0);
920
    hDIn         : out std_logic_vector(DATA_WIDTH-1 downto 0);
921
    hDOut        : in  std_logic_vector(DATA_WIDTH-1 downto 0);
922
    status       : in  std_logic_vector(3 downto 0)
923
    );
924
end dualport;
925
 
926
 
927
 
928
architecture arch of dualport is
929
  -- The door signal controls whether the read/write signal from the active port
930
  -- is allowed through to the read/write inputs of the SDRAM controller.
931
  type doorState is (OPENED, CLOSED);
932
  signal door_r, door_x : doorState;
933
 
934
  -- The port signal indicates which port is connected to the SDRAM controller.
935
  type portState is (PORT0, PORT1);
936
  signal port_r, port_x : portState;
937
 
938
  signal switch                           : std_logic;  -- indicates that the active port should be switched
939
  signal inProgress                       : std_logic;  -- the active port has a read/write op in-progress
940
  signal rd_i                             : std_logic;  -- read signal to the SDRAM controller (internal copy)
941
  signal wr_i                             : std_logic;  -- write signal to the SDRAM controller (internal copy)
942
  signal earlyOpBegun0_i, earlyOpBegun1_i : std_logic;  -- (internal copies)
943
  signal slot_r, slot_x                   : std_logic_vector(PORT_TIME_SLOTS'range);  -- time-slot allocation shift-register
944
begin
945
 
946
assign_dual_ports : process( port_r, hAddr0, hAddr1, hDIn0, hDIn1, uds0, uds1, lds0, lds1,
947
                             hDout, status, rst0, rst1, rd0, rd1, wr0, wr1, door_r,
948
                             earlyOpBegun, earlyOpBegun0_i, earlyOpBegun1_i,
949
                             rdPending, Done, rdDone, rd_i, wr_i, slot_r )
950
begin
951
  ----------------------------------------------------------------------------
952
  -- multiplex the SDRAM controller port signals to/from the dual host-side ports  
953
  ----------------------------------------------------------------------------
954
 
955
  -- send the SDRAM controller the address and data from the currently active port
956
  if port_r = PORT0 then
957
    hAddr   <= hAddr0;
958
    hDIn    <= hDIn0;
959
    uds     <= uds0;
960
    lds     <= lds0;
961
  -- send the SDRAM controller status to the active port and give the inactive port an inactive status code
962
    status0 <= status;
963
         status1 <= "1111";
964
  -- apply the read and write signals from the active port to the SDRAM controller only if the door is open.
965
         if door_r = OPENED then
966
           rd_i <= rd0;
967
                wr_i <= wr0;
968
         else
969
           rd_i <= NO;
970
                wr_i <= NO;
971
    end if;
972
    earlyOpBegun0_i <= earlyOpBegun;
973
    earlyOpBegun1_i <= NO;
974
    rdPending0      <= rdPending;
975
    rdPending1      <= NO;
976
    done0           <= done;
977
    done1           <= NO;
978
    rdDone0         <= rdDone;
979
    rdDone1         <= NO;
980
  else
981
    hAddr   <= hAddr1;
982
    hDIn    <= hDIn1;
983
    uds     <= uds1;
984
    lds     <= lds1;
985
  -- send the SDRAM controller status to the active port and give the inactive port an inactive status code
986
         status0 <= "1111";
987
    status1 <= status;
988
  -- apply the read and write signals from the active port to the SDRAM controller only if the door is open.
989
         if door_r = OPENED then
990
           rd_i <= rd1;
991
           wr_i <= wr1;
992
         else
993
           rd_i <= NO;
994
           wr_i <= NO;
995
    end if;
996
    earlyOpBegun0_i <= NO;
997
    earlyOpBegun1_i <= earlyOpBegun;
998
    rdPending0      <= NO;
999
    rdPending1      <= rdPending;
1000
    done0           <= NO;
1001
    done1           <= done;
1002
    rdDone0         <= NO;
1003
    rdDone1         <= rdDone;
1004
 end if;
1005
 
1006
  -- both ports get the data from the SDRAM but only the active port will use it
1007
  hDOut0 <= hDOut;
1008
  hDOut1 <= hDOut;
1009
 
1010
 
1011
  -- either port can reset the SDRAM controller
1012
  rst <= rst0 or rst1;
1013
 
1014
  rd   <= rd_i;
1015
  wr   <= wr_i;
1016
 
1017
  ----------------------------------------------------------------------------
1018
  -- Indicate when the active port needs to be switched.  A switch occurs if
1019
  -- a read or write operation is requested on the port that is not currently active and:
1020
  -- 1) no R/W operation is being performed on the active port or 
1021
  -- 2) a R/W operation is in progress on the active port, but the time-slot allocation 
1022
  --    register is giving precedence to the inactive port.  (The R/W operation on the
1023
  --    active port will be completed before the switch is made.)
1024
  -- This rule keeps the active port from hogging all the bandwidth.
1025
  ----------------------------------------------------------------------------
1026
 
1027
  if port_r = PORT0 then
1028
    if (((rd0 = NO) and (wr0 = NO)) or (slot_r(0) = '1')) then
1029
      switch <= (rd1 or wr1);
1030
    else
1031
      switch <= NO;
1032
    end if;
1033
  else
1034
    if (((rd1 = NO) and (wr1 = NO)) or (slot_r(0) = '0')) then
1035
      switch <= (rd0 or wr0);
1036
    else
1037
           switch  <= NO;
1038
    end if;
1039
  end if;
1040
 
1041
  -- send the status signals for various SDRAM controller operations back to the active port
1042
  earlyOpBegun0   <= earlyOpBegun0_i;
1043
  earlyOpBegun1   <= earlyOpBegun1_i;
1044
 
1045
  ----------------------------------------------------------------------------
1046
  -- Indicate when an operation on the active port is in-progress and
1047
  -- can't be interrupted by a switch to the other port.  (Only read operations
1048
  -- are looked at since write operations always complete in one cycle once they
1049
  -- are initiated.)
1050
  ----------------------------------------------------------------------------
1051
  inProgress <= rdPending or (rd_i and earlyOpBegun);
1052
 
1053
  ----------------------------------------------------------------------------
1054
  -- Update the time-slot allocation shift-register.  The port with priority is indicated by the
1055
  -- least-significant bit of the register.  The register is rotated right if:
1056
  -- 1) the current R/W operation has started, and
1057
  -- 2) both ports are requesting R/W operations (indicating contention), and
1058
  -- 3) the currently active port matches the port that currently has priority.
1059
  -- Under these conditions, the current time slot port allocation has been used so
1060
  -- the shift register is rotated right to bring the next port time-slot allocation
1061
  -- bit into play.
1062
  ----------------------------------------------------------------------------
1063
  if (earlyOpBegun = YES) and
1064
     ( ((rd0 = YES) or (wr0 = YES)) and ((rd1 = YES) or (wr1 = YES)) ) and
1065
     ( ((port_r = PORT0) and (slot_r(0) = '0')) or ((port_r = PORT1) and (slot_r(0) = '1')) ) then
1066
    slot_x <= slot_r(0) & slot_r(slot_r'high downto 1);
1067
  else
1068
    slot_x <= slot_r;
1069
  end if;
1070
 
1071
end process;
1072
 
1073
  ----------------------------------------------------------------------------
1074
  -- Determine which port will be active on the next cycle.  The active port is switched if:
1075
  -- 1) the currently active port has finished its current R/W operation, and
1076
  -- 2) there are no pending operations in progress, and
1077
  -- 3) the port switch indicator is active.
1078
  ----------------------------------------------------------------------------
1079
  port_process : process(port_r, inProgress, switch, done)
1080
  begin
1081
    port_x       <= port_r;             -- by default, the active port is not changed
1082
    case port_r is
1083
      when PORT0  =>
1084
        if (inProgress = NO) and (switch = YES) and (PIPE_EN or (done = YES)) then
1085
          port_x <= PORT1;
1086
        end if;
1087
      when PORT1  =>
1088
        if (inProgress = NO) and (switch = YES) and (PIPE_EN or (done = YES)) then
1089
          port_x <= PORT0;
1090
        end if;
1091
      when others =>
1092
        port_x   <= port_r;
1093
    end case;
1094
  end process port_process;
1095
 
1096
  -----------------------------------------------------------
1097
  -- Determine if the door is open for the active port to initiate new R/W operations to
1098
  -- the SDRAM controller.  If the door is open and R/W operations are in progress but
1099
  -- a switch to the other port is indicated, then the door is closed to prevent any
1100
  -- further R/W operations from the active port.  The door is re-opened once all
1101
  -- in-progress operations are completed, at which time the switch to the other port
1102
  -- is also completed so it can issue its own R/W commands.
1103
  -----------------------------------------------------------
1104
  door_process : process(door_r, inProgress, switch)
1105
  begin
1106
    door_x       <= door_r;             -- by default, the door remains as it is
1107
    case door_r is
1108
      when OPENED =>
1109
        if (inProgress = YES) and (switch = YES) then
1110
          door_x <= CLOSED;
1111
        end if;
1112
      when CLOSED =>
1113
        if inProgress = NO then
1114
          door_x <= OPENED;
1115
        end if;
1116
      when others =>
1117
        door_x   <= door_r;
1118
    end case;
1119
  end process door_process;
1120
 
1121
  -----------------------------------------------------------
1122
  -- update registers on the appropriate clock edge     
1123
  -----------------------------------------------------------
1124
  update : process(rst0, rst1, clk)
1125
  begin
1126
    if (rst0 = YES) or (rst1 = YES) then
1127
      -- asynchronous reset
1128
      door_r   <= CLOSED;
1129
      port_r   <= PORT0;
1130
      slot_r   <= PORT_TIME_SLOTS;
1131
      opBegun0 <= NO;
1132
      opBegun1 <= NO;
1133
    elsif rising_edge(clk) then
1134
      door_r   <= door_x;
1135
      port_r   <= port_x;
1136
      slot_r   <= slot_x;
1137
      -- opBegun signals are cycle-delayed versions of earlyOpBegun signals.
1138
      -- We can't use the actual opBegun signal from the SDRAM controller
1139
      -- because it would be turned off if the active port was switched on the
1140
      -- cycle immediately after earlyOpBegun went active.
1141
      opBegun0 <= earlyOpBegun0_i;
1142
      opBegun1 <= earlyOpBegun1_i;
1143
    end if;
1144
  end process update;
1145
 
1146
end arch;

powered by: WebSVN 2.1.0

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