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

📄 sdr_ctrl.vhd

📁 sdram controller vhdl
💻 VHD
字号:
---------------------------------------------------------------------------------------------------
--
-- Title       : SDR_CTRL
-- Design      : SDR_controller
-- Author      : Michal Krepa
-- Company     : XXX
--
---------------------------------------------------------------------------------------------------
--
-- File        : SDR_CTRL.vhd
-- Generated   : Tue Sep 16 10:07:58 2003
-- From        : interface description file
-- By          : Itf2Vhdl ver. 1.20
--
---------------------------------------------------------------------------------------------------
--
--  Description : Single data rate SDRAM controller

--  FEATURES:
--	support for read burst size of one/two/four/eight
--  write single access location
--  CAS latency = 1,2 or 3
--  editable timing parameters
--  pipelined operation	
--  supports the NOP, READ, WRITE, AUTO_REFRESH, PRECHARGE, ACTIVATE,
--  and LOAD_MR commands

--  LIMITATIONS:
--  support for 32 bits data-path width	only
--  does not support BURST_STOP command				
--  burst write is not supported
---------------------------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;


entity SDR_CTRL is	
	port(	  
		CLK : in STD_LOGIC;  
		nRST : in std_logic;
		ADDR : in std_logic_vector(20 downto 0);
		DATA_IN : in std_logic_vector(31 downto 0);
		DATA_OUT_SDR : out std_logic_vector(31 downto 0);
		nDTACK : out std_logic;
		WnR : in std_logic;
		nAS : in std_logic;
		nLBE : in std_logic_vector(3 downto 0);	
		-- sdram signals
		nCS : out STD_LOGIC;
		nRAS : out STD_LOGIC;
		nCAS : out STD_LOGIC;
		nWE : out STD_LOGIC;
		BS : out STD_LOGIC_vector(1 downto 0);
		CKE : out STD_LOGIC;
		DQM : out STD_LOGIC_VECTOR(3 downto 0);	 
		A : out STD_LOGIC_VECTOR(10 downto 0)
		);
end SDR_CTRL;

architecture SDR_CTRL of SDR_CTRL is   
	
	-- burst size	   
	-- "000" burst size of 1
	-- "001" b.s. of 2
	-- "010" b.s. of 4
	-- "011" b.s. of 8
	constant burst_size : std_logic_vector(2 downto 0) := "011";
	
	constant CLOCK_PERIOD : positive := 30; -- in ns
	-- timing constants in ns:
	constant tRC  : positive := 65;
	constant tRCD : positive := 20;
	constant tRP  : positive := 20;
	constant tREF : positive := 15000; -- for 1 row (for 4096 you need to divide number by 4096)        
	constant tRFC : positive := 65; 
	constant tWR  : positive := CLOCK_PERIOD + 7; 
	-- sdram initialization time
	-- fo eg.: if 100 us sdram initialization is needed, tSTARTUP_NOP should be 100000 [ns]
	constant tSTARTUP_NOP : positive := 100000;
	
	-- timing constants in cycles
	-- actual cycles will be one cycle longer (every) because of state transition time (1 cycle time)
	constant tRC_CYCLES  : natural := tRC  / CLOCK_PERIOD;	 -- tRC_time = tRC_CYCLES + 1
	constant tRCD_CYCLES : natural := tRCD / CLOCK_PERIOD;	 --	tRCD_time = tRCD_CYCLES + 1
	constant tRP_CYCLES  : natural := tRP  / CLOCK_PERIOD;	 -- tRP_time = tRP_CYCLES + 1
	constant tMRD_CYCLES : natural := 2; 					 -- tMRD_time = 2 tCK
	constant tREF_CYCLES : natural := tREF / CLOCK_PERIOD;	 --	tREF_time = tREF_CYCLES + 1
	constant tRFC_CYCLES : NATURAL := tRFC / CLOCK_PERIOD;	 -- tRFC_time = tRFC_CYCLES + 1
	constant tWR_CYCLES  : natural := tWR / CLOCK_PERIOD; 	 --	tWR_time = tWR_CYCLES + 1
	constant tSTARTUP_NOP_CYCLES : positive := tSTARTUP_NOP / (2*CLOCK_PERIOD);
	
	constant CAS_LATENCY : positive := 2; 
	
	-- specified to supress simulation warnings from micron sdram models
	constant hold_time: time:= 2 ns;
	
	type state_type is (
	initialize,
	active, 
	read_data,
	read,
	write,
	set_ModeRegister,
	precharge,
	auto_refresh,
	nop 
	);
	signal state : state_type;
	
	signal refresh_req      : std_logic;  -- Refresh request signals
	signal refresh_done_flg : std_logic; 
	signal refresh_timer : integer range 0 to tREF_CYCLES; 
	signal startup_timer : integer range 0 to tSTARTUP_NOP_CYCLES; 
	
	signal startup_pending : std_logic;	-- '1' - in startup sequence
	signal wait_counter : integer range 0 to 15; -- how many cycles wait until next command can be issued
	signal twice_autorefresh : std_logic; -- double autorefresh command needed in startup sequence
	signal nAS_WAITING	: std_logic; -- if read/write is waiting to be executed
	signal CAS_counter : integer range 0 to 3;
	signal execute_nop : std_logic;
	signal nLBE_s : std_logic_vector(3 downto 0);
	signal aref_enable : std_logic;	-- autorefresh enable
	
	signal bank_numb	 : std_logic_vector(1 downto 0);
	signal row_addr		 : std_logic_vector(10 downto 0);
	signal col_addr		 : std_logic_vector(7 downto 0);
	signal WnR_S		 : std_logic;   
	signal burst_counter : integer range 0 to 7;	
	
