Line 7... |
Line 7... |
--
|
--
|
-- Description:
|
-- Description:
|
-- Customizes the generic SDRAM controller module for the XSA Board.
|
-- Customizes the generic SDRAM controller module for the XSA Board.
|
--
|
--
|
-- Revision:
|
-- Revision:
|
-- 1.1.0
|
-- 1.2.0
|
--
|
--
|
-- Additional Comments:
|
-- Additional Comments:
|
|
-- 1.2.0:
|
|
-- added upper and lower data strobe signals
|
|
-- John Kent 2008-03-23
|
-- 1.1.0:
|
-- 1.1.0:
|
-- Added CLK_DIV generic parameter to allow stepping-down the clock frequency.
|
-- Added CLK_DIV generic parameter to allow stepping-down the clock frequency.
|
-- Added MULTIPLE_ACTIVE_ROWS generic parameter to enable/disable keeping an active row in each bank.
|
-- Added MULTIPLE_ACTIVE_ROWS generic parameter to enable/disable keeping an active row in each bank.
|
-- 1.0.0:
|
-- 1.0.0:
|
-- Initial release.
|
-- Initial release.
|
Line 56... |
Line 59... |
clk2x : out std_logic; -- double-speed host clock
|
clk2x : out std_logic; -- double-speed host clock
|
lock : out std_logic; -- true when host clock is locked to master clock
|
lock : out std_logic; -- true when host clock is locked to master clock
|
rst : in std_logic; -- reset
|
rst : in std_logic; -- reset
|
rd : in std_logic; -- initiate read operation
|
rd : in std_logic; -- initiate read operation
|
wr : in std_logic; -- initiate write operation
|
wr : in std_logic; -- initiate write operation
|
|
uds : in std_logic; -- upper data strobe
|
|
lds : in std_logic; -- lower data strobe
|
earlyOpBegun : out std_logic; -- read/write/self-refresh op begun (async)
|
earlyOpBegun : out std_logic; -- read/write/self-refresh op begun (async)
|
opBegun : out std_logic; -- read/write/self-refresh op begun (clocked)
|
opBegun : out std_logic; -- read/write/self-refresh op begun (clocked)
|
rdPending : out std_logic; -- read operation(s) are still in the pipeline
|
rdPending : out std_logic; -- read operation(s) are still in the pipeline
|
done : out std_logic; -- read or write operation is done
|
done : out std_logic; -- read or write operation is done
|
rdDone : out std_logic; -- read done and data is available
|
rdDone : out std_logic; -- read done and data is available
|
Line 116... |
Line 121... |
clk2x : out std_logic; -- double-speed host clock
|
clk2x : out std_logic; -- double-speed host clock
|
lock : out std_logic; -- true when host clock is locked to master clock
|
lock : out std_logic; -- true when host clock is locked to master clock
|
rst : in std_logic; -- reset
|
rst : in std_logic; -- reset
|
rd : in std_logic; -- initiate read operation
|
rd : in std_logic; -- initiate read operation
|
wr : in std_logic; -- initiate write operation
|
wr : in std_logic; -- initiate write operation
|
|
uds : in std_logic; -- upper data strobe
|
|
lds : in std_logic; -- lower data strobe
|
earlyOpBegun : out std_logic; -- read/write/self-refresh op begun (async)
|
earlyOpBegun : out std_logic; -- read/write/self-refresh op begun (async)
|
opBegun : out std_logic; -- read/write/self-refresh op begun (clocked)
|
opBegun : out std_logic; -- read/write/self-refresh op begun (clocked)
|
rdPending : out std_logic; -- read operation(s) are still in the pipeline
|
rdPending : out std_logic; -- read operation(s) are still in the pipeline
|
done : out std_logic; -- read or write operation is done
|
done : out std_logic; -- read or write operation is done
|
rdDone : out std_logic; -- read done and data is available
|
rdDone : out std_logic; -- read done and data is available
|
Line 153... |
Line 160... |
-- Otherwise the DLLs cannot be used so the SDRAM controller and external SDRAM clock on opposite edges
|
-- Otherwise the DLLs cannot be used so the SDRAM controller and external SDRAM clock on opposite edges
|
-- to try and mitigate the clock skew between the internal FPGA logic and the external SDRAM.
|
-- to try and mitigate the clock skew between the internal FPGA logic and the external SDRAM.
|
constant MIN_LOCK_FREQ : real := 25_000.0;
|
constant MIN_LOCK_FREQ : real := 25_000.0;
|
constant IN_PHASE : boolean := real(FREQ)/CLK_DIV >= MIN_LOCK_FREQ;
|
constant IN_PHASE : boolean := real(FREQ)/CLK_DIV >= MIN_LOCK_FREQ;
|
-- Calculate the frequency of the clock for the SDRAM.
|
-- Calculate the frequency of the clock for the SDRAM.
|
constant SDRAM_FREQ : natural := int_select(IN_PHASE, (FREQ*integer(2.0*CLK_DIV))/2, FREQ);
|
-- constant SDRAM_FREQ : natural := int_select(IN_PHASE, (FREQ*integer(2.0*CLK_DIV))/2, FREQ);
|
|
constant SDRAM_FREQ : natural := int_select(IN_PHASE, (FREQ*2)/integer(2.0*CLK_DIV), FREQ);
|
-- Compute the CLKDV_DIVIDE generic paramter for the DLL modules. It defaults to 2 when CLK_DIV=1
|
-- Compute the CLKDV_DIVIDE generic paramter for the DLL modules. It defaults to 2 when CLK_DIV=1
|
-- because the DLL does not support a divisor of 1 on the CLKDV output. We use the CLK0 output
|
-- because the DLL does not support a divisor of 1 on the CLKDV output. We use the CLK0 output
|
-- when CLK_DIV=1 so we don't care what is output on thr CLK_DIV output of the DLL.
|
-- when CLK_DIV=1 so we don't care what is output on thr CLK_DIV output of the DLL.
|
constant CLKDV_DIVIDE : real := real_select(CLK_DIV = 1.0, 2.0, CLK_DIV);
|
constant CLKDV_DIVIDE : real := real_select(CLK_DIV = 1.0, 2.0, CLK_DIV);
|
|
|
Line 179... |
Line 187... |
-----------------------------------------------------------
|
-----------------------------------------------------------
|
-- setup the DLLs for clock generation
|
-- setup the DLLs for clock generation
|
-----------------------------------------------------------
|
-----------------------------------------------------------
|
|
|
-- master clock must come from a dedicated clock pin
|
-- master clock must come from a dedicated clock pin
|
clkin : IBUFG port map (I => clk, O => int_clkin);
|
clkin_buf : BUFG port map (I => clk, O => int_clkin);
|
|
|
-- The external DLL is driven from the same source as the internal DLL
|
-- The external DLL is driven from the same source as the internal DLL
|
-- if the clock divisor is 1. If CLK_DIV is greater than 1, then the external DLL
|
-- if the clock divisor is 1. If CLK_DIV is greater than 1, then the external DLL
|
-- is driven by the divided clock from the internal DLL. Otherwise, the SDRAM will be
|
-- is driven by the divided clock from the internal DLL. Otherwise, the SDRAM will be
|
-- clocked on the opposite edge if the internal and external logic are not in-phase.
|
-- clocked on the opposite edge if the internal and external logic are not in-phase.
|
Line 233... |
Line 241... |
A2 => '1',
|
A2 => '1',
|
A3 => '1',
|
A3 => '1',
|
D => int_lock,
|
D => int_lock,
|
Q => dllext_rst_n
|
Q => dllext_rst_n
|
);
|
);
|
dllext_rst <= not dllext_rst when CLK_DIV/=1.0 else ZERO;
|
-- Error ???
|
|
-- dllext_rst <= not dllext_rst when CLK_DIV/=1.0 else ZERO;
|
|
dllext_rst <= not dllext_rst_n when CLK_DIV/=1.0 else ZERO;
|
|
|
-- generate an external SDRAM clock sync'ed to the master clock
|
-- generate an external SDRAM clock sync'ed to the master clock
|
sclkfb_buf : IBUFG port map(I => sclkfb, O => sclkfb_b); -- SDRAM clock with PCB delays
|
sclkfb_buf : IBUFG port map(I => sclkfb, O => sclkfb_b); -- SDRAM clock with PCB delays
|
-- sclkfb_buf : BUFGMUX port map(I => sclkfb, O => sclkfb_b); -- SDRAM clock with PCB delays
|
|
dllext : CLKDLL port map(
|
dllext : CLKDLL port map(
|
CLKIN => ext_clkin, -- this is either the master clock or the divided clock from the internal DLL
|
CLKIN => ext_clkin, -- this is either the master clock or the divided clock from the internal DLL
|
CLKFB => sclkfb_b,
|
CLKFB => sclkfb_b,
|
CLK0 => ext_clk1x,
|
CLK0 => ext_clk1x,
|
RST => dllext_rst,
|
RST => dllext_rst,
|
Line 254... |
Line 264... |
);
|
);
|
|
|
end generate;
|
end generate;
|
|
|
-- The buffered clock is just a buffered version of the master clock.
|
-- The buffered clock is just a buffered version of the master clock.
|
bufclk <= int_clkin;
|
bufclk_bufg : BUFG port map (I => int_clkin, O => bufclk);
|
-- The host-side clock comes from the CLK0 output of the internal DLL if the clock divisor is 1.
|
-- The host-side clock comes from the CLK0 output of the internal DLL if the clock divisor is 1.
|
-- Otherwise it comes from the CLKDV output if the clock divisor is greater than 1.
|
-- Otherwise it comes from the CLKDV output if the clock divisor is greater than 1.
|
-- Otherwise it is just a copy of the master clock if the DLLs aren't being used.
|
-- Otherwise it is just a copy of the master clock if the DLLs aren't being used.
|
clk_i <= int_clk1x_b when (IN_PHASE and (CLK_DIV = 1.0)) else
|
clk_i <= int_clk1x_b when (IN_PHASE and (CLK_DIV = 1.0)) else
|
int_clkdv_b when (IN_PHASE and (CLK_DIV/=1.0)) else
|
int_clkdv_b when (IN_PHASE and (CLK_DIV/=1.0)) else
|
Line 289... |
Line 299... |
clk => clk_i, -- master clock from external clock source (unbuffered)
|
clk => clk_i, -- master clock from external clock source (unbuffered)
|
lock => lock_i, -- valid synchronized clocks indicator
|
lock => lock_i, -- valid synchronized clocks indicator
|
rst => rst, -- reset
|
rst => rst, -- reset
|
rd => rd, -- host-side SDRAM read control from memory tester
|
rd => rd, -- host-side SDRAM read control from memory tester
|
wr => wr, -- host-side SDRAM write control from memory tester
|
wr => wr, -- host-side SDRAM write control from memory tester
|
|
uds => uds, -- host-side SDRAM upper data strobe
|
|
lds => lds, -- host-side SDRAM lower data strobe
|
rdPending => rdPending,
|
rdPending => rdPending,
|
opBegun => opBegun, -- SDRAM memory read/write done indicator
|
opBegun => opBegun, -- SDRAM memory read/write done indicator
|
earlyOpBegun => earlyOpBegun, -- SDRAM memory read/write done indicator
|
earlyOpBegun => earlyOpBegun, -- SDRAM memory read/write done indicator
|
rdDone => rdDone, -- SDRAM memory read/write done indicator
|
rdDone => rdDone, -- SDRAM memory read/write done indicator
|
done => done,
|
done => done,
|