Index: mist/sdram_statemachine.vhdl
===================================================================
--- mist/sdram_statemachine.vhdl	(revision 30)
+++ mist/sdram_statemachine.vhdl	(nonexistent)
@@ -1,541 +0,0 @@
----------------------------------------------------------------------------
--- (c) 2013 mark watson
--- I am happy for anyone to use this for non-commercial use.
--- If my vhdl files are used commercially or otherwise sold,
--- please contact me for explicit permission at scrameta (gmail).
--- This applies for source and binary form and derived works.
----------------------------------------------------------------------------
-LIBRARY ieee;
-USE ieee.std_logic_1164.all;
-use ieee.numeric_std.all;
-
-ENTITY sdram_statemachine IS
-generic
-(
-	ADDRESS_WIDTH : natural := 22;
-	ROW_WIDTH : natural := 12;
-	AP_BIT : natural := 10;
-	COLUMN_WIDTH : natural := 8
-);
-PORT 
-( 
-	CLK_SYSTEM : IN STD_LOGIC;
-	CLK_SDRAM : IN STD_LOGIC; -- this is a exact multiple of system clock
-	RESET_N : in STD_LOGIC;
-	
-	-- interface as though SRAM - this module can take care of caching/write combining etc etc. For first cut... nothing. TODO: What extra info would help me here?
-	DATA_IN : in std_logic_vector(31 downto 0);
-	ADDRESS_IN : in std_logic_vector(ADDRESS_WIDTH downto 0); -- 1 extra bit for byte alignment
-	READ_EN : in std_logic; -- if no reads pending may be a good time to do a refresh
-	WRITE_EN : in std_logic;
-	REQUEST : in std_logic; -- set true to request
-	BYTE_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0111, if 1=1011. Data fields valid:7 downto 0.
-	WORD_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0011, if 1=1001. Data fields valid:15 downto 0.
-	LONGWORD_ACCESS : in std_logic; -- a(0) ignored. lqdm/udqm mask is 0000
-	REFRESH : in std_logic;
-
-	COMPLETE : out std_logic;
-	DATA_OUT : out std_logic_vector(31 downto 0);
-
-	-- sdram itself
-	SDRAM_ADDR : out std_logic_vector(ROW_WIDTH-1 downto 0);
-	SDRAM_DQ : inout std_logic_vector(15 downto 0);
-	SDRAM_BA0 : out std_logic;
-	SDRAM_BA1 : out std_logic;
-	
-	SDRAM_CKE : out std_logic;
-	SDRAM_CS_N : out std_logic;
-	SDRAM_RAS_N : out std_logic;
-	SDRAM_CAS_N : out std_logic;
-	SDRAM_WE_N : out std_logic;
-	
-	SDRAM_ldqm : out std_logic; -- low enable, high disable - for byte addressing - NB, cas latency applies to reads
-	SDRAM_udqm : out std_logic;
-	
-	reset_client_n : out std_logic
-);
-END sdram_statemachine;
-
-ARCHITECTURE vhdl OF sdram_statemachine IS
-	function repeat(N: natural; B: std_logic) 
-	return std_logic_vector
-	is
-	variable result: std_logic_vector(1 to N);
-	begin
-	for i in 1 to N loop
-	result(i) := B;
-	end loop;
-	return result;
-	end;
-
-	-- bits are: CS_n, RAS_n, CAS_n,WE_n
-	constant sdram_command_inhibit                  : std_logic_vector(3 downto 0) := "1000";
-	constant sdram_command_no_operation             : std_logic_vector(3 downto 0) := "0111";
-	constant sdram_command_device_burst_stop        : std_logic_vector(3 downto 0) := "0110";
-	constant sdram_command_read                     : std_logic_vector(3 downto 0) := "0101";
-	constant sdram_command_write                    : std_logic_vector(3 downto 0) := "0100";
-	constant sdram_command_bank_activate            : std_logic_vector(3 downto 0) := "0011"; -- activate copies cells to buffer for reading/writing
-	constant sdram_command_precharge                : std_logic_vector(3 downto 0) := "0010"; -- precharge copies cells from buffer back to dram
-	constant sdram_command_mode_register            : std_logic_vector(3 downto 0) := "0000"; -- e.g. burst length etc
-	constant sdram_command_refresh                  : std_logic_vector(3 downto 0) := "0001"; -- must be in idle state - call 4096 times in 64ms
-	
-	signal command_next : std_logic_vector(3 downto 0);
-	
---	constant bank_state_idle                 : std_logic_vector(3 downto 0) := "0000";
---	constant bank_state_row_active           : std_logic_vector(3 downto 0) := "0001";
---	constant bank_state_read                 : std_logic_vector(3 downto 0) := "0010";
---	constant bank_state_write                : std_logic_vector(3 downto 0) := "0011";
---	constant bank_state_read_pre             : std_logic_vector(3 downto 0) := "0100";
---	constant bank_state_write_pre            : std_logic_vector(3 downto 0) := "0101";
---	constant bank_state_precharging          : std_logic_vector(3 downto 0) := "0111";
---	constant bank_state_row_activating       : std_logic_vector(3 downto 0) := "1000";
---	constant bank_state_write_recovering     : std_logic_vector(3 downto 0) := "1001";
---	constant bank_state_write_recovering_pre : std_logic_vector(3 downto 0) := "1010";
---	constant bank_state_refresh              : std_logic_vector(3 downto 0) := "1011";
---	constant bank_state_mode_access          : std_logic_vector(3 downto 0) := "1100"; 
---	constant bank_state_init                 : std_logic_vector(3 downto 0) := "1101"; 
--- Banks each have their own state, but since read/write lines are shared they are not truly independent
--- Also for auto-refresh all banks must be in idle state
-
-	constant sdram_state_powerup        : std_logic_vector(2 downto 0) := "000"; -- requires standard init
-	constant sdram_state_init           : std_logic_vector(2 downto 0) := "001"; -- requires standard init
-	constant sdram_state_idle           : std_logic_vector(2 downto 0) := "010"; -- ready to start a new request
-	constant sdram_state_refresh        : std_logic_vector(2 downto 0) := "011"; -- processing a refresh
-	constant sdram_state_read           : std_logic_vector(2 downto 0) := "100"; -- processing a read request
-	constant sdram_state_write          : std_logic_vector(2 downto 0) := "101"; -- processing a write request
-	constant sdram_state_init_precharge : std_logic_vector(2 downto 0) := "110";
-	
-	signal sdram_state_next : std_logic_vector(2 downto 0);
-	signal sdram_state_reg : std_logic_vector(2 downto 0);
-	
-	signal delay_next : std_logic_vector(13 downto 0);
-	signal delay_reg : std_logic_vector(13 downto 0);
-	
-	signal cycles_since_refresh_next : std_logic_vector(10 downto 0);
-	signal cycles_since_refresh_reg : std_logic_vector(10 downto 0); -- we expect a refresh about every 2000 cycles (approx 8ns each) - if this overflows we store the pending refresh below
-	
-	signal refresh_pending_next : std_logic_vector(11 downto 0);
-	signal refresh_pending_reg : std_logic_vector(11 downto 0); -- valid to do all 4096 once per 64ms
-	
-	signal suggest_refresh : std_logic; -- i.e. do we have any pending?
-	signal force_refresh : std_logic; -- i.e. do we NEED to refresh - up to 64ms...
-	signal require_refresh : std_logic; -- i.e. we NEED to refresh or we have some pending and the client says it is a good time	
-	signal refreshing_now : std_logic;
-	
-	signal idle_priority : std_logic_vector(3 downto 0);
-
-	signal data_out_next : std_logic_vector(31 downto 0);
-	signal data_out_reg : std_logic_vector(31 downto 0);
-	
-	signal reply_next : std_logic;
-	signal reply_reg : std_logic;
-	
-	-- track the active bank
-	-- Since we're often processing the same 512 bytes can keep the bank active and just read/write within it?
-	-- CAS,NOP,NOP,DATA
-	-- Perhaps if we're smart this can be access in one system clk cycle (4x slower than our one)
-	--signal bank_row_next : array( downto 0) of std_logic_vector(ROW_WIDTH-1 downto 0);
-	--signal bank_row_reg : array( downto 0) of std_logic_vector(ROW_WIDTH-1 downto 0);
-	
-	-- capture inputs
-	signal DATA_IN_snext      : std_logic_vector(31 downto 0);
-	signal DATA_IN_sreg       : std_logic_vector(31 downto 0);
-	signal ADDRESS_IN_snext   : std_logic_vector(ADDRESS_WIDTH-1 downto 0);
-	signal ADDRESS_IN_sreg    : std_logic_vector(ADDRESS_WIDTH-1 downto 0);
-	signal READ_EN_snext      : std_logic; -- if no reads pending may be a good time to do a refresh
-	signal READ_EN_sreg       : std_logic; -- if no reads pending may be a good time to do a refresh
-	signal WRITE_EN_snext     : std_logic;
-	signal WRITE_EN_sreg      : std_logic;	
-	signal dqm_mask_snext     : std_logic_vector(3 downto 0);
-	signal dqm_mask_sreg      : std_logic_vector(3 downto 0);
-	signal request_snext      : std_logic;
-	signal request_sreg       : std_logic;
-	signal refresh_snext      : std_logic;
-	signal refresh_sreg       : std_logic;
-	
-	-- slow clock output regs
-	signal DATA_OUT_snext     : std_logic_vector(31 downto 0);
-	signal DATA_OUT_sreg      : std_logic_vector(31 downto 0);
-	
-	signal reply_snext : std_logic;
-	signal reply_sreg  : std_logic;
-	
-	-- sdram output registers 
-	signal addr_next : std_logic_vector(ROW_WIDTH-1 downto 0);
-	signal dq_out_next : std_logic_vector(15 downto 0);
-	signal dq_output_next : std_logic;
-	signal dq_in_next  : std_logic_vector(15 downto 0);	
-	signal ba_next : std_logic_vector(1 downto 0);
-	signal cs_n_next : std_logic;
-	signal ras_n_next : std_logic;
-	signal cas_n_next : std_logic;
-	signal we_n_next : std_logic;
-	signal ldqm_next : std_logic;
-	signal udqm_next : std_logic;
-	signal cke_next : std_logic;
-	
-	signal addr_reg : std_logic_vector(ROW_WIDTH-1 downto 0);
-	signal dq_out_reg : std_logic_vector(15 downto 0);
-	signal dq_output_reg : std_logic;
-	signal ba_reg : std_logic_vector(1 downto 0);
-	signal cs_n_reg : std_logic;
-	signal ras_n_reg : std_logic;
-	signal cas_n_reg : std_logic;
-	signal we_n_reg : std_logic;
-	signal ldqm_reg : std_logic;
-	signal udqm_reg : std_logic;
-	signal cke_reg : std_logic;
-	
-	signal sdram_request_reg : std_logic;
-	signal sdram_request_next : std_logic;
-	
-	signal reset_client_n_reg : std_logic;
-	signal reset_client_n_next : std_logic;
-	
-BEGIN
-	-- register
-	process(CLK_SDRAM,reset_n)
-	begin
-		if (reset_N = '0') then
-			sdram_state_reg <= sdram_state_init;
-			delay_reg <= (others=>'0');
-			refresh_pending_reg <= (others=>'0');
-			cycles_since_refresh_reg <= (others=>'0');
-			data_out_reg <= (others=>'0');
-			reply_reg <= '0';
-			
-			addr_reg <= (others => '0');
-			dq_out_reg <= (others=> '0');
-			dq_output_reg <= '0';
-			ba_reg <= (others=>'0');
-			cs_n_reg <= '0';
-			ras_n_reg <= '0';
-			cas_n_reg <= '0';
-			we_n_reg <= '0';
-			ldqm_reg <= '0';
-			udqm_reg <= '0';
-			cke_reg <= '0';
-			
-			--bank_row_reg <= (others=>(others=>'0'));
-		elsif (CLK_SDRAM'event and CLK_SDRAM='1') then
-			sdram_state_reg <= sdram_state_next;
-			delay_reg <= delay_next;
-			refresh_pending_reg <= refresh_pending_next;
-			cycles_since_refresh_reg <= cycles_since_refresh_next;
-			data_out_reg <= data_out_next;
-			reply_reg <= reply_next;
-			
-			addr_reg <= addr_next;
-			dq_out_reg <= dq_out_next;
-			dq_output_reg <= dq_output_next;
-			ba_reg <= ba_next;
-			cs_n_reg <= cs_n_next;
-			ras_n_reg <= ras_n_next;
-			cas_n_reg <= cas_n_next;
-			we_n_reg <= we_n_next;
-			ldqm_reg <=ldqm_next;
-			udqm_reg <= udqm_next;
-			cke_reg <= cke_next;
-			
-			--bank_row_reg <= bank_row_next;
-		end if;
-	end process;
-
-	-- register request	
-	process(CLK_SYSTEM,reset_n)
-	begin
-		if (reset_N = '0') then
-			data_in_sreg <= (others=>'0');
-			address_in_sreg <= (others=>'0');
-			read_en_sreg <= '0';
-			write_en_sreg <= '0';
-			request_sreg <= '0';
-			dqm_mask_sreg <= (others=>'1');
-			refresh_sreg <= '0';
-			
-			data_out_sreg <= (others=>'0');
-			reply_sreg <= '0';
-			
-			sdram_request_reg <= '0';
-			
-			reset_client_n_reg <= '0';
-			
-		elsif (CLK_SYSTEM'event and CLK_SYSTEM='1') then
-			data_in_sreg <= data_in_snext;
-			address_in_sreg <= address_in_snext;
-			read_en_sreg <= read_en_snext;
-			write_en_sreg <= write_en_snext;
-			request_sreg <= request_snext;
-			dqm_mask_sreg <= dqm_mask_snext;
-			refresh_sreg <= refresh_snext;
-			
-			data_out_sreg <= data_out_snext;
-			reply_sreg <= reply_snext;
-			
-			sdram_request_reg <= sdram_request_next;
-			
-			reset_client_n_reg <= reset_client_n_next;
-		end if;
-	end process;
-
-	-- Inputs - NB, clocked at a smaller multiple
-	process(data_in_sreg, address_in_sreg, read_en_sreg, write_en_sreg, request_sreg, dqm_mask_sreg, refresh_sreg, data_in, address_in, read_en, write_en, sdram_request_next, byte_access, word_access, longword_access, refresh)
-	begin
-		data_in_snext <= data_in_sreg;
-		address_in_snext <= address_in_sreg;
-		read_en_snext <= read_en_sreg;
-		write_en_snext <= write_en_sreg;
-		request_snext <= request_sreg;
-		dqm_mask_snext <= dqm_mask_sreg;
-		
-		refresh_snext <= refresh; -- independent of memory requests
-	
-		-- only snap inputs on new request
-		-- in theory I could keep the requests in a fifo so I can handle several without waiting - processed in order
-		if ((sdram_request_next xor request_sreg) = '1') then
-			data_in_snext <= data_in;
-			address_in_snext <= address_in(ADDRESS_WIDTH downto 1);
-			read_en_snext <= read_en;
-			write_en_snext <= write_en;
-			request_snext <= sdram_request_next;
-			
-			dqm_mask_snext(0) <= (byte_access or word_access) and address_in(0); -- masked on misaligned byte or word
-			dqm_mask_snext(1) <= (byte_access) and not(address_in(0)); -- masked on aligned byte only
-			dqm_mask_snext(2) <= byte_access or (word_access and not(address_in(0))); -- masked on aligned word or byte
-			dqm_mask_snext(3) <= not(longword_access); -- masked for everything except long word access
-		end if;
-	end process;
-	
-	-- refresh counters
-	process(cycles_since_refresh_reg, refresh_pending_reg, refresh_sreg, refreshing_now, force_refresh, suggest_refresh)
-	begin
-		cycles_since_refresh_next <= std_logic_vector(unsigned(cycles_since_refresh_reg)+1);
-		refresh_pending_next <= refresh_pending_reg;
-		suggest_refresh <= '0';
-		force_refresh <= '0';
-		
-		if (refresh_pending_reg > X"000") then -- refresh_pending updates before refresh completes
-			suggest_refresh <= '1';
-		end if;
-		
-		if (refresh_pending_reg = X"FFF") then
-			force_refresh <= '1';
-		end if;
-		
-		require_refresh <= force_refresh or (suggest_refresh and refresh_sreg);
-		
-		if (refreshing_now = '1') then
-			-- refreshing right now
-			cycles_since_refresh_next <= (others=>'0');
-			
-			-- This is one of our pending refreshes (if we have any)			
-			if (suggest_refresh = '1') then
-				refresh_pending_next <= std_logic_vector(unsigned(refresh_pending_reg) -1);
-			end if;
-		else
-			if (cycles_since_refresh_reg = "11111111111") then
-				refresh_pending_next <= std_logic_vector(unsigned(refresh_pending_reg) +1);
-				cycles_since_refresh_next <= (others=>'0');
-			end if;
-		end if;
-
-	end process;
-	
-	--
-	process(reset_client_n_reg,sdram_state_reg,delay_reg, idle_priority, data_out_reg, read_en_sreg, write_en_sreg, address_in_sreg, data_in_sreg, reply_reg, require_refresh, dq_in_next, dqm_mask_sreg, request_sreg)
-	begin
-		idle_priority <= (others=>'0');
-		refreshing_now <= '0';
-	
-		reset_client_n_next <= reset_client_n_reg;
-	
-		sdram_state_next <= sdram_state_reg;
-		
-		command_next <= sdram_command_no_operation;
-		
-		delay_next <= std_logic_vector(unsigned(delay_reg) + 1);
-		
-		data_out_next <= data_out_reg;
-		reply_next <= reply_reg;
-		
-		-- Set some default for when we're sending NOP
-		dq_out_next <= (others=>'0');
-		dq_output_next <= '0';
-		cke_next <= '1';
-		ldqm_next <= '1';
-		udqm_next <= '1';
-		ba_next <= (others=>'0');
-		addr_next <= (others=>'1');
-
-		-- TODO - use bank states!!
-		-- TODO - MUCH MORE SMART STUFF!
-		-- Lets do them once we have Hello World running...
-		case sdram_state_reg is
-		when sdram_state_powerup =>			
-			-- wait 100us (min)
-			if (delay_reg(13) = '1') then
-				sdram_state_next <= sdram_state_init_precharge;
-				delay_next <= (others=>'0');
-			end if;			
-		when sdram_state_init =>			
-			case delay_reg(5 downto 3)&delay_reg(0) is
-			when "0001" =>
-				command_next <= sdram_command_precharge;
-				addr_next(AP_BIT) <= '1'; --all banks
-			when "0010" =>
-				command_next <= sdram_command_refresh;				
-				-- cke still high, so auto refresh
-			when "0100" =>
-				command_next <= sdram_command_refresh;
-				-- cke still high, so auto refresh
-			when "1000" =>
-				command_next <= sdram_command_mode_register;
-				--addr_next(2 downto 0) <= (others=>'0'); -- burst single cycle for now
-				addr_next(2 downto 0) <= "001"; -- two cycle burst to fetch word-aligned 32-bit, misaligned 16-bit, misaligned 8-bit
-				addr_next(3) <= '0'; -- sequential
-				addr_next(6 downto 4) <= "011"; -- cas latency 3 cycles
-				addr_next(8 downto 7) <= "00"; -- standard operation
-				addr_next(9) <= '0'; -- programmed burst access - of single cycle!
-				addr_next(11 downto 10) <= "00"; -- reserved
-			when "1010" =>
-				sdram_state_next <= sdram_state_idle;
-				delay_next <= (others=>'0');
-			when others =>
-				-- nop
-			end case;
-		when sdram_state_idle =>
-			reset_client_n_next <= '1';		
-			delay_next <= (others=>'0');						
-			
-			idle_priority <= (request_sreg xor reply_reg)&require_refresh&write_en_sreg&read_en_sreg;
-			case idle_priority is -- priority encoder...
-			when "0100"|"0101"|"0110"|"0111"|"1100"|"1101"|"1110"|"1111" =>
-				sdram_state_next <= sdram_state_refresh;
-			when "1010"|"1011" =>				
-				sdram_state_next <= sdram_state_write;
-			when "1001" =>
-				sdram_state_next <= sdram_state_read;
-			when others =>
-				-- stay here
-			end case;
-		when sdram_state_read =>
-			-- TODO - if same bank we can save some time... ?
-			-- Only do precharge on switching bank?
-				
-			case delay_reg(3 downto 0) is
-			when X"0" =>
-				command_next <= sdram_command_bank_activate;
-				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
-				addr_next <= address_in_sreg(ADDRESS_WIDTH-3 downto ADDRESS_WIDTH-3-ROW_WIDTH+1);
-			when X"3" => -- after t_rcd (18ns issi, 21ns psc) i.e. 3 cycles - beware of t_ras (6 cycles before auto-precharge)
-				command_next <= sdram_command_read;
-				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
-				addr_next(COLUMN_WIDTH-1 downto 0) <= address_in_sreg(ADDRESS_WIDTH-3-ROW_WIDTH downto 0);
-				addr_next(AP_BIT) <= '1'; -- auto-precharge
-				
-			when X"4" =>  -- command actually sent now
-				ldqm_next <= dqm_mask_sreg(0);  -- for first read
-				udqm_next <= dqm_mask_sreg(1);
-			
-			when X"5" =>  -- dqm for 1st read is sent
-				ldqm_next <= dqm_mask_sreg(2); -- for 2nd read
-				udqm_next <= dqm_mask_sreg(3);				
-			when X"7" => 
-				data_out_next(7 downto 0) <= (dq_in_next(7 downto 0) and not(repeat(8,dqm_mask_sreg(0)))) or (dq_in_next(15 downto 8) and repeat(8,dqm_mask_sreg(0)));
-				data_out_next(15 downto 8) <= dq_in_next(15 downto 8);				
-			when X"8" => -- auto-precharge starts here after cas cycles (at this speed issi can do 2, psc can do 3 -> use slowest)
-				data_out_next(15 downto 8) <= (dq_in_next(7 downto 0) and repeat(8,dqm_mask_sreg(0))) or (data_out_reg(15 downto 8) and not(repeat(8,dqm_mask_sreg(0))));
-				data_out_next(31 downto 16) <= dq_in_next(15 downto 0);
-				
-				reply_next <= request_sreg;
-				sdram_state_next <= sdram_state_idle;
-				-- after 3 cycles we can do the next ACT (21 ns psc)
-				-- TODO - directly switch to next action so as not to waste a cycle
-			when others =>
-			end case;				
-		when sdram_state_write =>
-			case delay_reg(3 downto 0) is
-			when X"0" =>
-				command_next <= sdram_command_bank_activate;
-				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
-				addr_next <= address_in_sreg(ADDRESS_WIDTH-3 downto ADDRESS_WIDTH-3-ROW_WIDTH+1);
-			when X"3" => -- after t_rcd (18ns issi, 21ns psc) i.e. 3 cycles - before of t_ras (6 cycles before auto-precharge)
-				command_next <= sdram_command_write; 
-				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
-				addr_next(COLUMN_WIDTH-1 downto 0) <= address_in_sreg(ADDRESS_WIDTH-3-ROW_WIDTH downto 0);
-				addr_next(AP_BIT) <= '1'; -- auto-precharge
-				
-				dq_output_next <= '1';
-				dq_out_next(7 downto 0) <= data_in_sreg(7 downto 0);
-				dq_out_next(15 downto 8) <= (data_in_sreg(15 downto 8) and not(repeat(8,dqm_mask_sreg(0)))) or (data_in_sreg(7 downto 0) and repeat(8,dqm_mask_sreg(0)));
-				ldqm_next <= dqm_mask_sreg(0);
-				udqm_next <= dqm_mask_sreg(1);
-			when X"4" =>
-				dq_output_next <= '1';
-				dq_out_next(7 downto 0) <= (data_in_sreg(23 downto 16) and not(repeat(8,dqm_mask_sreg(0)))) or (data_in_sreg(15 downto 8) and repeat(8,dqm_mask_sreg(0)));
-				dq_out_next(15 downto 8) <= data_in_sreg(31 downto 24);
-				ldqm_next <= dqm_mask_sreg(2);
-				udqm_next <= dqm_mask_sreg(3);
-
-				reply_next <= request_sreg;				
-			when X"6" => -- after 3 cycles we can do the next ACT (21 ns psc)
-				sdram_state_next <= sdram_state_idle;		
-				-- TODO - directly switch to next action to match read
-			when others =>
-			end case;				
-		when sdram_state_refresh =>
-			case delay_reg(3 downto 0) is
-			when X"0" =>
-				command_next <= sdram_command_refresh;
-				-- cke still high, so auto refresh
-				refreshing_now <= '1';
-			when X"8" =>
-				sdram_state_next <= sdram_state_idle;
-			when others =>
-			end case;
-		when others =>
-			sdram_state_next <= sdram_state_init;			
-		end case;
-	end process;
-	
-	-- command_next directly translates to lines to send
-	-- NB command_next is send ON NEXT CLOCK - so we get a clean clk->q with no combinational logic
-	process(command_next)
-	begin
-		cs_n_next <= command_next(3);
-		ras_n_next <= command_next(2);
-		cas_n_next <= command_next(1);
-		we_n_next <= command_next(0);
-	end process;
-	
-	-- outputs to SDRAM - because timing is tight these SHOULD ALL BE DIRECT FROM REGISTERS
-	SDRAM_ADDR <= addr_reg;
-	SDRAM_DQ <= dq_out_reg when dq_output_reg='1' else (others=>'Z');
-	SDRAM_BA0 <= ba_reg(0);
-	SDRAM_BA1 <= ba_reg(1);
-	SDRAM_CS_N <= cs_n_reg;
-	SDRAM_RAS_N <= ras_n_reg;
-	SDRAM_CAS_N <= cas_n_reg;
-	SDRAM_WE_N <= we_n_reg;
-	SDRAM_ldqm <= ldqm_reg;
-	SDRAM_udqm <= udqm_reg;
-	SDRAM_CKE <= cke_reg;
-	
-	-- inputs from SDRAM
-	dq_in_next <= SDRAM_DQ;
-	
-	-- back to slower clock
-	reply_snext <= reply_reg;
-	data_out_snext <= data_out_reg;
-	
-	-- outputs to rest of system
-	--REPLY <= reply_sreg;
-	DATA_OUT <= DATA_OUT_sreg;
-
-	-- a little sdram glue - move to sdram wrapper?
-	COMPLETE <= (reply_sreg xnor sdram_request_reg) and not(request);
-	sdram_request_next <= sdram_request_reg xor request;
-	
-	reset_client_n <= reset_client_n_reg;
-	
-END vhdl;
Index: common/components/sdram_statemachine.vhdl
===================================================================
--- common/components/sdram_statemachine.vhdl	(nonexistent)
+++ common/components/sdram_statemachine.vhdl	(revision 31)
@@ -0,0 +1,541 @@
+---------------------------------------------------------------------------
+-- (c) 2013 mark watson
+-- I am happy for anyone to use this for non-commercial use.
+-- If my vhdl files are used commercially or otherwise sold,
+-- please contact me for explicit permission at scrameta (gmail).
+-- This applies for source and binary form and derived works.
+---------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+ENTITY sdram_statemachine IS
+generic
+(
+	ADDRESS_WIDTH : natural := 22;
+	ROW_WIDTH : natural := 12;
+	AP_BIT : natural := 10;
+	COLUMN_WIDTH : natural := 8
+);
+PORT 
+( 
+	CLK_SYSTEM : IN STD_LOGIC;
+	CLK_SDRAM : IN STD_LOGIC; -- this is a exact multiple of system clock
+	RESET_N : in STD_LOGIC;
+	
+	-- interface as though SRAM - this module can take care of caching/write combining etc etc. For first cut... nothing. TODO: What extra info would help me here?
+	DATA_IN : in std_logic_vector(31 downto 0);
+	ADDRESS_IN : in std_logic_vector(ADDRESS_WIDTH downto 0); -- 1 extra bit for byte alignment
+	READ_EN : in std_logic; -- if no reads pending may be a good time to do a refresh
+	WRITE_EN : in std_logic;
+	REQUEST : in std_logic; -- set true to request
+	BYTE_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0111, if 1=1011. Data fields valid:7 downto 0.
+	WORD_ACCESS : in std_logic; -- ldqm/udqm set based on a(0) - if 0=0011, if 1=1001. Data fields valid:15 downto 0.
+	LONGWORD_ACCESS : in std_logic; -- a(0) ignored. lqdm/udqm mask is 0000
+	REFRESH : in std_logic;
+
+	COMPLETE : out std_logic;
+	DATA_OUT : out std_logic_vector(31 downto 0);
+
+	-- sdram itself
+	SDRAM_ADDR : out std_logic_vector(ROW_WIDTH-1 downto 0);
+	SDRAM_DQ : inout std_logic_vector(15 downto 0);
+	SDRAM_BA0 : out std_logic;
+	SDRAM_BA1 : out std_logic;
+	
+	SDRAM_CKE : out std_logic;
+	SDRAM_CS_N : out std_logic;
+	SDRAM_RAS_N : out std_logic;
+	SDRAM_CAS_N : out std_logic;
+	SDRAM_WE_N : out std_logic;
+	
+	SDRAM_ldqm : out std_logic; -- low enable, high disable - for byte addressing - NB, cas latency applies to reads
+	SDRAM_udqm : out std_logic;
+	
+	reset_client_n : out std_logic
+);
+END sdram_statemachine;
+
+ARCHITECTURE vhdl OF sdram_statemachine IS
+	function repeat(N: natural; B: std_logic) 
+	return std_logic_vector
+	is
+	variable result: std_logic_vector(1 to N);
+	begin
+	for i in 1 to N loop
+	result(i) := B;
+	end loop;
+	return result;
+	end;
+
+	-- bits are: CS_n, RAS_n, CAS_n,WE_n
+	constant sdram_command_inhibit                  : std_logic_vector(3 downto 0) := "1000";
+	constant sdram_command_no_operation             : std_logic_vector(3 downto 0) := "0111";
+	constant sdram_command_device_burst_stop        : std_logic_vector(3 downto 0) := "0110";
+	constant sdram_command_read                     : std_logic_vector(3 downto 0) := "0101";
+	constant sdram_command_write                    : std_logic_vector(3 downto 0) := "0100";
+	constant sdram_command_bank_activate            : std_logic_vector(3 downto 0) := "0011"; -- activate copies cells to buffer for reading/writing
+	constant sdram_command_precharge                : std_logic_vector(3 downto 0) := "0010"; -- precharge copies cells from buffer back to dram
+	constant sdram_command_mode_register            : std_logic_vector(3 downto 0) := "0000"; -- e.g. burst length etc
+	constant sdram_command_refresh                  : std_logic_vector(3 downto 0) := "0001"; -- must be in idle state - call 4096 times in 64ms
+	
+	signal command_next : std_logic_vector(3 downto 0);
+	
+--	constant bank_state_idle                 : std_logic_vector(3 downto 0) := "0000";
+--	constant bank_state_row_active           : std_logic_vector(3 downto 0) := "0001";
+--	constant bank_state_read                 : std_logic_vector(3 downto 0) := "0010";
+--	constant bank_state_write                : std_logic_vector(3 downto 0) := "0011";
+--	constant bank_state_read_pre             : std_logic_vector(3 downto 0) := "0100";
+--	constant bank_state_write_pre            : std_logic_vector(3 downto 0) := "0101";
+--	constant bank_state_precharging          : std_logic_vector(3 downto 0) := "0111";
+--	constant bank_state_row_activating       : std_logic_vector(3 downto 0) := "1000";
+--	constant bank_state_write_recovering     : std_logic_vector(3 downto 0) := "1001";
+--	constant bank_state_write_recovering_pre : std_logic_vector(3 downto 0) := "1010";
+--	constant bank_state_refresh              : std_logic_vector(3 downto 0) := "1011";
+--	constant bank_state_mode_access          : std_logic_vector(3 downto 0) := "1100"; 
+--	constant bank_state_init                 : std_logic_vector(3 downto 0) := "1101"; 
+-- Banks each have their own state, but since read/write lines are shared they are not truly independent
+-- Also for auto-refresh all banks must be in idle state
+
+	constant sdram_state_powerup        : std_logic_vector(2 downto 0) := "000"; -- requires standard init
+	constant sdram_state_init           : std_logic_vector(2 downto 0) := "001"; -- requires standard init
+	constant sdram_state_idle           : std_logic_vector(2 downto 0) := "010"; -- ready to start a new request
+	constant sdram_state_refresh        : std_logic_vector(2 downto 0) := "011"; -- processing a refresh
+	constant sdram_state_read           : std_logic_vector(2 downto 0) := "100"; -- processing a read request
+	constant sdram_state_write          : std_logic_vector(2 downto 0) := "101"; -- processing a write request
+	constant sdram_state_init_precharge : std_logic_vector(2 downto 0) := "110";
+	
+	signal sdram_state_next : std_logic_vector(2 downto 0);
+	signal sdram_state_reg : std_logic_vector(2 downto 0);
+	
+	signal delay_next : std_logic_vector(13 downto 0);
+	signal delay_reg : std_logic_vector(13 downto 0);
+	
+	signal cycles_since_refresh_next : std_logic_vector(10 downto 0);
+	signal cycles_since_refresh_reg : std_logic_vector(10 downto 0); -- we expect a refresh about every 2000 cycles (approx 8ns each) - if this overflows we store the pending refresh below
+	
+	signal refresh_pending_next : std_logic_vector(11 downto 0);
+	signal refresh_pending_reg : std_logic_vector(11 downto 0); -- valid to do all 4096 once per 64ms
+	
+	signal suggest_refresh : std_logic; -- i.e. do we have any pending?
+	signal force_refresh : std_logic; -- i.e. do we NEED to refresh - up to 64ms...
+	signal require_refresh : std_logic; -- i.e. we NEED to refresh or we have some pending and the client says it is a good time	
+	signal refreshing_now : std_logic;
+	
+	signal idle_priority : std_logic_vector(3 downto 0);
+
+	signal data_out_next : std_logic_vector(31 downto 0);
+	signal data_out_reg : std_logic_vector(31 downto 0);
+	
+	signal reply_next : std_logic;
+	signal reply_reg : std_logic;
+	
+	-- track the active bank
+	-- Since we're often processing the same 512 bytes can keep the bank active and just read/write within it?
+	-- CAS,NOP,NOP,DATA
+	-- Perhaps if we're smart this can be access in one system clk cycle (4x slower than our one)
+	--signal bank_row_next : array( downto 0) of std_logic_vector(ROW_WIDTH-1 downto 0);
+	--signal bank_row_reg : array( downto 0) of std_logic_vector(ROW_WIDTH-1 downto 0);
+	
+	-- capture inputs
+	signal DATA_IN_snext      : std_logic_vector(31 downto 0);
+	signal DATA_IN_sreg       : std_logic_vector(31 downto 0);
+	signal ADDRESS_IN_snext   : std_logic_vector(ADDRESS_WIDTH-1 downto 0);
+	signal ADDRESS_IN_sreg    : std_logic_vector(ADDRESS_WIDTH-1 downto 0);
+	signal READ_EN_snext      : std_logic; -- if no reads pending may be a good time to do a refresh
+	signal READ_EN_sreg       : std_logic; -- if no reads pending may be a good time to do a refresh
+	signal WRITE_EN_snext     : std_logic;
+	signal WRITE_EN_sreg      : std_logic;	
+	signal dqm_mask_snext     : std_logic_vector(3 downto 0);
+	signal dqm_mask_sreg      : std_logic_vector(3 downto 0);
+	signal request_snext      : std_logic;
+	signal request_sreg       : std_logic;
+	signal refresh_snext      : std_logic;
+	signal refresh_sreg       : std_logic;
+	
+	-- slow clock output regs
+	signal DATA_OUT_snext     : std_logic_vector(31 downto 0);
+	signal DATA_OUT_sreg      : std_logic_vector(31 downto 0);
+	
+	signal reply_snext : std_logic;
+	signal reply_sreg  : std_logic;
+	
+	-- sdram output registers 
+	signal addr_next : std_logic_vector(ROW_WIDTH-1 downto 0);
+	signal dq_out_next : std_logic_vector(15 downto 0);
+	signal dq_output_next : std_logic;
+	signal dq_in_next  : std_logic_vector(15 downto 0);	
+	signal ba_next : std_logic_vector(1 downto 0);
+	signal cs_n_next : std_logic;
+	signal ras_n_next : std_logic;
+	signal cas_n_next : std_logic;
+	signal we_n_next : std_logic;
+	signal ldqm_next : std_logic;
+	signal udqm_next : std_logic;
+	signal cke_next : std_logic;
+	
+	signal addr_reg : std_logic_vector(ROW_WIDTH-1 downto 0);
+	signal dq_out_reg : std_logic_vector(15 downto 0);
+	signal dq_output_reg : std_logic;
+	signal ba_reg : std_logic_vector(1 downto 0);
+	signal cs_n_reg : std_logic;
+	signal ras_n_reg : std_logic;
+	signal cas_n_reg : std_logic;
+	signal we_n_reg : std_logic;
+	signal ldqm_reg : std_logic;
+	signal udqm_reg : std_logic;
+	signal cke_reg : std_logic;
+	
+	signal sdram_request_reg : std_logic;
+	signal sdram_request_next : std_logic;
+	
+	signal reset_client_n_reg : std_logic;
+	signal reset_client_n_next : std_logic;
+	
+BEGIN
+	-- register
+	process(CLK_SDRAM,reset_n)
+	begin
+		if (reset_N = '0') then
+			sdram_state_reg <= sdram_state_init;
+			delay_reg <= (others=>'0');
+			refresh_pending_reg <= (others=>'0');
+			cycles_since_refresh_reg <= (others=>'0');
+			data_out_reg <= (others=>'0');
+			reply_reg <= '0';
+			
+			addr_reg <= (others => '0');
+			dq_out_reg <= (others=> '0');
+			dq_output_reg <= '0';
+			ba_reg <= (others=>'0');
+			cs_n_reg <= '0';
+			ras_n_reg <= '0';
+			cas_n_reg <= '0';
+			we_n_reg <= '0';
+			ldqm_reg <= '0';
+			udqm_reg <= '0';
+			cke_reg <= '0';
+			
+			--bank_row_reg <= (others=>(others=>'0'));
+		elsif (CLK_SDRAM'event and CLK_SDRAM='1') then
+			sdram_state_reg <= sdram_state_next;
+			delay_reg <= delay_next;
+			refresh_pending_reg <= refresh_pending_next;
+			cycles_since_refresh_reg <= cycles_since_refresh_next;
+			data_out_reg <= data_out_next;
+			reply_reg <= reply_next;
+			
+			addr_reg <= addr_next;
+			dq_out_reg <= dq_out_next;
+			dq_output_reg <= dq_output_next;
+			ba_reg <= ba_next;
+			cs_n_reg <= cs_n_next;
+			ras_n_reg <= ras_n_next;
+			cas_n_reg <= cas_n_next;
+			we_n_reg <= we_n_next;
+			ldqm_reg <=ldqm_next;
+			udqm_reg <= udqm_next;
+			cke_reg <= cke_next;
+			
+			--bank_row_reg <= bank_row_next;
+		end if;
+	end process;
+
+	-- register request	
+	process(CLK_SYSTEM,reset_n)
+	begin
+		if (reset_N = '0') then
+			data_in_sreg <= (others=>'0');
+			address_in_sreg <= (others=>'0');
+			read_en_sreg <= '0';
+			write_en_sreg <= '0';
+			request_sreg <= '0';
+			dqm_mask_sreg <= (others=>'1');
+			refresh_sreg <= '0';
+			
+			data_out_sreg <= (others=>'0');
+			reply_sreg <= '0';
+			
+			sdram_request_reg <= '0';
+			
+			reset_client_n_reg <= '0';
+			
+		elsif (CLK_SYSTEM'event and CLK_SYSTEM='1') then
+			data_in_sreg <= data_in_snext;
+			address_in_sreg <= address_in_snext;
+			read_en_sreg <= read_en_snext;
+			write_en_sreg <= write_en_snext;
+			request_sreg <= request_snext;
+			dqm_mask_sreg <= dqm_mask_snext;
+			refresh_sreg <= refresh_snext;
+			
+			data_out_sreg <= data_out_snext;
+			reply_sreg <= reply_snext;
+			
+			sdram_request_reg <= sdram_request_next;
+			
+			reset_client_n_reg <= reset_client_n_next;
+		end if;
+	end process;
+
+	-- Inputs - NB, clocked at a smaller multiple
+	process(data_in_sreg, address_in_sreg, read_en_sreg, write_en_sreg, request_sreg, dqm_mask_sreg, refresh_sreg, data_in, address_in, read_en, write_en, sdram_request_next, byte_access, word_access, longword_access, refresh)
+	begin
+		data_in_snext <= data_in_sreg;
+		address_in_snext <= address_in_sreg;
+		read_en_snext <= read_en_sreg;
+		write_en_snext <= write_en_sreg;
+		request_snext <= request_sreg;
+		dqm_mask_snext <= dqm_mask_sreg;
+		
+		refresh_snext <= refresh; -- independent of memory requests
+	
+		-- only snap inputs on new request
+		-- in theory I could keep the requests in a fifo so I can handle several without waiting - processed in order
+		if ((sdram_request_next xor request_sreg) = '1') then
+			data_in_snext <= data_in;
+			address_in_snext <= address_in(ADDRESS_WIDTH downto 1);
+			read_en_snext <= read_en;
+			write_en_snext <= write_en;
+			request_snext <= sdram_request_next;
+			
+			dqm_mask_snext(0) <= (byte_access or word_access) and address_in(0); -- masked on misaligned byte or word
+			dqm_mask_snext(1) <= (byte_access) and not(address_in(0)); -- masked on aligned byte only
+			dqm_mask_snext(2) <= byte_access or (word_access and not(address_in(0))); -- masked on aligned word or byte
+			dqm_mask_snext(3) <= not(longword_access); -- masked for everything except long word access
+		end if;
+	end process;
+	
+	-- refresh counters
+	process(cycles_since_refresh_reg, refresh_pending_reg, refresh_sreg, refreshing_now, force_refresh, suggest_refresh)
+	begin
+		cycles_since_refresh_next <= std_logic_vector(unsigned(cycles_since_refresh_reg)+1);
+		refresh_pending_next <= refresh_pending_reg;
+		suggest_refresh <= '0';
+		force_refresh <= '0';
+		
+		if (refresh_pending_reg > X"000") then -- refresh_pending updates before refresh completes
+			suggest_refresh <= '1';
+		end if;
+		
+		if (refresh_pending_reg = X"FFF") then
+			force_refresh <= '1';
+		end if;
+		
+		require_refresh <= force_refresh or (suggest_refresh and refresh_sreg);
+		
+		if (refreshing_now = '1') then
+			-- refreshing right now
+			cycles_since_refresh_next <= (others=>'0');
+			
+			-- This is one of our pending refreshes (if we have any)			
+			if (suggest_refresh = '1') then
+				refresh_pending_next <= std_logic_vector(unsigned(refresh_pending_reg) -1);
+			end if;
+		else
+			if (cycles_since_refresh_reg = "11111111111") then
+				refresh_pending_next <= std_logic_vector(unsigned(refresh_pending_reg) +1);
+				cycles_since_refresh_next <= (others=>'0');
+			end if;
+		end if;
+
+	end process;
+	
+	--
+	process(reset_client_n_reg,sdram_state_reg,delay_reg, idle_priority, data_out_reg, read_en_sreg, write_en_sreg, address_in_sreg, data_in_sreg, reply_reg, require_refresh, dq_in_next, dqm_mask_sreg, request_sreg)
+	begin
+		idle_priority <= (others=>'0');
+		refreshing_now <= '0';
+	
+		reset_client_n_next <= reset_client_n_reg;
+	
+		sdram_state_next <= sdram_state_reg;
+		
+		command_next <= sdram_command_no_operation;
+		
+		delay_next <= std_logic_vector(unsigned(delay_reg) + 1);
+		
+		data_out_next <= data_out_reg;
+		reply_next <= reply_reg;
+		
+		-- Set some default for when we're sending NOP
+		dq_out_next <= (others=>'0');
+		dq_output_next <= '0';
+		cke_next <= '1';
+		ldqm_next <= '1';
+		udqm_next <= '1';
+		ba_next <= (others=>'0');
+		addr_next <= (others=>'1');
+
+		-- TODO - use bank states!!
+		-- TODO - MUCH MORE SMART STUFF!
+		-- Lets do them once we have Hello World running...
+		case sdram_state_reg is
+		when sdram_state_powerup =>			
+			-- wait 100us (min)
+			if (delay_reg(13) = '1') then
+				sdram_state_next <= sdram_state_init_precharge;
+				delay_next <= (others=>'0');
+			end if;			
+		when sdram_state_init =>			
+			case delay_reg(5 downto 3)&delay_reg(0) is
+			when "0001" =>
+				command_next <= sdram_command_precharge;
+				addr_next(AP_BIT) <= '1'; --all banks
+			when "0010" =>
+				command_next <= sdram_command_refresh;				
+				-- cke still high, so auto refresh
+			when "0100" =>
+				command_next <= sdram_command_refresh;
+				-- cke still high, so auto refresh
+			when "1000" =>
+				command_next <= sdram_command_mode_register;
+				--addr_next(2 downto 0) <= (others=>'0'); -- burst single cycle for now
+				addr_next(2 downto 0) <= "001"; -- two cycle burst to fetch word-aligned 32-bit, misaligned 16-bit, misaligned 8-bit
+				addr_next(3) <= '0'; -- sequential
+				addr_next(6 downto 4) <= "011"; -- cas latency 3 cycles
+				addr_next(8 downto 7) <= "00"; -- standard operation
+				addr_next(9) <= '0'; -- programmed burst access - of single cycle!
+				addr_next(11 downto 10) <= "00"; -- reserved
+			when "1010" =>
+				sdram_state_next <= sdram_state_idle;
+				delay_next <= (others=>'0');
+			when others =>
+				-- nop
+			end case;
+		when sdram_state_idle =>
+			reset_client_n_next <= '1';		
+			delay_next <= (others=>'0');						
+			
+			idle_priority <= (request_sreg xor reply_reg)&require_refresh&write_en_sreg&read_en_sreg;
+			case idle_priority is -- priority encoder...
+			when "0100"|"0101"|"0110"|"0111"|"1100"|"1101"|"1110"|"1111" =>
+				sdram_state_next <= sdram_state_refresh;
+			when "1010"|"1011" =>				
+				sdram_state_next <= sdram_state_write;
+			when "1001" =>
+				sdram_state_next <= sdram_state_read;
+			when others =>
+				-- stay here
+			end case;
+		when sdram_state_read =>
+			-- TODO - if same bank we can save some time... ?
+			-- Only do precharge on switching bank?
+				
+			case delay_reg(3 downto 0) is
+			when X"0" =>
+				command_next <= sdram_command_bank_activate;
+				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
+				addr_next <= address_in_sreg(ADDRESS_WIDTH-3 downto ADDRESS_WIDTH-3-ROW_WIDTH+1);
+			when X"3" => -- after t_rcd (18ns issi, 21ns psc) i.e. 3 cycles - beware of t_ras (6 cycles before auto-precharge)
+				command_next <= sdram_command_read;
+				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
+				addr_next(COLUMN_WIDTH-1 downto 0) <= address_in_sreg(ADDRESS_WIDTH-3-ROW_WIDTH downto 0);
+				addr_next(AP_BIT) <= '1'; -- auto-precharge
+				
+			when X"4" =>  -- command actually sent now
+				ldqm_next <= dqm_mask_sreg(0);  -- for first read
+				udqm_next <= dqm_mask_sreg(1);
+			
+			when X"5" =>  -- dqm for 1st read is sent
+				ldqm_next <= dqm_mask_sreg(2); -- for 2nd read
+				udqm_next <= dqm_mask_sreg(3);				
+			when X"7" => 
+				data_out_next(7 downto 0) <= (dq_in_next(7 downto 0) and not(repeat(8,dqm_mask_sreg(0)))) or (dq_in_next(15 downto 8) and repeat(8,dqm_mask_sreg(0)));
+				data_out_next(15 downto 8) <= dq_in_next(15 downto 8);				
+			when X"8" => -- auto-precharge starts here after cas cycles (at this speed issi can do 2, psc can do 3 -> use slowest)
+				data_out_next(15 downto 8) <= (dq_in_next(7 downto 0) and repeat(8,dqm_mask_sreg(0))) or (data_out_reg(15 downto 8) and not(repeat(8,dqm_mask_sreg(0))));
+				data_out_next(31 downto 16) <= dq_in_next(15 downto 0);
+				
+				reply_next <= request_sreg;
+				sdram_state_next <= sdram_state_idle;
+				-- after 3 cycles we can do the next ACT (21 ns psc)
+				-- TODO - directly switch to next action so as not to waste a cycle
+			when others =>
+			end case;				
+		when sdram_state_write =>
+			case delay_reg(3 downto 0) is
+			when X"0" =>
+				command_next <= sdram_command_bank_activate;
+				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
+				addr_next <= address_in_sreg(ADDRESS_WIDTH-3 downto ADDRESS_WIDTH-3-ROW_WIDTH+1);
+			when X"3" => -- after t_rcd (18ns issi, 21ns psc) i.e. 3 cycles - before of t_ras (6 cycles before auto-precharge)
+				command_next <= sdram_command_write; 
+				ba_next <= address_in_sreg(ADDRESS_WIDTH-1 downto ADDRESS_WIDTH-2);
+				addr_next(COLUMN_WIDTH-1 downto 0) <= address_in_sreg(ADDRESS_WIDTH-3-ROW_WIDTH downto 0);
+				addr_next(AP_BIT) <= '1'; -- auto-precharge
+				
+				dq_output_next <= '1';
+				dq_out_next(7 downto 0) <= data_in_sreg(7 downto 0);
+				dq_out_next(15 downto 8) <= (data_in_sreg(15 downto 8) and not(repeat(8,dqm_mask_sreg(0)))) or (data_in_sreg(7 downto 0) and repeat(8,dqm_mask_sreg(0)));
+				ldqm_next <= dqm_mask_sreg(0);
+				udqm_next <= dqm_mask_sreg(1);
+			when X"4" =>
+				dq_output_next <= '1';
+				dq_out_next(7 downto 0) <= (data_in_sreg(23 downto 16) and not(repeat(8,dqm_mask_sreg(0)))) or (data_in_sreg(15 downto 8) and repeat(8,dqm_mask_sreg(0)));
+				dq_out_next(15 downto 8) <= data_in_sreg(31 downto 24);
+				ldqm_next <= dqm_mask_sreg(2);
+				udqm_next <= dqm_mask_sreg(3);
+
+				reply_next <= request_sreg;				
+			when X"6" => -- after 3 cycles we can do the next ACT (21 ns psc)
+				sdram_state_next <= sdram_state_idle;		
+				-- TODO - directly switch to next action to match read
+			when others =>
+			end case;				
+		when sdram_state_refresh =>
+			case delay_reg(3 downto 0) is
+			when X"0" =>
+				command_next <= sdram_command_refresh;
+				-- cke still high, so auto refresh
+				refreshing_now <= '1';
+			when X"8" =>
+				sdram_state_next <= sdram_state_idle;
+			when others =>
+			end case;
+		when others =>
+			sdram_state_next <= sdram_state_init;			
+		end case;
+	end process;
+	
+	-- command_next directly translates to lines to send
+	-- NB command_next is send ON NEXT CLOCK - so we get a clean clk->q with no combinational logic
+	process(command_next)
+	begin
+		cs_n_next <= command_next(3);
+		ras_n_next <= command_next(2);
+		cas_n_next <= command_next(1);
+		we_n_next <= command_next(0);
+	end process;
+	
+	-- outputs to SDRAM - because timing is tight these SHOULD ALL BE DIRECT FROM REGISTERS
+	SDRAM_ADDR <= addr_reg;
+	SDRAM_DQ <= dq_out_reg when dq_output_reg='1' else (others=>'Z');
+	SDRAM_BA0 <= ba_reg(0);
+	SDRAM_BA1 <= ba_reg(1);
+	SDRAM_CS_N <= cs_n_reg;
+	SDRAM_RAS_N <= ras_n_reg;
+	SDRAM_CAS_N <= cas_n_reg;
+	SDRAM_WE_N <= we_n_reg;
+	SDRAM_ldqm <= ldqm_reg;
+	SDRAM_udqm <= udqm_reg;
+	SDRAM_CKE <= cke_reg;
+	
+	-- inputs from SDRAM
+	dq_in_next <= SDRAM_DQ;
+	
+	-- back to slower clock
+	reply_snext <= reply_reg;
+	data_out_snext <= data_out_reg;
+	
+	-- outputs to rest of system
+	--REPLY <= reply_sreg;
+	DATA_OUT <= DATA_OUT_sreg;
+
+	-- a little sdram glue - move to sdram wrapper?
+	COMPLETE <= (reply_sreg xnor sdram_request_reg) and not(request);
+	sdram_request_next <= sdram_request_reg xor request;
+	
+	reset_client_n <= reset_client_n_reg;
+	
+END vhdl;
Index: de1/atari800core_de1.vhd
===================================================================
--- de1/atari800core_de1.vhd	(revision 30)
+++ de1/atari800core_de1.vhd	(revision 31)
@@ -90,6 +90,7 @@
 	SIGNAL CLK : STD_LOGIC;
 	SIGNAL CLK_SDRAM : STD_LOGIC;
 	SIGNAL RESET_N : STD_LOGIC;
+	signal SDRAM_RESET_N : std_logic;
 	SIGNAL PLL_LOCKED : STD_LOGIC;
 
 	-- PIA
@@ -136,6 +137,18 @@
 	SIGNAL	ROM_REQUEST :  STD_LOGIC;
 	SIGNAL	ROM_REQUEST_COMPLETE :  STD_LOGIC;
 
+	-- SDRAM
+	signal SDRAM_REQUEST : std_logic;
+	signal SDRAM_REQUEST_COMPLETE : std_logic;
+	signal SDRAM_READ_ENABLE :  STD_LOGIC;
+	signal SDRAM_WRITE_ENABLE : std_logic;
+	signal SDRAM_ADDR : STD_LOGIC_VECTOR(22 DOWNTO 0);
+	signal SDRAM_DO : STD_LOGIC_VECTOR(31 DOWNTO 0);
+	
+	signal SDRAM_REFRESH : std_logic;
+	
+	signal SYSTEM_RESET_REQUEST: std_logic;
+
 	-- pokey keyboard
 	SIGNAL KEYBOARD_SCAN : std_logic_vector(5 downto 0);
 	SIGNAL KEYBOARD_RESPONSE : std_logic_vector(1 downto 0);
@@ -173,18 +186,6 @@
 FL_RST_N <= '1';
 FL_ADDR <= (others=>'0');
 
-DRAM_BA_0 <= '1';
-DRAM_BA_1 <= '1';
-DRAM_CS_N <= '1';
-DRAM_RAS_N <= '1';
-DRAM_CAS_N <= '1';
-DRAM_WE_N <= '1';
-DRAM_LDQM <= '1';
-DRAM_UDQM <= '1';
-DRAM_CKE <= '0';
-DRAM_ADDR <= (others=>'0');
-DRAM_DQ <= (others=>'Z');
-
 SD_CLK <= '1';
 SD_CMD <= '1';
 SD_THREE <= '1';
@@ -192,6 +193,8 @@
 LEDG <= (others=>'1');
 LEDR <= (others=>'1');
 
+SYSTEM_RESET_REQUEST <= '0';
+
 -- TODO FUJI? Or Program counter or...
 hexdecoder0 : entity work.hexdecoder
 PORT MAP(CLK => CLK,
@@ -234,6 +237,42 @@
 		 DOUT => RAM_DO,
 		 SRAM_ADDR => SRAM_ADDR);
 
+sdram_adaptor : entity work.sdram_statemachine
+GENERIC MAP(ADDRESS_WIDTH => 22,
+			AP_BIT => 10,
+			COLUMN_WIDTH => 8,
+			ROW_WIDTH => 12
+			)
+PORT MAP(CLK_SYSTEM => CLK,
+		 CLK_SDRAM => CLK_SDRAM,
+		 RESET_N =>  RESET_N and not(SYSTEM_RESET_REQUEST),
+		 READ_EN => SDRAM_READ_ENABLE,
+		 WRITE_EN => SDRAM_WRITE_ENABLE,
+		 REQUEST => SDRAM_REQUEST,
+		 BYTE_ACCESS => PBI_WIDTH_8BIT_ACCESS,
+		 WORD_ACCESS => PBI_WIDTH_16BIT_ACCESS,
+		 LONGWORD_ACCESS => PBI_WIDTH_32BIT_ACCESS,
+		 REFRESH => SDRAM_REFRESH,
+		 ADDRESS_IN => SDRAM_ADDR,
+		 DATA_IN => PBI_WRITE_DATA(31 downto 0),
+		 SDRAM_DQ => DRAM_DQ,
+		 COMPLETE => SDRAM_REQUEST_COMPLETE,
+		 SDRAM_BA0 => DRAM_BA_0,
+		 SDRAM_BA1 => DRAM_BA_1,
+		 SDRAM_CKE => DRAM_CKE,
+		 SDRAM_CS_N => DRAM_CS_N,
+		 SDRAM_RAS_N => DRAM_RAS_N,
+		 SDRAM_CAS_N => DRAM_CAS_N,
+		 SDRAM_WE_N => DRAM_WE_N,
+		 SDRAM_ldqm => DRAM_LDQM,
+		 SDRAM_udqm => DRAM_UDQM,
+		 DATA_OUT => SDRAM_DO,
+		 SDRAM_ADDR => DRAM_ADDR(11 downto 0),
+		 reset_client_n => SDRAM_RESET_N
+		 );
+		 
+SDRAM_REFRESH <= '0'; -- TODO
+
 -- PIA mapping
 CA1_IN <= '1';
 CB1_IN <= '1';
@@ -255,9 +294,6 @@
 CART_RD4 <= '0';
 CART_RD5 <= '0';
 
--- Since we're not exposing PBI, expose a few key parts needed for SDRAM
---SDRAM_DI <= PBI_WRITE_DATA;
-
 -- Internal rom/ram
 internalromram1 : entity work.internalromram
 	GENERIC MAP
@@ -431,7 +467,7 @@
 	PORT MAP
 	(
 		CLK => CLK,
-		RESET_N => RESET_N,
+		RESET_N => RESET_N and SDRAM_RESET_N and not(SYSTEM_RESET_REQUEST),
 
 		VGA_VS => VGA_VS_RAW,
 		VGA_HS => VGA_HS_RAW,
@@ -491,12 +527,12 @@
 		
 		ANTIC_LIGHTPEN => ANTIC_LIGHTPEN,
 
-		SDRAM_REQUEST => open,
-		SDRAM_REQUEST_COMPLETE => '0',
-		SDRAM_READ_ENABLE => open,
-		SDRAM_WRITE_ENABLE => open,
-		SDRAM_ADDR => open,
-		SDRAM_DO => (others=>'0'),
+		SDRAM_REQUEST => SDRAM_REQUEST,
+		SDRAM_REQUEST_COMPLETE => SDRAM_REQUEST_COMPLETE,
+		SDRAM_READ_ENABLE => SDRAM_READ_ENABLE,
+		SDRAM_WRITE_ENABLE => SDRAM_WRITE_ENABLE,
+		SDRAM_ADDR => SDRAM_ADDR,
+		SDRAM_DO => SDRAM_DO,
 
 		SDRAM_REFRESH => open, -- TODO
 
@@ -520,12 +556,12 @@
 		DMA_WRITE_DATA => (others=>'0'),
 		MEMORY_READY_DMA => open,
 
-		RAM_SELECT => (others=>'0'),
+		RAM_SELECT => "110",
 		ROM_SELECT => (others=>'0'),
 		CART_EMULATION_SELECT => "0000000",
 		CART_EMULATION_ACTIVATE => '0',
 		PAL => '1',
-		USE_SDRAM => '0',
+		USE_SDRAM => '1',
 		ROM_IN_RAM => '0',
 		THROTTLE_COUNT_6502 => THROTTLE_COUNT_6502,
 		HALT => '0' 
Index: mist/atari800core.qsf
===================================================================
--- mist/atari800core.qsf	(revision 30)
+++ mist/atari800core.qsf	(revision 31)
@@ -311,7 +311,6 @@
 set_global_assignment -name VHDL_FILE data_io.vhdl
 set_global_assignment -name SDC_FILE atari800core.sdc
 set_global_assignment -name QIP_FILE mist_sector_buffer.qip
-set_global_assignment -name VHDL_FILE sdram_statemachine.vhdl
 set_global_assignment -name VHDL_FILE atari800core_mist.vhd
 set_global_assignment -name VERILOG_FILE user_io.v
 set_global_assignment -name QIP_FILE pll.qip
Index: mist/build.sh
===================================================================
--- mist/build.sh	(revision 30)
+++ mist/build.sh	(revision 31)
@@ -1,7 +1,6 @@
 rm -rf build
 mkdir build
 cp atari800core_mist.vhd build
-cp sdram_statemachine.vhdl build
 cp pll.* build
 cp atari800core.sdc build
 cp data_io.vhdl build
