OpenCores
URL https://opencores.org/ocsvn/simpcon/simpcon/trunk

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_sram32_flash.vhd] - Rev 29

Go to most recent revision | Compare with Previous | Blame | View Log

--
--	sc_sram32_flash.vhd
--
--	SimpCon compliant external memory interface
--	for 32-bit SRAM (e.g. Cyclone board)
--
--	Connection between mem_sc and the external memory bus
--
--	memory mapping
--	
--		0x000000-x7ffff	external SRAM (w mirror)	max. 512 kW (4*4 MBit)
--		0x080000-xfffff	external Flash (w mirror)	max. 512 kB (4 MBit)
--		0x100000-xfffff	external NAND flash
--
--	RAM: 32 bit word
--	ROM: 8 bit word (for flash programming)
--
--	todo:
--		
--
--	2005-11-22	first version
--	2005-12-02	added flash interface
--
 
Library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.jop_types.all;
use work.sc_pack.all;
 
entity sc_mem_if is
generic (ram_ws : integer; rom_ws : integer);
 
port (
 
	clk, reset	: in std_logic;
 
--
--	SimpCon memory interface
--
	sc_mem_out		: in sc_mem_out_type;
	sc_mem_in		: out sc_in_type;
 
-- memory interface
 
	ram_addr	: out std_logic_vector(17 downto 0);
	ram_dout	: out std_logic_vector(31 downto 0);
	ram_din		: in std_logic_vector(31 downto 0);
	ram_dout_en	: out std_logic;
	ram_ncs		: out std_logic;
	ram_noe		: out std_logic;
	ram_nwe		: out std_logic;
 
--
--	config/program flash and big nand flash interface
--
	fl_a	: out std_logic_vector(18 downto 0);
	fl_d	: inout std_logic_vector(7 downto 0);
	fl_ncs	: out std_logic;
	fl_ncsb	: out std_logic;
	fl_noe	: out std_logic;
	fl_nwe	: out std_logic;
	fl_rdy	: in std_logic
 
);
end sc_mem_if;
 
architecture rtl of sc_mem_if is
 
--
--	signals for mem interface
--
	type state_type		is (
							idl, rd1, rd2, wr1,
							fl_rd1, fl_rd2, fl_wr1, fl_wr2
						);
	signal state 		: state_type;
	signal next_state	: state_type;
 
	signal nwr_int		: std_logic;
	signal wait_state	: unsigned(3 downto 0);
	signal cnt			: unsigned(1 downto 0);
 
	signal dout_ena		: std_logic;
	signal ram_data		: std_logic_vector(31 downto 0);
	signal ram_data_ena	: std_logic;
 
	signal flash_dout	: std_logic_vector(7 downto 0);
	signal fl_dout_ena	: std_logic;
	signal flash_data	: std_logic_vector(7 downto 0);
	signal flash_data_ena	: std_logic;
	signal nand_rdy		: std_logic;
 
	signal trans_ram	: std_logic;
	signal trans_flash	: std_logic;
	-- selection for read mux
	signal ram_access	: std_logic;
	-- selection for Flash/NAND ncs
	signal sel_flash	: std_logic;
 
begin
 
	assert MEM_ADDR_SIZE>=21 report "Too less address bits";
	ram_dout_en <= dout_ena;
 
	sc_mem_in.rdy_cnt <= cnt;
 
--
--	decode ram/flash
--	The signals are only valid for the first cycle
--
process(sc_mem_out.address(20 downto 19))
begin
 
	trans_ram <= '0';
	trans_flash <= '0';
 
	case sc_mem_out.address(20 downto 19) is
		when "00" =>
			trans_ram <= '1';
		when "01" =>
			trans_flash <= '1';
		when others =>
			null;
	end case;
 
end process;
 
--
--	Register memory address, write data and read data
--
process(clk, reset)
begin
	if reset='1' then
 
		ram_addr <= (others => '0');
		ram_dout <= (others => '0');
		ram_data <= (others => '0');
		flash_dout <= (others => '0');
		fl_a <= (others => '0');
		sel_flash <= '1';			-- AMD default
		ram_access <= '1';			-- RAM default
 
	elsif rising_edge(clk) then
 
		if sc_mem_out.rd='1' or sc_mem_out.wr='1' then
			if trans_ram='1' then
				ram_access <= '1';
				ram_addr <= sc_mem_out.address(17 downto 0);
			else
				ram_access <= '0';
				fl_a <= sc_mem_out.address(18 downto 0);
				-- select flash type
				-- and keep it selected
				if trans_flash='1' then
					sel_flash <= '1';
				else
					sel_flash <= '0';
				end if;
			end if;
		end if;
		if sc_mem_out.wr='1' then
			if trans_ram='1' then
				ram_dout <= sc_mem_out.wr_data;
			else
				flash_dout <= sc_mem_out.wr_data(7 downto 0);
			end if;
		end if;
		if ram_data_ena='1' then
			ram_data <= ram_din;
		end if;
		if flash_data_ena='1' then
			-- signal NAND rdy only for NAND access
			nand_rdy <= fl_rdy and not sel_flash;
			flash_data <= fl_d;
		end if;
 
	end if;
end process;
 
--
--	MUX registered RAM and Flash data
--
process(ram_access, ram_data, flash_data, nand_rdy)
 
begin
	if (ram_access='1') then
		sc_mem_in.rd_data <= ram_data;
	else
		sc_mem_in.rd_data <= std_logic_vector(to_unsigned(0, 32-9)) & nand_rdy & flash_data;
	end if;
