mirror of
https://github.com/UzixLS/ncomputing-l230.git
synced 2025-07-18 14:51:31 +03:00
272 lines
8.0 KiB
VHDL
272 lines
8.0 KiB
VHDL
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.numeric_std.all;
|
|
|
|
entity sdram is
|
|
generic(
|
|
freq : integer := 80
|
|
);
|
|
|
|
port(
|
|
clk : in std_logic;
|
|
reset : in std_logic;
|
|
refresh : in std_logic;
|
|
|
|
memAddress : in std_logic_vector(21 downto 0);
|
|
memDataIn : in std_logic_vector(31 downto 0);
|
|
memDataOut : out std_logic_vector(31 downto 0);
|
|
memDataMask : in std_logic_vector(3 downto 0);
|
|
memWr : in std_logic;
|
|
memReq : in std_logic;
|
|
memAck : out std_logic := '0';
|
|
|
|
memAddress2 : in std_logic_vector(21 downto 0);
|
|
memDataIn2 : in std_logic_vector(31 downto 0);
|
|
memDataOut2 : out std_logic_vector(31 downto 0);
|
|
memDataMask2 : in std_logic_vector(3 downto 0);
|
|
memWr2 : in std_logic;
|
|
memReq2 : in std_logic;
|
|
memAck2 : out std_logic := '0';
|
|
|
|
-- SD-RAM ports
|
|
pMemClk : out std_logic; -- SD-RAM Clock
|
|
pMemCke : out std_logic; -- SD-RAM Clock enable
|
|
pMemCs_n : out std_logic; -- SD-RAM Chip select
|
|
pMemRas_n : out std_logic; -- SD-RAM Row/RAS
|
|
pMemCas_n : out std_logic; -- SD-RAM /CAS
|
|
pMemWe_n : out std_logic; -- SD-RAM /WE
|
|
pMemDqm : out std_logic_vector(3 downto 0); -- SD-RAM DQM
|
|
pMemBa1 : out std_logic; -- SD-RAM Bank select address 1
|
|
pMemBa0 : out std_logic; -- SD-RAM Bank select address 0
|
|
pMemAdr : out std_logic_vector(11 downto 0); -- SD-RAM Address
|
|
pMemDat : inout std_logic_vector(31 downto 0) -- SD-RAM Data
|
|
);
|
|
|
|
end sdram;
|
|
|
|
architecture rtl of sdram is
|
|
|
|
-- -- SD-RAM control signals
|
|
signal SdrCmd : std_logic_vector(3 downto 0);
|
|
signal SdrBa0 : std_logic;
|
|
signal SdrBa1 : std_logic;
|
|
signal SdrDqm : std_logic_vector(3 downto 0);
|
|
signal SdrAdr : std_logic_vector(11 downto 0);
|
|
signal SdrDat : std_logic_vector(31 downto 0);
|
|
|
|
signal iMemAck : std_logic;
|
|
signal iMemAck2 : std_logic;
|
|
|
|
constant SdrCmd_de : std_logic_vector(3 downto 0) := "1111"; -- deselect
|
|
constant SdrCmd_pr : std_logic_vector(3 downto 0) := "0010"; -- precharge all
|
|
constant SdrCmd_re : std_logic_vector(3 downto 0) := "0001"; -- refresh
|
|
constant SdrCmd_ms : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
|
|
constant SdrCmd_xx : std_logic_vector(3 downto 0) := "0111"; -- no operation
|
|
constant SdrCmd_ac : std_logic_vector(3 downto 0) := "0011"; -- activate
|
|
constant SdrCmd_rd : std_logic_vector(3 downto 0) := "0101"; -- read
|
|
constant SdrCmd_wr : std_logic_vector(3 downto 0) := "0100"; -- write
|
|
|
|
begin
|
|
|
|
memAck <= iMemAck;
|
|
memAck2 <= iMemAck2;
|
|
|
|
process( clk )
|
|
|
|
type typSdrRoutine is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
|
|
variable SdrRoutine : typSdrRoutine := SdrRoutine_Null;
|
|
variable SdrRoutineSeq : unsigned(7 downto 0) := X"00";
|
|
|
|
variable refreshDelayCounter : unsigned(23 downto 0) := x"000000";
|
|
variable SdrRefreshCounter : unsigned(15 downto 0) := X"0000";
|
|
|
|
variable SdrPort : std_logic := '0';
|
|
variable SdrAddress : std_logic_vector(21 downto 0);
|
|
|
|
begin
|
|
|
|
if clk'event and clk = '1' then
|
|
|
|
iMemAck <= '0';
|
|
iMemAck2 <= '0';
|
|
|
|
case SdrRoutine is
|
|
|
|
when SdrRoutine_Null =>
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrDat <= (others => 'Z');
|
|
|
|
if refreshDelayCounter = 0 then
|
|
SdrRoutine := SdrRoutine_Init;
|
|
end if;
|
|
|
|
when SdrRoutine_Init =>
|
|
if( SdrRoutineSeq = X"0" ) then
|
|
SdrCmd <= SdrCmd_pr;
|
|
SdrAdr <= "111111111111";
|
|
SdrBa1 <= '0';
|
|
SdrBa0 <= '0';
|
|
SdrDqm <= "1111";
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"4" or SdrRoutineSeq = X"0C" ) then
|
|
SdrCmd <= SdrCmd_re;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"14" ) then
|
|
SdrCmd <= SdrCmd_ms;
|
|
SdrAdr <= "000" & "0" & "0" & "010" & "0" & "000";
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"17" ) then
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := X"00";
|
|
SdrRoutine := SdrRoutine_Idle;
|
|
else
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
end if;
|
|
|
|
when SdrRoutine_Idle =>
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrDat <= (others => 'Z');
|
|
|
|
if memReq = '1' and iMemAck = '0' then
|
|
SdrPort := '0';
|
|
SdrAddress := memAddress;
|
|
|
|
if( memWr = '1' ) then
|
|
SdrRoutine := SdrRoutine_WriteOne;
|
|
else
|
|
SdrRoutine := SdrRoutine_ReadOne;
|
|
end if;
|
|
|
|
elsif memReq2 = '1' and iMemAck2 = '0' then
|
|
SdrPort := '1';
|
|
SdrAddress := memAddress2;
|
|
|
|
if( memWr2 = '1' ) then
|
|
SdrRoutine := SdrRoutine_WriteOne;
|
|
else
|
|
SdrRoutine := SdrRoutine_ReadOne;
|
|
end if;
|
|
|
|
|
|
elsif SdrRefreshCounter < 4096 and refresh = '1' then
|
|
SdrRoutine := SdrRoutine_RefreshAll;
|
|
SdrRefreshCounter := SdrRefreshCounter + 1;
|
|
end if;
|
|
|
|
when SdrRoutine_RefreshAll =>
|
|
if( SdrRoutineSeq = X"0" ) then
|
|
SdrCmd <= SdrCmd_re;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"6" ) then
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := X"00";
|
|
SdrRoutine := SdrRoutine_Idle;
|
|
else
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
end if;
|
|
|
|
when SdrRoutine_ReadOne =>
|
|
if( SdrRoutineSeq = X"0" ) then
|
|
SdrCmd <= SdrCmd_ac;
|
|
SdrBa0 <= SdrAddress(20);
|
|
SdrBa1 <= SdrAddress(21);
|
|
SdrAdr <= SdrAddress(19 downto 8);
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"2" ) then
|
|
SdrCmd <= SdrCmd_rd;
|
|
SdrDqm <= "0000";
|
|
SdrAdr(11 downto 8) <= "0100";
|
|
SdrAdr(7 downto 0) <= SdrAddress(7 downto 0);
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"5" ) then
|
|
if( SdrPort = '0' ) then
|
|
memDataOut <= pMemDat;
|
|
iMemAck <= '1';
|
|
else
|
|
memDataOut2 <= pMemDat;
|
|
iMemAck2 <= '1';
|
|
end if;
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"6" ) then
|
|
SdrRoutineSeq := X"00";
|
|
SdrRoutine := SdrRoutine_Idle;
|
|
else
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
end if;
|
|
|
|
when SdrRoutine_WriteOne =>
|
|
if( SdrRoutineSeq = X"0" ) then
|
|
SdrCmd <= SdrCmd_ac;
|
|
SdrBa0 <= SdrAddress(20);
|
|
SdrBa1 <= SdrAddress(21);
|
|
SdrAdr <= SdrAddress(19 downto 8);
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"2" ) then
|
|
SdrCmd <= SdrCmd_wr;
|
|
SdrAdr(11 downto 8) <= "0100";
|
|
SdrAdr(7 downto 0) <= SdrAddress(7 downto 0);
|
|
if( SdrPort = '0' ) then
|
|
SdrDat <= memDataIn;
|
|
SdrDqm(0) <= not memDataMask(0);
|
|
SdrDqm(1) <= not memDataMask(1);
|
|
SdrDqm(2) <= not memDataMask(2);
|
|
SdrDqm(3) <= not memDataMask(3);
|
|
else
|
|
SdrDat <= memDataIn2;
|
|
SdrDqm(0) <= not memDataMask2(0);
|
|
SdrDqm(1) <= not memDataMask2(1);
|
|
SdrDqm(2) <= not memDataMask2(2);
|
|
SdrDqm(3) <= not memDataMask2(3);
|
|
end if;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"3" ) then
|
|
if( SdrPort = '0' ) then
|
|
iMemAck <= '1';
|
|
else
|
|
iMemAck2 <= '1';
|
|
end if;
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrDat <= (others => 'Z');
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
elsif( SdrRoutineSeq = X"5" ) then
|
|
SdrRoutineSeq := X"00";
|
|
SdrRoutine := SdrRoutine_Idle;
|
|
else
|
|
SdrCmd <= SdrCmd_xx;
|
|
SdrRoutineSeq := SdrRoutineSeq + 1;
|
|
end if;
|
|
|
|
end case;
|
|
|
|
refreshDelayCounter := refreshDelayCounter + 1;
|
|
|
|
if( refreshDelayCounter >= ( freq * 1000 * 64 ) ) then
|
|
refreshDelayCounter := x"000000";
|
|
SdrRefreshCounter := x"0000";
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
pMemClk <= not clk;
|
|
pMemCke <= '1';
|
|
|
|
pMemCs_n <= SdrCmd(3);
|
|
pMemRas_n <= SdrCmd(2);
|
|
pMemCas_n <= SdrCmd(1);
|
|
pMemWe_n <= SdrCmd(0);
|
|
|
|
pMemDqm <= SdrDqm;
|
|
pMemBa1 <= SdrBa1;
|
|
pMemBa0 <= SdrBa0;
|
|
|
|
pMemAdr <= SdrAdr;
|
|
pMemDat <= SdrDat;
|
|
|
|
end rtl;
|