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; use IEEE.numeric_std.all;
entity sdram is entity sdram is
port( port(
CLK : in std_logic; CLK : in std_logic;
clk_28MHz : in std_logic; clk_28MHz: in std_logic;
c0 : in std_logic; c0 : in std_logic;
c1 : in std_logic; c3 : in std_logic;
c2 : in std_logic;
c3 : in std_logic; -- Memory port
curr_cpu : in std_logic; loader : in std_logic;
-- Memory port bsel : in std_logic_vector(1 downto 0); -- Active HI
loader : in std_logic; A : in std_logic_vector(23 downto 0);
bsel : in std_logic_vector(1 downto 0); -- Active HI DI : in std_logic_vector(15 downto 0);
A : in std_logic_vector(23 downto 0); DO : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(15 downto 0); curr_cpu : in std_logic;
DO : out std_logic_vector(15 downto 0); DO_cpu : out std_logic_vector(15 downto 0);
DO_cpu : out std_logic_vector(15 downto 0); REQ : in std_logic;
dram_stb : out std_logic; RNW : in std_logic;
----------------------------
REQ : in std_logic; -- SDRAM Pin
RNW : in std_logic; CKE : out std_logic;
RFSH : in std_logic; --< REFRESH command NOT USED RAS_n : out std_logic;
RFSHREQ : out std_logic; --> request for refresh CAS_n : out std_logic;
IDLE : out std_logic; --> WE_n : out std_logic;
-- SDRAM Pin CS_n : out std_logic;
CK : out std_logic; BA : out std_logic_vector(1 downto 0);
CKE : out std_logic; MA : out std_logic_vector(12 downto 0);
RAS_n : out std_logic; DQ : inout std_logic_vector(15 downto 0);
CAS_n : out std_logic; DQML : out std_logic;
WE_n : out std_logic; DQMH : 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)
);
end sdram; end sdram;
architecture rtl of sdram is architecture rtl of sdram is
signal state : unsigned(4 downto 0) := "00000"; signal state : unsigned(4 downto 0) := "00000";
signal addr_in : std_logic_vector(23 downto 0); signal col : std_logic_vector(7 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 WR_in : std_logic; signal WR_in : std_logic;
signal WR_in1 : std_logic;
-- signal WR_r : std_logic;
signal RD_in : std_logic; signal RD_in : std_logic;
signal RD_in1 : std_logic;
-- signal RD_r : std_logic;
signal REQ_in : std_logic; signal REQ_in : std_logic;
signal RNW_in : std_logic; signal RNW_in : std_logic;
signal rd_op : std_logic; signal rd_op : std_logic;
signal RFSH_in : std_logic; signal RFSH_in : std_logic;
-- SD-RAM control signals
signal sdr_cmd : std_logic_vector(2 downto 0); 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_xx : std_logic_vector(2 downto 0) := "111"; -- no operation
constant SdrCmd_ac : std_logic_vector(2 downto 0) := "011"; -- activate constant SdrCmd_ac : std_logic_vector(2 downto 0) := "011"; -- activate
@ -99,156 +70,96 @@ architecture rtl of sdram is
begin begin
TST(0) <= WR_in; --idle1; --RD_in; process (clk_28MHz)
TST(1) <= data_in(0); --idle1; --
TST(2) <= idle1; --
TST(3) <= st_rfsh;
process (clk_28MHz, c3, DI, A, c0)
begin begin
if rising_edge (clk_28MHz) and (c3 = '1') then --next_cycle if rising_edge (clk_28MHz) then
if (REQ = '1' and RNW = '1') then if c3 = '1' then --next_cycle
RD_in <= '1'; RD_in <= REQ and RNW;
elsif (REQ = '1' and RNW = '0') then WR_in <= REQ and not RNW;
WR_in <= '1'; RFSH_in <= not REQ;
else end if;
RFSH_in <= '1';
if c0 = '1' then --NOT WORK
RD_in <= '0';
WR_in <= '0';
RFSH_in <= '0';
end if; 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 if;
end process; end process;
process (CLK) process (CLK)
begin begin
if CLK'event and CLK = '0' then if rising_edge(CLK) then
--------------------------------------------------------- ---------------------------------------------------------
case state is case state is
-- Init -- Init
when "00000" => -- s00 when "00000" => -- s00
sdr_cmd <= SdrCmd_pr; -- PRECHARGE sdr_cmd <= SdrCmd_pr; -- PRECHARGE
sdr_a <= "1111111111111"; DQ <= (others => 'Z');
sdr_ba1 <= '0'; MA <= (others => '1');
sdr_ba0 <= '0'; BA <= "00";
sdr_dqml <= '1'; DQML <= '1';
sdr_dqmh <= '1'; DQMH <= '1';
state <= state + 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; state <= state + 1;
when "10001" => -- s11
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER when "10001" => -- s11
sdr_a <= "000" & "1" & "00" & "010" & "0" & "000"; sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
MA <= "000" & "1" & "00" & "010" & "0" & "000";
state <= state + 1; state <= state + 1;
-- Idle -- Idle
when "11000" => -- s18 when "11000" => -- s18
sdr_dq <= (others => 'Z'); rd_op <= '0';
if RD_in = '1' then if rd_op = '1' then
idle1 <= '0'; DO <= DQ;
bsel_int <= bsel; if curr_cpu = '1' then
address <= addr_in; -- LOCK ADDR DO_cpu <= DQ;
sdr_cmd <= SdrCmd_ac; -- ACTIVE end if;
sdr_ba1 <= addr_in(10); -- A(11) end if;
sdr_ba0 <= addr_in(9); -- A(10) if RD_in = '1' or (WR_in = '1' and (loader = '1' or A(23) = '0')) then
-- sdr_a <= addr_in(23 downto 11); -- RAW_ADDR(12..0) col <= A(7 downto 0); -- LOCK COL
sdr_a <= "0"&addr_in(23)&addr_in(20 downto 11)&addr_in(8); -- RAW_ADDR(12..0) sdr_cmd <= SdrCmd_ac; -- ACTIVE
state <= "11001"; -- s19 Read = when "11010" BA <= A(10 downto 9);
elsif WR_in = '1' and (loader = '1' or addr_in(23) = '0') then --Rising UP MA <= "0"&A(23)&A(20 downto 11)&A(8); -- RAW_ADDR(12..0)
idle1 <= '0'; DQML <= not (bsel(0) or RD_in);
rd_op <= '0'; DQMH <= not (bsel(1) or RD_in);
bsel_int <= bsel; rd_op <= RD_in;
address <= addr_in; state <= state + 1;
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
elsif RFSH_in = '1' then elsif RFSH_in = '1' then
idle1 <= '0';
rd_op <= '0';
st_rfsh <= '1';
rfsh_req <= '0';
sdr_cmd <= SdrCmd_re; -- REFRESH sdr_cmd <= SdrCmd_re; -- REFRESH
state <= "10011"; -- s13 state <= "10011"; -- s13
else
sdr_cmd <= SdrCmd_xx; -- NOP
idle1 <= '1';
rd_op <= '0';
st_rfsh <= '0';
end if; 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 -- 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------------ -- -----------------------ROW------------------------- BA1 BA0 -----------COLUMN------------
-- Single read - with auto precharge
when "11010" => -- s1A -- Single read/write - with auto precharge
sdr_cmd <= SdrCmd_rd; -- READ (A10 = 1 enable auto precharge; A9..0 = column) when "11010" => -- s1A
-- sdr_a <= "0010" & address(8 downto 0); MA <= "00100" & col; -- A10 = 1 enable auto precharge; A9..0 = column
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;
state <= "10110"; -- s16 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 => when others =>
sdr_dq <= (others => 'Z'); DQ <= (others => 'Z');
sdr_cmd <= SdrCmd_xx; -- NOP sdr_cmd <= SdrCmd_xx; -- NOP
state <= state + 1; state <= state + 1;
end case; end case;
-- 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 if;
end process; 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'; CKE <= '1';
RAS_n <= sdr_cmd(2); CS_n <= '0';
CAS_n <= sdr_cmd(1); RAS_n <= sdr_cmd(2);
CAS_n <= sdr_cmd(1);
WE_n <= sdr_cmd(0); 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; end rtl;