Iprove SDRAM controller.

This commit is contained in:
sorgelig
2018-08-16 17:23:10 +08:00
parent 926e6efe75
commit 4fe409ba5b

View File

@ -13,77 +13,48 @@ use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity sdram is
port(
CLK : in std_logic;
clk_28MHz : in std_logic;
c0 : in std_logic;
c1 : in std_logic;
c2 : in std_logic;
c3 : in std_logic;
curr_cpu : in std_logic;
-- Memory port
loader : in std_logic;
bsel : in std_logic_vector(1 downto 0); -- Active HI
A : in std_logic_vector(23 downto 0);
DI : in std_logic_vector(15 downto 0);
DO : out std_logic_vector(15 downto 0);
DO_cpu : out std_logic_vector(15 downto 0);
dram_stb : out std_logic;
----------------------------
REQ : in std_logic;
RNW : in std_logic;
RFSH : in std_logic; --< REFRESH command NOT USED
RFSHREQ : out std_logic; --> request for refresh
IDLE : out std_logic; -->
-- SDRAM Pin
CK : out std_logic;
CKE : out std_logic;
RAS_n : out std_logic;
CAS_n : out std_logic;
WE_n : out std_logic;
BA1 : out std_logic;
BA0 : out std_logic;
MA : out std_logic_vector(12 downto 0);
DQ : inout std_logic_vector(15 downto 0);
DQML : out std_logic;
DQMH : out std_logic;
--
TST : out std_logic_vector(3 downto 0)
);
port(
CLK : in std_logic;
clk_28MHz: in std_logic;
c0 : in std_logic;
c3 : in std_logic;
-- Memory port
loader : in std_logic;
bsel : in std_logic_vector(1 downto 0); -- Active HI
A : in std_logic_vector(23 downto 0);
DI : in std_logic_vector(15 downto 0);
DO : out std_logic_vector(15 downto 0);
curr_cpu : in std_logic;
DO_cpu : out std_logic_vector(15 downto 0);
REQ : in std_logic;
RNW : in std_logic;
-- SDRAM Pin
CKE : out std_logic;
RAS_n : out std_logic;
CAS_n : out std_logic;
WE_n : out std_logic;
CS_n : out std_logic;
BA : out std_logic_vector(1 downto 0);
MA : out std_logic_vector(12 downto 0);
DQ : inout std_logic_vector(15 downto 0);
DQML : out std_logic;
DQMH : out std_logic
);
end sdram;
architecture rtl of sdram is
signal state : unsigned(4 downto 0) := "00000";
signal addr_in : std_logic_vector(23 downto 0);
signal address : std_logic_vector(23 downto 0);
signal bsel_int : std_logic_vector(1 downto 0);
signal rfsh_cnt : unsigned(9 downto 0) := "0000000000";
signal rfsh_req : std_logic := '0';
signal data_reg : std_logic_vector(15 downto 0);
signal cpu_reg : std_logic_vector(15 downto 0);
signal data_in : std_logic_vector(15 downto 0);
signal idle1 : std_logic;
signal st_rfsh : std_logic;
signal req_dis : std_logic;
------------------------------
signal col : std_logic_vector(7 downto 0);
signal WR_in : std_logic;
signal WR_in1 : std_logic;
-- signal WR_r : std_logic;
signal RD_in : std_logic;
signal RD_in1 : std_logic;
-- signal RD_r : std_logic;
signal REQ_in : std_logic;
signal RNW_in : std_logic;
signal rd_op : std_logic;
signal RFSH_in : std_logic;
-- SD-RAM control signals
signal sdr_cmd : std_logic_vector(2 downto 0);
signal sdr_ba0 : std_logic;
signal sdr_ba1 : std_logic;
signal sdr_dqml : std_logic;
signal sdr_dqmh : std_logic;
signal sdr_a : std_logic_vector(12 downto 0);
signal sdr_dq : std_logic_vector(15 downto 0);
constant SdrCmd_xx : std_logic_vector(2 downto 0) := "111"; -- no operation
constant SdrCmd_ac : std_logic_vector(2 downto 0) := "011"; -- activate
@ -99,156 +70,96 @@ architecture rtl of sdram is
begin
TST(0) <= WR_in; --idle1; --RD_in;
TST(1) <= data_in(0); --idle1; --
TST(2) <= idle1; --
TST(3) <= st_rfsh;
process (clk_28MHz, c3, DI, A, c0)
process (clk_28MHz)
begin
if rising_edge (clk_28MHz) and (c3 = '1') then --next_cycle
if (REQ = '1' and RNW = '1') then
RD_in <= '1';
elsif (REQ = '1' and RNW = '0') then
WR_in <= '1';
else
RFSH_in <= '1';
if rising_edge (clk_28MHz) then
if c3 = '1' then --next_cycle
RD_in <= REQ and RNW;
WR_in <= REQ and not RNW;
RFSH_in <= not REQ;
end if;
if c0 = '1' then --NOT WORK
RD_in <= '0';
WR_in <= '0';
RFSH_in <= '0';
end if;
end if;
data_in <= DI;
addr_in <= A;
if rising_edge (clk_28MHz) and (c0 = '1') then --NOT WORK
RD_in <= '0';
WR_in <= '0';
RFSH_in <= '0';
end if;
end process;
process (CLK)
begin
if CLK'event and CLK = '0' then
if rising_edge(CLK) then
---------------------------------------------------------
case state is
-- Init
when "00000" => -- s00
sdr_cmd <= SdrCmd_pr; -- PRECHARGE
sdr_a <= "1111111111111";
sdr_ba1 <= '0';
sdr_ba0 <= '0';
sdr_dqml <= '1';
sdr_dqmh <= '1';
when "00000" => -- s00
sdr_cmd <= SdrCmd_pr; -- PRECHARGE
DQ <= (others => 'Z');
MA <= (others => '1');
BA <= "00";
DQML <= '1';
DQMH <= '1';
state <= state + 1;
when "00011" | "01010" => -- s03 s0A
sdr_cmd <= SdrCmd_re; -- REFRESH
when "00011" | "01010" => -- s03 s0A
sdr_cmd <= SdrCmd_re; -- REFRESH
state <= state + 1;
when "10001" => -- s11
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
sdr_a <= "000" & "1" & "00" & "010" & "0" & "000";
when "10001" => -- s11
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
MA <= "000" & "1" & "00" & "010" & "0" & "000";
state <= state + 1;
-- Idle
when "11000" => -- s18
sdr_dq <= (others => 'Z');
if RD_in = '1' then
idle1 <= '0';
bsel_int <= bsel;
address <= addr_in; -- LOCK ADDR
sdr_cmd <= SdrCmd_ac; -- ACTIVE
sdr_ba1 <= addr_in(10); -- A(11)
sdr_ba0 <= addr_in(9); -- A(10)
-- sdr_a <= addr_in(23 downto 11); -- RAW_ADDR(12..0)
sdr_a <= "0"&addr_in(23)&addr_in(20 downto 11)&addr_in(8); -- RAW_ADDR(12..0)
state <= "11001"; -- s19 Read = when "11010"
elsif WR_in = '1' and (loader = '1' or addr_in(23) = '0') then --Rising UP
idle1 <= '0';
rd_op <= '0';
bsel_int <= bsel;
address <= addr_in;
sdr_cmd <= SdrCmd_ac; -- ACTIVE
sdr_ba1 <= addr_in(10);
sdr_ba0 <= addr_in(9);
-- sdr_a <= addr_in(23 downto 11);
sdr_a <= "0"&addr_in(23)&addr_in(20 downto 11)&addr_in(8); -- RAW_ADDR(12..0)
state <= "11011"; -- s1B Write
when "11000" => -- s18
rd_op <= '0';
if rd_op = '1' then
DO <= DQ;
if curr_cpu = '1' then
DO_cpu <= DQ;
end if;
end if;
if RD_in = '1' or (WR_in = '1' and (loader = '1' or A(23) = '0')) then
col <= A(7 downto 0); -- LOCK COL
sdr_cmd <= SdrCmd_ac; -- ACTIVE
BA <= A(10 downto 9);
MA <= "0"&A(23)&A(20 downto 11)&A(8); -- RAW_ADDR(12..0)
DQML <= not (bsel(0) or RD_in);
DQMH <= not (bsel(1) or RD_in);
rd_op <= RD_in;
state <= state + 1;
elsif RFSH_in = '1' then
idle1 <= '0';
rd_op <= '0';
st_rfsh <= '1';
rfsh_req <= '0';
sdr_cmd <= SdrCmd_re; -- REFRESH
state <= "10011"; -- s13
else
sdr_cmd <= SdrCmd_xx; -- NOP
idle1 <= '1';
rd_op <= '0';
st_rfsh <= '0';
end if;
-- A24 A23 A22 A21 A20 A19 A18 A17 A16 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
-- -----------------------ROW------------------------- BA1 BA0 -----------COLUMN------------
-- Single read - with auto precharge
when "11010" => -- s1A
sdr_cmd <= SdrCmd_rd; -- READ (A10 = 1 enable auto precharge; A9..0 = column)
-- sdr_a <= "0010" & address(8 downto 0);
sdr_a <= "00100" & address(7 downto 0);
sdr_dqml <= '0';
sdr_dqmh <= '0';
state <= "10110"; -- s16
rd_op <= '1';
-- Single write - with auto precharge
when "11100" => -- s1C
sdr_cmd <= SdrCmd_wr; -- WRITE (A10 = 1 enable auto precharge; A9..0 = column)
-- sdr_a <= "0010" & address(8 downto 0);
sdr_a <= "00100" & address(7 downto 0);
sdr_dqml <= not bsel_int(0);
sdr_dqmh <= not bsel_int(1);
sdr_dq <= data_in;
-- Single read/write - with auto precharge
when "11010" => -- s1A
MA <= "00100" & col; -- A10 = 1 enable auto precharge; A9..0 = column
state <= "10110"; -- s16
if rd_op = '1' then
sdr_cmd <= SdrCmd_rd; -- READ
else
sdr_cmd <= SdrCmd_wr; -- WRITE
DQ <= DI;
end if;
when others =>
sdr_dq <= (others => 'Z');
sdr_cmd <= SdrCmd_xx; -- NOP
DQ <= (others => 'Z');
sdr_cmd <= SdrCmd_xx; -- NOP
state <= state + 1;
end case;
end if;
end process;
-- Providing a distributed AUTO REFRESH command every 7.81us
if rfsh_cnt = "1010010001" then -- (84MHz * 1000 * 64 / 8192) = 657 %10 1001 0001
rfsh_cnt <= (others => '0');
rfsh_req <= '1';
else
rfsh_cnt <= rfsh_cnt + 1;
end if;
end if;
end process;
process (CLK, rd_op)
begin --------------CLK = '0'------OK------------
if CLK'event and CLK = '1' and rd_op = '1' then ---idle1 = '0' then
if state = "11000" then -- s18
data_reg <= DQ;
if curr_cpu = '1' then
cpu_reg <= DQ;
end if;
end if;
end if;
end process;
IDLE <= idle1;
DO <= data_reg;
DO_cpu <= cpu_reg;
RFSHREQ <= rfsh_req;
CK <= CLK;
CKE <= '1';
RAS_n <= sdr_cmd(2);
CAS_n <= sdr_cmd(1);
CKE <= '1';
CS_n <= '0';
RAS_n <= sdr_cmd(2);
CAS_n <= sdr_cmd(1);
WE_n <= sdr_cmd(0);
DQML <= sdr_dqml;
DQMH <= sdr_dqmh;
BA1 <= sdr_ba1;
BA0 <= sdr_ba0;
MA <= sdr_a;
DQ <= sdr_dq;
dram_stb <= rd_op;
end rtl;