mirror of
https://github.com/UzixLS/ncomputing-l230.git
synced 2025-07-18 23:01:18 +03:00
add fpga firmware template
This commit is contained in:
271
fpga/sdram.vhd
Normal file
271
fpga/sdram.vhd
Normal file
@ -0,0 +1,271 @@
|
||||
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;
|
Reference in New Issue
Block a user