📄 sdramcntl.vhd
字号:
--**********************************************************************************
-- Ryan Henderson
-- Oregon Institute of Technology
-- CMOS digital camera controller and frame capture device
-- May, 21 2002
--
-- sdramcntl.vhd
--
-- Written by D. Vanden Bout, Xess
--
-- Simplifies the SDRAM on the XSA-100 board to a SRAM like interface. Handles init
-- bank switching and refresh. Instantiated by ram control. Slightly modified
--**********************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use WORK.common.all;
entity sdramCntl is
generic(
FREQ: natural := 50_000; -- operating frequency in KHz
DATA_WIDTH: natural := 16; -- host & SDRAM data width
HADDR_WIDTH: natural := 23; -- host-side address width
SADDR_WIDTH: natural := 12 -- SDRAM-side address width
);
port(
clk: in std_logic; -- master clock
-- host side
rst: in std_logic; -- reset
rd: in std_logic; -- read data
wr: in std_logic; -- write data
done: out std_logic; -- read/write op done
hAddr: in unsigned(HADDR_WIDTH-1 downto 0); -- address from host
hDIn: in unsigned(DATA_WIDTH-1 downto 0); -- data from host
hDOut: out unsigned(DATA_WIDTH-1 downto 0); -- data to host
sdramCntl_state: out std_logic_vector(3 downto 0);
-- SDRAM side
cke: out std_logic; -- clock-enable to SDRAM
cs_n: out std_logic; -- chip-select to SDRAM
ras_n: out std_logic; -- command input to SDRAM
cas_n: out std_logic; -- command input to SDRAM
we_n: out std_logic; -- command input to SDRAM
ba: out unsigned(1 downto 0); -- SDRAM bank address bits
sAddr: out unsigned(SADDR_WIDTH-1 downto 0); -- row/column address
sData: inout unsigned(DATA_WIDTH-1 downto 0); -- in/out databus
dqmh: out std_logic; -- high databits I/O mask
dqml: out std_logic -- low databits I/O mask
);
end sdramCntl;
architecture arch of sdramCntl is
-- constants
constant NRows: natural := 4096; -- number of rows in SDRAM
constant NCols: natural := 512; -- number of columns in SDRAM
constant ColCmdPos: natural := 10; -- position of command bit in SDRAM column address
constant Tinit: natural := 200; -- min initialization interval (us)
constant Tras: natural := 45; -- min interval between active to precharge commands (ns)
constant Trc: natural := 67; -- min interval between active to active 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 Ccas: natural := 3; -- CAS latency (cycles)
constant Cmrd: natural := 3; -- mode register setup time (cycles)
constant RfshCycles: natural := 8; -- number of refresh cycles needed to init RAM
constant ROW_LEN: natural := log2(NRows); -- number of row address bits
constant COL_LEN: natural := log2(NCols); -- number of column address bits
constant NORM: natural := 1_000_000; -- normalize ns * KHz
constant INIT_CYCLES: natural := 1 + ((Tinit * FREQ) / 1000); -- SDRMA power-on initialization interval
constant RAS_CYCLES: natural := 1 + ((Tras * FREQ) / NORM); -- active-to-precharge interval
constant RC_CYCLES: natural := 1 + ((Trc * FREQ) / NORM); -- active-to-active 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
-- states of the SDRAM controller state machine
type cntlState is (
INITWAIT, -- initialization - waiting for power-on initialization to complete
INITPCHG, -- initialization - doing precharge of banks
INITSETMODE, -- initialization - set SDRAM mode
INITRFSH, -- initialization - do refreshes
REFRESH, -- refresh a row of the SDRAM
RW, -- wait for read/write operations to SDRAM
RDDONE, -- indicate that the SDRAM read is done
WRDONE, -- indicate that the SDRAM write is done
ACTIVATE -- open a row of the SDRAM for reading/writing
);
signal state_r, state_next: cntlState; -- state register and next state
constant AUTO_PCHG_ON: std_logic := '1'; -- set sAddr(10) to this value to auto-precharge the bank
constant AUTO_PCHG_OFF: std_logic := '0'; -- set sAddr(10) to this value to disable auto-precharge
constant ALL_BANKS: std_logic := '1'; -- set sAddr(10) to this value to select all banks
constant ACTIVE_BANK: std_logic := '0'; -- set sAddr(10) to this value to select only the active bank
signal bank: unsigned(ba'range);
signal row: unsigned(ROW_LEN - 1 downto 0);
signal col: unsigned(COL_LEN - 1 downto 0);
signal col_tmp: unsigned(sAddr'high-1 downto sAddr'low);
signal changeRow: std_logic;
signal dirOut: std_logic; -- high when driving data to SDRAM
-- registers
signal activeBank_r, activeBank_next: unsigned(bank'range); -- currently active SDRAM bank
signal activeRow_r, activeRow_next: unsigned(row'range); -- currently active SDRAM row
signal inactiveFlag_r, inactiveFlag_next: std_logic; -- 1 when all SDRAM rows are inactive
signal initFlag_r, initFlag_next: std_logic; -- 1 when initializing SDRAM
signal doRfshFlag_r, doRfshFlag_next: std_logic; -- 1 when a row refresh operation is required
signal wrFlag_r, wrFlag_next: std_logic; -- 1 when writing data to SDRAM
signal rdFlag_r, rdFlag_next: std_logic; -- 1 when reading data from SDRAM
signal rfshCntr_r, rfshCntr_next: unsigned(log2(RfshCycles+1)-1 downto 0); -- counts initialization refreshes
-- timer registers that count down times for various SDRAM operations
signal timer_r, timer_next: unsigned(log2(INIT_CYCLES+1)-1 downto 0); -- current SDRAM op time
signal rasTimer_r, rasTimer_next: unsigned(log2(RAS_CYCLES+1)-1 downto 0); -- active-to-precharge time
signal wrTimer_r, wrTimer_next: unsigned(log2(WR_CYCLES+1)-1 downto 0); -- write-to-precharge time
signal refTimer_r, refTimer_next: unsigned(log2(REF_CYCLES+1)-1 downto 0); -- time between row refreshes
-- SDRAM commands
subtype sdramCmd is unsigned(5 downto 0);
-- cmd = (cs_n,ras_n,cas_n,we_n,dqmh,dqml)
constant NOP_CMD: sdramCmd := "011100";
constant ACTIVE_CMD: sdramCmd := "001100";
constant READ_CMD: sdramCmd := "010100";
constant WRITE_CMD: sdramCmd := "010000";
constant PCHG_CMD: sdramCmd := "001011";
constant MODE_CMD: sdramCmd := "000011";
constant RFSH_CMD: sdramCmd := "000111";
signal cmd: sdramCmd;
-- SDRAM mode register
subtype sdramMode is unsigned(11 downto 0);
constant MODE: sdramMode := "00" & "0" & "00" & "011" & "0" & "000";
signal logic0 : std_logic;
begin
logic0 <= '0';
hDOut <= sData(hDOut'range); -- connect SDRAM data bus to host data bus
sData <= hDIn(sData'range) when dirOut='1' else (others=>'Z'); -- connect host data bus to SDRAM data bus
combinatorial: process(rd,wr,hAddr,hDIn,state_r,bank,row,col,changeRow,
activeBank_r,activeRow_r,initFlag_r,doRfshFlag_r,rdFlag_r,wrFlag_r,
rfshCntr_r,timer_r,rasTimer_r,wrTimer_r,refTimer_r,cmd,col_tmp,inactiveFlag_r)
begin
-- attach bits in command to SDRAM control signals
(cs_n,ras_n,cas_n,we_n,dqmh,dqml) <= cmd;
-- get bank, row, column from host address
bank <= hAddr(bank'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN);
row <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN);
col <= hAddr(COL_LEN - 1 downto 0);
-- extend column (if needed) until it is as large as the (SDRAM address bus - 1)
col_tmp <= (others=>'0'); -- set it to all zeroes
col_tmp(col'range) <= col; -- write column into the lower bits
-- default operations
cke <= YES; -- enable SDRAM clock input
cmd <= NOP_CMD; -- set SDRAM command to no-operation
if initFlag_r = YES then
cs_n <= HI;
dqml <= HI;
dqmh <= HI;
end if;
done <= NO; -- pending SDRAM operation is not done
ba <= bank; -- set SDRAM bank address bits
-- set SDRAM address to column with interspersed command bit
sAddr(ColCmdPos-1 downto 0) <= col_tmp(ColCmdPos-1 downto 0);
sAddr(sAddr'high downto ColCmdPos+1) <= col_tmp(col_tmp'high downto ColCmdPos);
sAddr(ColCmdPos) <= AUTO_PCHG_OFF; -- set command bit to disable auto-precharge
dirOut <= NO;
-- default register updates
state_next <= state_r;
inactiveFlag_next <= inactiveFlag_r;
activeBank_next <= activeBank_r;
activeRow_next <= activeRow_r;
initFlag_next <= initFlag_r;
doRfshFlag_next <= doRfshFlag_r;
rdFlag_next <= rdFlag_r;
wrFlag_next <= wrFlag_r;
rfshCntr_next <= rfshCntr_r;
-- update timers
if timer_r /= TO_UNSIGNED(0,timer_r'length) then
timer_next <= timer_r - 1;
else
timer_next <= timer_r;
end if;
if rasTimer_r /= TO_UNSIGNED(0,rasTimer_r'length) then
rasTimer_next <= rasTimer_r - 1;
else
rasTimer_next <= rasTimer_r;
end if;
if wrTimer_r /= TO_UNSIGNED(0,wrTimer_r'length) then
wrTimer_next <= wrTimer_r - 1;
else
wrTimer_next <= wrTimer_r;
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -