⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdramcntl.vhd

📁 VHDL-vga_core(vhdl).rar FPGA上实现 VGA的IP(VHDL)
💻 VHD
📖 第 1 页 / 共 2 页
字号:
library IEEE,unisim;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use unisim.vcomponents.all;

entity sdramCntl is
	generic(
		FREQ:	natural := 25_000;			-- operating frequency in KHz
		DATA_WIDTH: natural := 16;		-- host & SDRAM data width
		NROWS: natural := 4096;				-- number of rows in SDRAM array
		NCOLS: natural := 512;				-- number of columns in SDRAM array
		HADDR_WIDTH: natural := 23;		-- host-side address width
		SADDR_WIDTH: natural := 12		-- SDRAM-side address width
	);
	port(
		clkin:	in	std_logic;				-- master clock

		-- host side
		bufclk:	out std_logic;				-- buffered master clock
		clk0:		out std_logic;				-- host clock sync'ed to master clock
		clk2x:	out std_logic;				-- double-speed host clock
		lock:		out std_logic;				-- indicate when clock circuitry is locked to master clock
		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
		sclkfb:	in	std_logic;				-- clock from SDRAM after PCB delays
		sclk:		out std_logic;				-- SDRAM clock sync'ed to master clock
		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);					-- SDRAM row/column address
		sData:	inout unsigned(DATA_WIDTH-1 downto 0);				-- SDRAM 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

	function log2(v: in natural) return natural is
		variable n: natural;
		variable logn: natural;
	begin
		n := 1;
		for i in 0 to 128 loop
			logn := i;
			exit when (n>=v);
			n := n * 2;
		end loop;
		return logn;
	end function log2;

	constant YES:	std_logic := '1';
	constant NO:	std_logic := '0';
	constant HI:	std_logic := '1';
	constant LO:	std_logic := '0';

	-- constants
	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	:= 2;				-- 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 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";

	-- clock DLL signals
	signal logic0: std_logic;
	-- signals for internal logic clock DLL
	signal bufclkin, dllint_clk0, dllint_clk2x, bufdllint_clk0, bufdllint_clk2x, lockint: std_logic;
	-- signals for external logic clock DLL
	signal bufsclkfb, dllext_clk0, lockext: std_logic;
	signal clk: std_logic;	-- clock for SDRAM controller logic
	
begin

	logic0 <= '0';
	
	-- master clock must come from a dedicated clock pin
	clkpad: IBUFG port map (I=>clkin, O=>bufclkin);
	bufclk <= bufclkin;

	-- generate an internal clock sync'ed to the master clock
	dllint: CLKDLL port map(
		CLKIN=>bufclkin, CLKFB=>bufdllint_clk0, CLK0=>dllint_clk0,
		RST=>logic0, CLK90=>open, CLK180=>open, CLK270=>open,
		CLK2X=>dllint_clk2x, CLKDV=>open, LOCKED=>lockint
	);
	-- sync'ed single and double-speed clocks for use by internal logic
	clkg: BUFG port map (I=>dllint_clk0, O=>bufdllint_clk0);
	clkg2x: BUFG port map(I=>dllint_clk2x, O=>bufdllint_clk2x);
	clk <= bufdllint_clk0;		-- SDRAM controller logic clock
	clk0 <= bufdllint_clk0;		-- clock to other FPGA logic
	clk2x <= bufdllint_clk2x;	-- doubled clock to other FPGA logic;
	lock <= lockint and lockext;	-- indicate lock status of the DLLs
	
	-- generate an external SDRAM clock sync'ed to the master clock
	clkfbpad : IBUFG  port map (I=>sclkfb, O=>bufsclkfb);  -- SDRAM clock with PCB delays
	dllext: CLKDLL port map(
		CLKIN=>bufclkin, CLKFB=>bufsclkfb, CLK0=>dllext_clk0, 
		RST=>logic0, CLK90=>open, CLK180=>open, CLK270=>open,
		CLK2X=>open, CLKDV=>open, LOCKED=>lockext
	);
	-- output the sync'ed SDRAM clock to the SDRAM
	clkextpad: OBUF port map (I=>dllext_clk0, O=>sclk);
	
	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,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
		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;
		doRfshFlag_next <= doRfshFlag_r;
		rdFlag_next <= rdFlag_r;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -