---------------------------------------------------------------------------------- -- Company: www.Circuit-Break.de -- Engineer: Jens Weiss -- -- Create Date: 21:45:37 11/22/2020 -- Design Name: -- Module Name: Memory_Controller - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Memory_Controller is Generic (ADDR_WIDTH : integer range 8 to 24 := 19; DATA_WIDTH : integer range 8 to 32 := 8; WAITSTATES : integer range 0 to 8 := 2); Port (-- clock signal clk : in std_logic; reset : in std_logic; -- Signale to SRAM Bus Driver RAM_uC_Adress : out std_logic_vector(ADDR_WIDTH-1 downto 0); RAM_uC_Data_in : in std_ulogic_vector(DATA_WIDTH-1 downto 0); RAM_uC_Data_out : out std_ulogic_vector(DATA_WIDTH-1 downto 0); RAM_FPGA_Adress : out std_logic_vector(ADDR_WIDTH-1 downto 0); RAM_FPGA_Data_in : in std_ulogic_vector(DATA_WIDTH-1 downto 0); RAM_FPGA_Data_out : out std_ulogic_vector(DATA_WIDTH-1 downto 0); RAM_Data_Select : out std_logic; RAM_Data_Direction : out std_logic; RAM_CEn : out std_logic; RAM_OEn : out std_logic; RAM_WEn : out std_logic; -- Signals to µC uC_Data_Addr : inout std_logic_vector(DATA_WIDTH-1 downto 0); uC_AD16 : in std_logic; uC_AD17 : in std_logic; uC_AD18 : in std_logic; uC_ALE0 : in std_logic; uC_ALE1 : in std_logic; uC_CEn : in std_logic; uC_OEn : in std_logic; uC_WEn : in std_logic; RAM_busy : out std_logic; RAM_error : out std_logic; RAM_done : out std_logic; -- Signals to FPGA FPGA_Addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); FPGA_Data_in : in std_ulogic_vector(DATA_WIDTH-1 downto 0); FPGA_Data_out : out std_ulogic_vector(DATA_WIDTH-1 downto 0); FPGA_CEn : in std_logic; FPGA_rw : in std_logic; FPGA_start : in std_logic ); end Memory_Controller; architecture Behavioral of Memory_Controller is --internal Signals signal internal_uC_Addr : std_logic_vector (ADDR_WIDTH - 1 downto 0); signal internal_uC_nWE : std_logic; signal internal_uC_nOE : std_logic; signal internal_RAM_error : std_logic; signal internal_RAM_done : std_logic := '1'; signal internal_FPGA_nWE : std_logic := '1'; signal internal_FPGA_nOE : std_logic := '1'; signal internal_FPGA_Data_in : std_ulogic_vector (DATA_WIDTH-1 downto 0); signal internal_FPGA_Data_out : std_ulogic_vector (DATA_WIDTH-1 downto 0); signal internal_RAM_FPGA_Data_in : std_ulogic_vector (DATA_WIDTH-1 downto 0); signal internal_RAM_FPGA_Data_out : std_ulogic_vector (DATA_WIDTH-1 downto 0); type state_type is (idle, FPGA_rd1, FPGA_rd2, FPGA_rd3, FPGA_wr1, FPGA_wr2, FPGA_wr3); signal state_reg : state_type; signal delay : integer range 0 to WAITSTATES; begin --latch SRAM Addr internal_uC_Addr(15 downto 8) <= uC_Data_Addr when (uC_ALE1 = '1') else internal_uC_Addr(15 downto 8); internal_uC_Addr(7 downto 0) <= uC_Data_Addr when (uC_ALE0 = '1') else internal_uC_Addr(7 downto 0); internal_uC_Addr(18) <= uC_AD18; internal_uC_Addr(17) <= uC_AD17; internal_uC_Addr(16) <= uC_AD16; --switch address lines between internal dual port ram and external SRAM process begin wait until (rising_edge(clk)); if (reset = '1') then internal_uC_nOE <= '1'; internal_FPGA_nOE <= '1'; internal_uC_nWE <= '1'; internal_FPGA_nWE <= '1'; RAM_Data_Direction <= '0'; RAM_Data_Select <= '0'; end if; --uC selects RAM if(uC_CEn = '0') then RAM_Data_Select <= '0'; if (uC_WEn = '0') then RAM_Data_Direction <= '1'; RAM_uC_Data_out <= to_stdulogicvector(uC_Data_Addr); internal_uC_nWE <= '0'; else internal_uC_nWE <= '1'; end if; if (uC_OEn = '0') then uC_Data_Addr <= to_stdlogicvector(RAM_uC_Data_in); RAM_Data_Direction <= '0'; internal_uC_nOE <= '0'; else uC_Data_Addr <= (others => 'Z'); internal_uC_nOE <= '1'; end if; -- else -- RAM_Data_Select <= '1'; end if; --FPGA selects RAM if(FPGA_CEn = '0') then RAM_Data_Select <= '1'; internal_FPGA_Data_in <= FPGA_Data_in; internal_RAM_FPGA_Data_in <= RAM_FPGA_Data_in; if (FPGA_start = '1') and (state_reg = idle) then if (FPGA_rw = '1') then --write Operation RAM_Data_Direction <= '1'; state_reg <= FPGA_wr1; else --read operation RAM_Data_Direction <= '0'; state_reg <= FPGA_rd1; end if; end if; -- else -- RAM_Data_Select <= '0'; end if; case state_reg is when idle => internal_RAM_done <= '1'; delay <= 0; when FPGA_wr1 => internal_FPGA_nWE <= '0'; internal_RAM_done <= '0'; internal_RAM_FPGA_Data_out <= internal_FPGA_Data_in; state_reg <= FPGA_wr2; when FPGA_wr2 => if (delay < WAITSTATES) then delay <= delay + 1; else delay <= 0; internal_FPGA_nWE <= '1'; state_reg <= FPGA_wr3; end if; when FPGA_wr3 => if (delay < WAITSTATES) then delay <= delay + 1; else delay <= 0; state_reg <= idle; end if; when FPGA_rd1 => internal_FPGA_nOE <= '0'; internal_RAM_done <= '0'; state_reg <= FPGA_rd2; when FPGA_rd2 => if (delay < WAITSTATES) then delay <= delay + 1; else delay <= 0; internal_FPGA_Data_out <= internal_RAM_FPGA_Data_in; state_reg <= FPGA_rd3; end if; when FPGA_rd3 => --if (delay < WAITSTATES) then -- delay <= delay + 1; --else -- delay <= 0; internal_FPGA_nOE <= '1'; state_reg <= idle; --end if; when others => state_reg <= idle; end case; --uC and FPGA select RAM if(uC_CEn = '0') and (FPGA_CEn = '0') then internal_RAM_error <= '1'; else internal_RAM_error <= '0'; end if; end process; --signal routing to modules RAM_uC_Adress <= internal_uC_Addr; RAM_FPGA_Adress <= FPGA_Addr; FPGA_Data_out <= internal_FPGA_Data_out; RAM_FPGA_Data_out <= internal_RAM_FPGA_Data_out; RAM_CEn <= not(uC_CEn xor FPGA_CEn); RAM_OEn <= not(internal_uC_nOE xor internal_FPGA_nOE); RAM_WEn <= not(internal_uC_nWE xor internal_FPGA_nWE); RAM_error <= internal_RAM_error; RAM_done <= internal_RAM_done; RAM_busy <= uC_CEn xor FPGA_CEn; end Behavioral;