OpenCores
URL https://opencores.org/ocsvn/395_vgs/395_vgs/trunk

Subversion Repositories 395_vgs

[/] [395_vgs/] [trunk/] [hdl/] [sdramcntl.vhd] - Blame information for rev 32

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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