📄 sdramcntl.vhd
字号:
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
package sdram is
-- SDRAM controller
component sdramCntl
generic(
FREQ : natural := 50_000; -- operating frequency in KHz
IN_PHASE : boolean := true; -- SDRAM and controller work on same or opposite clock edge
PIPE_EN : boolean := false; -- if true, enable pipelined read operations
MAX_NOP : natural := 10000; -- number of NOPs before entering self-refresh
MULTIPLE_ACTIVE_ROWS : boolean := false; -- if true, allow an active row in each bank
DATA_WIDTH : natural := 32; -- host & SDRAM data width
NROWS : natural := 4096; -- number of rows in SDRAM array
NCOLS : natural := 256; -- number of columns in SDRAM array
HADDR_WIDTH : natural := 23; -- host-side address width
SADDR_WIDTH : natural := 12 -- SDRAM-side address width
);
port(
-- host side
clk : in std_logic; -- master clock
lock : in std_logic; -- true if clock is stable
rst_n : in std_logic; -- reset
rd : in std_logic; -- initiate read operation
wr : in std_logic; -- initiate write operation
earlyOpBegun : out std_logic; -- read/write/self-refresh op has begun (async)
opBegun : out std_logic; -- read/write/self-refresh op has begun (clocked)
rdPending : out std_logic; -- true if read operation(s) are still in the pipeline
done : out std_logic; -- read or write operation is done
rdDone : out std_logic; -- read operation is done and data is available
hAddr : in std_logic_vector(HADDR_WIDTH-1 downto 0); -- address from host to SDRAM
hDIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- data from host to SDRAM
hDOut : out std_logic_vector(DATA_WIDTH-1 downto 0); -- data from SDRAM to host
status : out std_logic_vector(3 downto 0); -- diagnostic status of the FSM
-- SDRAM side
cke : out std_logic; -- clock-enable to SDRAM
ce_n : out std_logic; -- chip-select to SDRAM
ras_n : out std_logic; -- SDRAM row address strobe
cas_n : out std_logic; -- SDRAM column address strobe
we_n : out std_logic; -- SDRAM write enable
ba : out std_logic_vector(1 downto 0); -- SDRAM bank address
sAddr : out std_logic_vector(SADDR_WIDTH-1 downto 0); -- SDRAM row/column address
sDIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- data from SDRAM
sDOut : out std_logic_vector(DATA_WIDTH-1 downto 0); -- data to SDRAM
sDOutEn : out std_logic; -- true if data is output to SDRAM on sDOut
dqm : out std_logic_vector(DATA_WIDTH/8-1 downto 0) -- data mask
);
end component;
end package sdram;
--------------------------------------------------------------------
-- Company : XESS Corp.
-- Engineer : Dave Vanden Bout
-- Creation Date : 05/17/2005
-- Copyright : 2005, XESS Corp
-- Tool Versions : WebPACK 6.3.03i
--
-- Description:
-- SDRAM controller
--
-- Revision:
-- 1.4.0
--
-- Additional Comments:
-- 1.4.0:
-- Added generic parameter to enable/disable independent active rows in each bank.
-- 1.3.0:
-- Modified to allow independently active rows in each bank.
-- 1.2.0:
-- Modified to allow pipelining of read/write operations.
-- 1.1.0:
-- Initial release.
--
-- License:
-- This code can be freely distributed and modified as long as
-- this header is not removed.
--------------------------------------------------------------------
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use WORK.common.all;
entity sdramCntl is
generic(
FREQ : natural := 50_000; -- operating frequency in KHz
IN_PHASE : boolean := true; -- SDRAM and controller work on same or opposite clock edge
PIPE_EN : boolean := false; -- if true, enable pipelined read operations
MAX_NOP : natural := 10000; -- number of NOPs before entering self-refresh
MULTIPLE_ACTIVE_ROWS : boolean := false; -- if true, allow an active row in each bank
DATA_WIDTH : natural := 32; -- host & SDRAM data width
NROWS : natural := 4096; -- number of rows in SDRAM array
NCOLS : natural := 256; -- number of columns in SDRAM array
HADDR_WIDTH : natural := 23; -- host-side address width
SADDR_WIDTH : natural := 12 -- SDRAM-side address width
);
port(
-- host side
clk : in std_logic; -- master clock
lock : in std_logic; -- true if clock is stable
rst_n : in std_logic; -- reset
rd : in std_logic; -- initiate read operation
wr : in std_logic; -- initiate write operation
earlyOpBegun : out std_logic; -- read/write/self-refresh op has begun (async)
opBegun : out std_logic; -- read/write/self-refresh op has begun (clocked)
rdPending : out std_logic; -- true if read operation(s) are still in the pipeline
done : out std_logic; -- read or write operation is done
rdDone : out std_logic; -- read operation is done and data is available
hAddr : in std_logic_vector(HADDR_WIDTH-1 downto 0); -- address from host to SDRAM
hDIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- data from host to SDRAM
hDOut : out std_logic_vector(DATA_WIDTH-1 downto 0); -- data from SDRAM to host
status : out std_logic_vector(3 downto 0); -- diagnostic status of the FSM
-- SDRAM side
cke : out std_logic; -- clock-enable to SDRAM
ce_n : out std_logic; -- chip-select to SDRAM
ras_n : out std_logic; -- SDRAM row address strobe
cas_n : out std_logic; -- SDRAM column address strobe
we_n : out std_logic; -- SDRAM write enable
ba : out std_logic_vector(1 downto 0); -- SDRAM bank address
sAddr : out std_logic_vector(SADDR_WIDTH-1 downto 0); -- SDRAM row/column address
sDIn : in std_logic_vector(DATA_WIDTH-1 downto 0); -- data from SDRAM
sDOut : out std_logic_vector(DATA_WIDTH-1 downto 0); -- data to SDRAM
sDOutEn : out std_logic; -- true if data is output to SDRAM on sDOut
dqm : out std_logic_vector(DATA_WIDTH/8-1 downto 0) -- data mask
);
end sdramCntl;
architecture arch of sdramCntl is
constant OUTPUT : std_logic := '1'; -- direction of dataflow w.r.t. this controller
constant INPUT : std_logic := '0';
constant NOP : std_logic := '0'; -- no operation
constant READ : std_logic := '1'; -- read operation
constant WRITE : std_logic := '1'; -- write operation
-- SDRAM timing parameters
constant Tinit : natural := 200; -- min initialization interval (us)
constant Tras : natural := 45; -- min interval between active to precharge commands (ns)
constant Trcd : natural := 20; -- min interval between active and R/W commands (ns)
constant Tref : natural := 64_000_000; -- maximum refresh interval (ns)
constant Trfc : natural := 66; -- duration of refresh operation (ns)
constant Trp : natural := 20; -- min precharge command duration (ns)
constant Twr : natural := 15; -- write recovery time (ns)
constant Txsr : natural := 75; -- exit self-refresh time (ns)
-- SDRAM timing parameters converted into clock cycles (based on FREQ)
constant NORM : natural := 1_000_000; -- normalize ns * KHz
constant INIT_CYCLES : natural := 1+((Tinit*FREQ)/1000); -- SDRAM power-on initialization interval
constant RAS_CYCLES : natural := 1+((Tras*FREQ)/NORM); -- active-to-precharge interval
constant RCD_CYCLES : natural := 1+((Trcd*FREQ)/NORM); -- active-to-R/W interval
constant REF_CYCLES : natural := 1+(((Tref/NROWS)*FREQ)/NORM); -- interval between row refreshes
constant RFC_CYCLES : natural := 1+((Trfc*FREQ)/NORM); -- refresh operation interval
constant RP_CYCLES : natural := 1+((Trp*FREQ)/NORM); -- precharge operation interval
constant WR_CYCLES : natural := 1+((Twr*FREQ)/NORM); -- write recovery time
constant XSR_CYCLES : natural := 1+((Txsr*FREQ)/NORM); -- exit self-refresh time
constant MODE_CYCLES : natural := 2; -- mode register setup time
constant CAS_CYCLES : natural := 3; -- CAS latency
constant RFSH_OPS : natural := 8; -- number of refresh operations needed to init SDRAM
-- timer registers that count down times for various SDRAM operations
signal timer_r, timer_x : natural range 0 to INIT_CYCLES; -- current SDRAM op time
signal rasTimer_r, rasTimer_x : natural range 0 to RAS_CYCLES; -- active-to-precharge time
signal wrTimer_r, wrTimer_x : natural range 0 to WR_CYCLES; -- write-to-precharge time
signal refTimer_r, refTimer_x : natural range 0 to REF_CYCLES; -- time between row refreshes
signal rfshCntr_r, rfshCntr_x : natural range 0 to NROWS; -- counts refreshes that are neede
signal nopCntr_r, nopCntr_x : natural range 0 to MAX_NOP; -- counts consecutive NOP operations
signal doSelfRfsh : std_logic; -- active when the NOP counter hits zero and self-refresh can start
-- states of the SDRAM controller state machine
type cntlState is (
INITWAIT, -- initialization - waiting for power-on initialization to complete
INITPCHG, -- initialization - initial precharge of SDRAM banks
INITSETMODE, -- initialization - set SDRAM mode
INITRFSH, -- initialization - do initial refreshes
RW, -- read/write/refresh the SDRAM
ACTIVATE, -- open a row of the SDRAM for reading/writing
REFRESHROW, -- refresh a row of the SDRAM
SELFREFRESH -- keep SDRAM in self-refresh mode with CKE low
);
signal state_r, state_x : cntlState; -- state register and next state
-- commands that are sent to the SDRAM to make it perform certain operations
-- commands use these SDRAM input pins (ce_n,ras_n,cas_n,we_n,dqm)
subtype sdramCmd is unsigned(7 downto 0);
constant NOP_CMD : sdramCmd := "01110000";
constant ACTIVE_CMD : sdramCmd := "00110000";
constant READ_CMD : sdramCmd := "01010000";
constant WRITE_CMD : sdramCmd := "01000000";
constant PCHG_CMD : sdramCmd := "00101111";
constant MODE_CMD : sdramCmd := "00001111";
constant RFSH_CMD : sdramCmd := "00011111";
-- SDRAM mode register
-- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS
subtype sdramMode is std_logic_vector(11 downto 0);
constant MODE : sdramMode := "00" & "0" & "00" & "011" & "0" & "000";
-- the host address is decomposed into these sets of SDRAM address components
constant ROW_LEN : natural := log2(NROWS); -- number of row address bits
constant COL_LEN : natural := log2(NCOLS); -- number of column address bits
signal bank : std_logic_vector(ba'range); -- bank address bits
signal row : std_logic_vector(ROW_LEN - 1 downto 0); -- row address within bank
signal col : std_logic_vector(sAddr'range); -- column address within row
-- registers that store the currently active row in each bank of the SDRAM
constant NUM_ACTIVE_ROWS : integer := int_select(MULTIPLE_ACTIVE_ROWS = false, 1, 2**ba'length);
type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range);
signal activeRow_r, activeRow_x : activeRowType;
signal activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1); -- indicates that some row in a bank is active
signal bankIndex : natural range 0 to NUM_ACTIVE_ROWS-1; -- bank address bits
signal activeBank_r, activeBank_x : std_logic_vector(ba'range); -- indicates the bank with the active row
signal doActivate : std_logic; -- indicates when a new row in a bank needs to be activated
-- there is a command bit embedded within the SDRAM column address
constant CMDBIT_POS : natural := 10; -- position of command bit
constant AUTO_PCHG_ON : std_logic := '1'; -- CMDBIT value to auto-precharge the bank
constant AUTO_PCHG_OFF : std_logic := '0'; -- CMDBIT value to disable auto-precharge
constant ONE_BANK : std_logic := '0'; -- CMDBIT value to select one bank
constant ALL_BANKS : std_logic := '1'; -- CMDBIT value to select all banks
-- status signals that indicate when certain operations are in progress
signal wrInProgress : std_logic; -- write operation in progress
signal rdInProgress : std_logic; -- read operation in progress
signal activateInProgress : std_logic; -- row activation is in progress
-- these registers track the progress of read and write operations
signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0); -- pipeline of read ops in progress
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -