Project

General

Profile

---------------------------------------------------------------------------
-- 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;
(11-11/13)