begin	
	-- Hold nAS	  
	-- nAS - active low address strobe
	ADS_DETECT: process(nRST, CLK)
	begin
		if nRST = '0' then
			nAS_WAITING <= '0';
			bank_numb <= (others => '0');  
			col_addr <= (others => '0');   
			row_addr <= (others => '0'); 
			DATA_OUT_SDR <= (others => '0'); 
			nLBE_s <= (others => '1');
		elsif rising_edge(CLK) then	 
			-- if address strobe latch address
			if nAS='0' then
				nAS_WAITING <= '1';
				bank_numb <= ADDR(20 downto 19) after hold_time;	 
				row_addr <= ADDR(18 downto 8) after hold_time;	
				col_addr <= ADDR(7 downto 0) after hold_time;
				DATA_OUT_SDR <= DATA_IN after hold_time;
				nLBE_s <= nLBE;
			elsif state = active then
				nAS_WAITING <= '0';
			end if;
		end if;
	end process;
	
	sdram_ctrl : process(CLK, nRST)
	begin		
		if nRST = '0' then
			CKE <= '0';	
			DQM <= (others => '1');	
			nCS <= '1';
			nRAS <= '1';
			nCAS <= '1'; 
			nWE <= '1';
			BS <= "00";
			A <= (others => '0');		
			state <= initialize; 
			startup_pending <= '1';	
			wait_counter <= 0;	 
			twice_autorefresh <= '1';
			nDTACK <= '1';	
			CAS_counter <= 0;  
			burst_counter <= 0;
			startup_timer <= 0;
			refresh_done_flg <= '0';
			WnR_S <= '0';  
			execute_nop <= '0';	 
			aref_enable <= '1';
		elsif rising_edge(CLK) then
			
			case state is		 
				--------------------------
				-- initialization		 
				--------------------------
				when initialize =>
				CKE <= '1';	
				nCS <= '0';
				state <= nop after hold_time;	
				
				-----------------------------
				-- MODE REGISTER SET command
				-----------------------------
				when set_ModeRegister =>
				nCS  <= '0' after hold_time;
				nRAS <= '0' after hold_time;
				nCAS <= '0' after hold_time;
				nWE  <= '0' after hold_time; 
				A <= '0'  						-- should be '0' to ensure compability with future devices
				& '1'	 					-- write burst mode: '0' - programmed burst length; '1' - single acces location
				& "00" 						-- operation mode: "00" - standard; others - reserved
				& conv_std_logic_vector(CAS_Latency,3) -- CAS Latency
				& '0'						-- Burst Mode: '0' - sequence; '1' - interleave
				& burst_size; 					-- BURST LENGTH	of 8 
				-- after MRS command issue n nop cycles where n = tMRD_CYCLES 
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;
				
				-- wait for tMRD_CYCLES before issue
				if wait_counter < tMRD_CYCLES then
					wait_counter <= wait_counter + 1; 
					execute_nop <= '1';
				else			
					-- sdram initialization complete
					wait_counter <= 0;	
					startup_pending <= '0';	
					nDTACK <= '0' after hold_time;
					state <= nop after hold_time;	
					execute_nop <= '0';
				end if;	
				
				--------------------------
				-- NOP command			 
				--------------------------
				when nop =>
				nCS <= '0' after hold_time;
				nRAS <= '1' after hold_time;
				nCAS <= '1' after hold_time;
				nWE <= '1' after hold_time;		 
				DQM <= (others => '0') after hold_time;	
				WnR_S <= WnR after hold_time;  
				
				execute_nop <= '0';	
				nDTACK <= '1' after hold_time;
				
				if startup_pending = '1' then
					if startup_timer < tSTARTUP_NOP_CYCLES then
						startup_timer <= startup_timer + 1;
						state <= initialize after hold_time;
					else
						state <= precharge after hold_time;
					end if;	 				 
				elsif refresh_req = '1' and aref_enable = '1' then
					refresh_done_flg <= '1';
					state <= auto_refresh after hold_time;	
				elsif nAS_WAITING = '1' then 
					aref_enable <= '0';
					refresh_done_flg <= '0';
					state <= active after hold_time;				
				else 
					refresh_done_flg <= '0';
				end if;
				
				--------------------------
				-- PRECHARGE command	  
				--------------------------
				when precharge =>	 
				nCS <= '0' after hold_time;
				nRAS <= '0' after hold_time;
				nCAS <= '1' after hold_time;
				nWE <= '0' after hold_time;	 
				A(10) <= '1'; -- precharge all banks  
				
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;
				
				-- if burst size 1 or 2
				if burst_size(2 downto 1) = "00" then
					nDTACK <= '1';
				end if;
				
				if wait_counter < tRP_CYCLES then
					wait_counter <= wait_counter + 1;
					execute_nop <= '1';
				else
					execute_nop <= '0';
					wait_counter <= 0;
					
					if startup_pending = '1' then 
						state <= auto_refresh after hold_time;
					else
						state <= nop after hold_time;
					end if;	
				end if;
				
				-------------------------
				-- AUTO REFRESH command
				-------------------------
				when auto_refresh =>
				nCS <= '0' after hold_time;
				nRAS <= '0' after hold_time;
				nCAS <= '0' after hold_time;
				nWE <= '1' after hold_time;	
				
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;
				
				if wait_counter < (tRFC_CYCLES-1)+conv_integer(startup_pending) then
					wait_counter <= wait_counter + 1; 
					execute_nop <= '1';
				else   
					execute_nop <= '0';
					wait_counter <= 0;
					if twice_autorefresh = '1' then
						twice_autorefresh <= '0';
					else
						if startup_pending = '1' then
							state <= set_ModeRegister after hold_time;
						else
							state <= nop after hold_time;
						end if;
					end if;
				end if;	  
				
				-------------------------
				-- ACTIVE command
				-------------------------
				when active =>
				nCS <= '0' after hold_time;
				nRAS <= '0' after hold_time;
				nCAS <= '1' after hold_time;
				nWE <= '1' after hold_time;
				A <= row_addr after hold_time;
				BS(1 downto 0) <= bank_numb after hold_time;  
				
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;
				
				if wait_counter < tRCD_CYCLES then
					wait_counter <= wait_counter + 1;
					execute_nop <= '1';
				else
					execute_nop <= '0';
					wait_counter <= 0;
					if WnR_S = '1' then
						state <= write after hold_time;	  
						nDTACK <= '0' after hold_time;
					else
						state <= read after hold_time;
					end if;	   
				end if;
				
				------------------------
				-- READ command
				------------------------ 
				when read =>
				nCS <= '0' after hold_time;
				nRAS <= '1' after hold_time;
				nCAS <= '0' after hold_time;
				nWE <= '1' after hold_time;	 
				DQM <= (others => '0') after hold_time;
				A(7 downto 0) <= col_addr after hold_time;
				A(10) <= '0';				
				
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;
				
				if CAS_counter < CAS_LATENCY then
					CAS_counter <= CAS_counter + 1;
					execute_nop <= '1';
				else	  
					if burst_size = "000" then
						state <= precharge after hold_time; 
						aref_enable <= '1';
						execute_nop <= '0';
						nDTACK <= '0' after hold_time;
					else 
						CAS_counter <= 0;	   
						execute_nop <= '0';	  
						nDTACK <= '0' after hold_time;
						state <= read_data after hold_time;
					end if;					
				end if;	  
				case burst_size is 
					
					-- burst size of 2
					when "001" =>
					wait_counter <= 5; 
					
					-- burst size of 4
					when "010" =>
					wait_counter <= 4;
					
					-- burst size of 8 or no burst
					when others =>
					wait_counter <= 0; 
				end case;
				
				------------------------
				-- reading data
				------------------------
				when read_data =>	
				
				if wait_counter = 5 then	 
					state <= precharge after hold_time;
					aref_enable <= '1';
					wait_counter <= 0;
				else
					wait_counter <= wait_counter + 1;
				end if;	   
				
				------------------------
				-- WRITE command
				------------------------
				when write =>		  
				nCS <= '0' after hold_time;
				nRAS <= '1' after hold_time;
				nCAS <= '0' after hold_time;
				nWE <= '0' after hold_time;
				DQM <= nLBE_s after hold_time;
				A(10) <= '0'; -- disable autoprecharge 
				A(9 downto 8) <= "00" after hold_time;
				A(7 downto 0) <= col_addr after hold_time;
				nDTACK <= '1' after hold_time;	  
				
				if execute_nop = '1' then
					nCS <= '0' after hold_time;
					nRAS <= '1' after hold_time;
					nCAS <= '1' after hold_time;
					nWE <= '1' after hold_time;		
				end if;	
				
				if wait_counter < tWR_CYCLES then
					wait_counter <= wait_counter + 1;
					execute_nop <= '1';
				else
					execute_nop <= '0';
					wait_counter <= 0;			
					aref_enable <= '1';
					state <= precharge after hold_time;	
				end if;
				
				when others =>
				nDTACK <= '1' after hold_time;
				state <= nop;
				nCS <= '1';
				nRAS <= '1';
				nCAS <= '1'; 
				nWE <= '1';
				BS <= (others => '0');
				CKE <= '1';
				DQM <= (others => '1');	 
				A <= (others => '0');	
			end case;
		end if;
		
	end process;
	
	-- generate refresh counts and requests
	refresh_process: process (CLK, nRST) is
	begin  
		if nRST = '0' then     
			
			refresh_timer <= 0;
			refresh_req <= '0';	 
			
		elsif rising_edge(CLK) then  
			
			if refresh_timer < tREF_CYCLES then				
				refresh_req <= '0';
				refresh_timer <= refresh_timer + 1;			
			elsif refresh_done_flg = '1' then			
				refresh_req <= '0';
				refresh_timer <= 0;			
			else			
				refresh_req <= '1';			
			end if;		
		end if;	  
		
	end process refresh_process; 
		
	
end SDR_CTRL;

⌨️ 快捷键说明

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