end process;
 
--
--	'delay' nwe 1/2 cycle -> change on falling edge
--
process(clk, reset)
 
begin
	if (reset='1') then
		ram_nwe <= '1';
	elsif falling_edge(clk) then
		ram_nwe <= nwr_int;
	end if;
 
end process;
 
 
--
--	next state logic
--
process(state, sc_mem_out, trans_ram, wait_state)
 
begin
 
	next_state <= state;
 
	case state is
 
		when idl =>
			if sc_mem_out.rd='1' then
				if trans_ram='1' then
					if ram_ws=0 then
						-- then we omit state rd1!
						next_state <= rd2;
					else
						next_state <= rd1;
					end if;
				else
					next_state <= fl_rd1;
				end if;
			elsif sc_mem_out.wr='1' then
				if trans_ram='1' then
					next_state <= wr1;
				else
					next_state <= fl_wr1;
				end if;
			end if;
 
		-- the WS state
		when rd1 =>
			if wait_state=2 then
				next_state <= rd2;
			end if;
 
		-- last read state
		when rd2 =>
			next_state <= idl;
			-- This should do to give us a pipeline
			-- level of 2 for read
			-- we don't care about a flash trans.
			-- in the pipeline!
			if sc_mem_out.rd='1' then
				if ram_ws=0 then
					-- then we omit state rd1!
					next_state <= rd2;
				else
					next_state <= rd1;
				end if;
			elsif sc_mem_out.wr='1' then
				next_state <= wr1;
			end if;
 
		-- the WS state
		when wr1 =>
-- TODO: check what happens on ram_ws=0
-- TODO: do we need a write pipelining?
--	not at the moment, but parhaps later when
--	we write the stack content to main memory
			if wait_state=1 then
				next_state <= idl;
			end if;
 
		when fl_rd1 =>
			if wait_state=2 then
				next_state <= fl_rd2;
			end if;
 
		when fl_rd2 =>
			next_state <= idl;
			-- we do no pipelining with the Flashs
 
		when fl_wr1 =>
			if wait_state=2 then
				next_state <= fl_wr2;
			end if;
 
		when fl_wr2 =>
			next_state <= idl;
 
	end case;
 
end process;
 
--
--	state machine register
--	output register (RAM, Flash control lines)
--
process(clk, reset)
 
begin
	if (reset='1') then
		state <= idl;
		dout_ena <= '0';
		ram_ncs <= '1';
		ram_noe <= '1';
		ram_data_ena <= '0';
 
		fl_noe <= '1';
		fl_nwe <= '1';
		flash_data_ena <= '0';
		fl_dout_ena <= '0';
 
	elsif rising_edge(clk) then
 
		state <= next_state;
		dout_ena <= '0';
		ram_ncs <= '1';
		ram_noe <= '1';
		ram_data_ena <= '0';
 
		fl_noe <= '1';
		fl_nwe <= '1';
		flash_data_ena <= '0';
		fl_dout_ena <= '0';
 
		case next_state is
 
			when idl =>
 
			-- the wait state
			when rd1 =>
				ram_ncs <= '0';
				ram_noe <= '0';
 
			-- last read state
			when rd2 =>
				ram_ncs <= '0';
				ram_noe <= '0';
				ram_data_ena <= '1';
 
 
			-- the WS state
			when wr1 =>
				ram_ncs <= '0';
				dout_ena <= '1';
 
			when fl_rd1 =>
				fl_noe <= '0';
 
			when fl_rd2 =>
				fl_noe <= '0';
				flash_data_ena <= '1';
 
			when fl_wr1 =>
				fl_nwe <= '0';
				fl_dout_ena <= '1';
 
			when fl_wr2 =>
				fl_dout_ena <= '1';
 
		end case;
 
	end if;
end process;
 
--
--	nwr combinatorial processing
--	for the negativ edge
--
process(next_state, state)
begin
 
	nwr_int <= '1';
	if next_state=wr1 then
		nwr_int <= '0';
	end if;
 
end process;
 
--
-- wait_state processing
-- cs delay, dout enable
--
process(clk, reset)
begin
	if (reset='1') then
		wait_state <= (others => '1');
		cnt <= "00";
	elsif rising_edge(clk) then
 
		wait_state <= wait_state-1;
 
		cnt <= "11";
		if next_state=idl then
			cnt <= "00";
		-- if wait_state<4 then
		elsif wait_state(3 downto 2)="00" then
			cnt <= wait_state(1 downto 0)-1;
		end if;
 
		if sc_mem_out.rd='1' or sc_mem_out.wr='1' then
			if trans_ram='1' then
				wait_state <= to_unsigned(ram_ws+1, 4);
				if ram_ws<3 then
					cnt <= to_unsigned(ram_ws+1, 2);
				else
					cnt <= "11";
				end if;
			else
				wait_state <= to_unsigned(rom_ws+1, 4);
				cnt <= "11";
			end if;
		end if;
 
	end if;
end process;
 
--
--	Flash signals
--
 
--
--	leave last ncs. Only toggle between two flashs.
--
	fl_ncs <= not sel_flash;	-- Flash ncs
	fl_ncsb <= sel_flash;		-- NAND ncs
 
--
--	tristate output
--
process(fl_dout_ena, flash_dout)
 
begin
	if (fl_dout_ena='1') then
		fl_d <= flash_dout(7 downto 0);
	else
		fl_d <= (others => 'Z');
	end if;
end process;
 
end rtl;
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.