|
---------------------------------------------------------------------------
|
|
-- SRAM memory controller
|
|
---------------------------------------------------------------------------
|
|
-- This file is a part of "Aeon Lite" project
|
|
-- Dmitriy Schapotschkin aka ILoveSpeccy '2014
|
|
-- ilovespeccy@speccyland.net
|
|
-- Project homepage: www.speccyland.net
|
|
---------------------------------------------------------------------------
|
|
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
USE ieee.numeric_std.all;
|
|
|
|
ENTITY sram_statemachine IS
|
|
PORT (
|
|
CLK : in std_logic;
|
|
RESET_N : in std_logic;
|
|
|
|
DATA_IN : in std_logic_vector(31 downto 0);
|
|
ADDRESS_IN : in std_logic_vector(22 downto 0);
|
|
WRITE_EN : in std_logic;
|
|
REQUEST : in std_logic;
|
|
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
|
|
COMPLETE : out std_logic;
|
|
DATA_OUT : out std_logic_vector(31 downto 0);
|
|
|
|
SRAM_ADDR : out std_logic_vector(17 downto 0);
|
|
SRAM_DQ : inout std_logic_vector(15 downto 0);
|
|
SRAM_WE_N : out std_logic;
|
|
SRAM_OE_N : out std_logic;
|
|
SRAM_UB_N : out std_logic;
|
|
SRAM_LB_N : out std_logic;
|
|
SRAM_CE0_N : out std_logic;
|
|
SRAM_CE1_N : out std_logic );
|
|
END sram_statemachine;
|
|
|
|
ARCHITECTURE vhdl OF sram_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;
|
|
|
|
signal SRAM_DI : std_logic_vector(15 downto 0);
|
|
signal SRAM_DO : std_logic_vector(15 downto 0);
|
|
signal DATA_OUT_REG : std_logic_vector(31 downto 0);
|
|
signal MASK : std_logic_vector(3 downto 0);
|
|
signal ADDRESS_IN_NEXT : std_logic_vector(18 downto 0);
|
|
|
|
type STATES is (ST_IDLE, ST_READ0, ST_READ1, ST_READ2, ST_WRITE0, ST_WRITE1, ST_WRITE2);
|
|
signal STATE : STATES;
|
|
|
|
BEGIN
|
|
|
|
SRAM_DQ <= SRAM_DI;
|
|
SRAM_DO <= SRAM_DQ;
|
|
|
|
DATA_OUT <= DATA_OUT_REG;
|
|
ADDRESS_IN_NEXT <= std_logic_vector(unsigned(ADDRESS_IN(19 downto 1)) + 1);
|
|
|
|
COMPLETE <= '1' when STATE = ST_IDLE and REQUEST = '0' else '0';
|
|
|
|
process(CLK, RESET_N)
|
|
begin
|
|
if RESET_N = '0' then
|
|
SRAM_DI <= (OTHERS=>'Z');
|
|
SRAM_WE_N <= '1';
|
|
SRAM_OE_N <= '1';
|
|
SRAM_CE0_N <= '1';
|
|
SRAM_CE1_N <= '1';
|
|
SRAM_LB_N <= '1';
|
|
SRAM_UB_N <= '1';
|
|
STATE <= ST_IDLE;
|
|
else
|
|
if rising_edge(CLK) then
|
|
|
|
case STATE is
|
|
when ST_IDLE =>
|
|
|
|
SRAM_DI <= (OTHERS=>'Z');
|
|
SRAM_WE_N <= '1';
|
|
SRAM_OE_N <= '1';
|
|
SRAM_LB_N <= '1';
|
|
SRAM_UB_N <= '1';
|
|
|
|
if REQUEST = '1' then
|
|
|
|
MASK(0) <= (BYTE_ACCESS or WORD_ACCESS) and ADDRESS_IN(0); -- masked on misaligned byte or word
|
|
MASK(1) <= (BYTE_ACCESS) and not(address_in(0)); -- masked on aligned byte only
|
|
MASK(2) <= BYTE_ACCESS or (WORD_ACCESS and not(ADDRESS_IN(0))); -- masked on aligned word or byte
|
|
MASK(3) <= not(LONGWORD_ACCESS); -- masked for everything except long word access
|
|
|
|
SRAM_ADDR <= ADDRESS_IN(18 downto 1);
|
|
|
|
SRAM_CE0_N <= ADDRESS_IN(19);
|
|
SRAM_CE1_N <= not ADDRESS_IN(19);
|
|
|
|
if WRITE_EN = '1' then
|
|
STATE <= ST_WRITE0;
|
|
else
|
|
STATE <= ST_READ0;
|
|
end if;
|
|
end if;
|
|
|
|
when ST_WRITE0 =>
|
|
SRAM_LB_N <= MASK(0);
|
|
SRAM_UB_N <= MASK(1);
|
|
SRAM_DI(7 downto 0) <= DATA_IN(7 downto 0);
|
|
SRAM_DI(15 downto 8) <= (DATA_IN(15 downto 8) and not(repeat(8,MASK(0)))) or (DATA_IN(7 downto 0) and repeat(8,MASK(0)));
|
|
SRAM_WE_N <= '0';
|
|
STATE <= ST_WRITE1;
|
|
|
|
when ST_WRITE1 =>
|
|
SRAM_WE_N <= '1';
|
|
STATE <= ST_WRITE2;
|
|
|
|
when ST_WRITE2 =>
|
|
SRAM_ADDR <= ADDRESS_IN_NEXT(17 downto 0);
|
|
SRAM_CE0_N <= ADDRESS_IN_NEXT(18);
|
|
SRAM_CE1_N <= not ADDRESS_IN_NEXT(18);
|
|
SRAM_DI(7 downto 0) <= (DATA_IN(23 downto 16) and not(repeat(8,MASK(0)))) or (DATA_IN(15 downto 8) and repeat(8,MASK(0)));
|
|
SRAM_DI(15 downto 8) <= DATA_IN(31 downto 24);
|
|
SRAM_LB_N <= MASK(2);
|
|
SRAM_UB_N <= MASK(3);
|
|
SRAM_WE_N <= '0';
|
|
STATE <= ST_IDLE;
|
|
|
|
when ST_READ0 =>
|
|
SRAM_LB_N <= MASK(0);
|
|
SRAM_UB_N <= MASK(1);
|
|
SRAM_OE_N <= '0';
|
|
STATE <= ST_READ1;
|
|
|
|
when ST_READ1 =>
|
|
DATA_OUT_REG(7 downto 0) <= (SRAM_DO(7 downto 0) and not(repeat(8,MASK(0)))) or (SRAM_DO(15 downto 8) and repeat(8,MASK(0)));
|
|
DATA_OUT_REG(15 downto 8) <= SRAM_DO(15 downto 8);
|
|
SRAM_ADDR <= ADDRESS_IN_NEXT(17 downto 0);
|
|
SRAM_CE0_N <= ADDRESS_IN_NEXT(18);
|
|
SRAM_CE1_N <= not ADDRESS_IN_NEXT(18);
|
|
SRAM_LB_N <= MASK(2);
|
|
SRAM_UB_N <= MASK(3);
|
|
STATE <= ST_READ2;
|
|
|
|
when ST_READ2 =>
|
|
DATA_OUT_REG(15 downto 8 ) <= (SRAM_DO(7 downto 0) and repeat(8,MASK(0))) or (DATA_OUT_REG(15 downto 8) and not(repeat(8,MASK(0))));
|
|
DATA_OUT_REG(31 downto 16) <= SRAM_DO(15 downto 0);
|
|
STATE <= ST_IDLE;
|
|
|
|
when OTHERS =>
|
|
STATE <= ST_IDLE;
|
|
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
END vhdl;
|