mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
Iprove SDRAM controller.
This commit is contained in:
197
src/sdram.vhd
197
src/sdram.vhd
@ -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;
|
|
||||||
c2 : in std_logic;
|
|
||||||
c3 : in std_logic;
|
c3 : in std_logic;
|
||||||
curr_cpu : in std_logic;
|
|
||||||
-- Memory port
|
-- Memory port
|
||||||
loader : in std_logic;
|
loader : in std_logic;
|
||||||
bsel : in std_logic_vector(1 downto 0); -- Active HI
|
bsel : in std_logic_vector(1 downto 0); -- Active HI
|
||||||
A : in std_logic_vector(23 downto 0);
|
A : in std_logic_vector(23 downto 0);
|
||||||
DI : in std_logic_vector(15 downto 0);
|
DI : in std_logic_vector(15 downto 0);
|
||||||
DO : out 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);
|
DO_cpu : out std_logic_vector(15 downto 0);
|
||||||
dram_stb : out std_logic;
|
|
||||||
----------------------------
|
|
||||||
REQ : in std_logic;
|
REQ : in std_logic;
|
||||||
RNW : 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
|
-- SDRAM Pin
|
||||||
CK : out std_logic;
|
|
||||||
CKE : out std_logic;
|
CKE : out std_logic;
|
||||||
RAS_n : out std_logic;
|
RAS_n : out std_logic;
|
||||||
CAS_n : out std_logic;
|
CAS_n : out std_logic;
|
||||||
WE_n : out std_logic;
|
WE_n : out std_logic;
|
||||||
BA1 : out std_logic;
|
CS_n : out std_logic;
|
||||||
BA0 : out std_logic;
|
BA : out std_logic_vector(1 downto 0);
|
||||||
MA : out std_logic_vector(12 downto 0);
|
MA : out std_logic_vector(12 downto 0);
|
||||||
DQ : inout std_logic_vector(15 downto 0);
|
DQ : inout std_logic_vector(15 downto 0);
|
||||||
DQML : out std_logic;
|
DQML : out std_logic;
|
||||||
DQMH : 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
|
|
||||||
RFSH_in <= '1';
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
data_in <= DI;
|
if c0 = '1' then --NOT WORK
|
||||||
addr_in <= A;
|
|
||||||
if rising_edge (clk_28MHz) and (c0 = '1') then --NOT WORK
|
|
||||||
RD_in <= '0';
|
RD_in <= '0';
|
||||||
WR_in <= '0';
|
WR_in <= '0';
|
||||||
RFSH_in <= '0';
|
RFSH_in <= '0';
|
||||||
end if;
|
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
|
when "00011" | "01010" => -- s03 s0A
|
||||||
sdr_cmd <= SdrCmd_re; -- REFRESH
|
sdr_cmd <= SdrCmd_re; -- REFRESH
|
||||||
state <= state + 1;
|
state <= state + 1;
|
||||||
|
|
||||||
when "10001" => -- s11
|
when "10001" => -- s11
|
||||||
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
|
sdr_cmd <= SdrCmd_ms; -- LOAD MODE REGISTER
|
||||||
sdr_a <= "000" & "1" & "00" & "010" & "0" & "000";
|
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');
|
|
||||||
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';
|
rd_op <= '0';
|
||||||
bsel_int <= bsel;
|
if rd_op = '1' then
|
||||||
address <= addr_in;
|
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
|
sdr_cmd <= SdrCmd_ac; -- ACTIVE
|
||||||
sdr_ba1 <= addr_in(10);
|
BA <= A(10 downto 9);
|
||||||
sdr_ba0 <= addr_in(9);
|
MA <= "0"&A(23)&A(20 downto 11)&A(8); -- RAW_ADDR(12..0)
|
||||||
-- sdr_a <= addr_in(23 downto 11);
|
DQML <= not (bsel(0) or RD_in);
|
||||||
sdr_a <= "0"&addr_in(23)&addr_in(20 downto 11)&addr_in(8); -- RAW_ADDR(12..0)
|
DQMH <= not (bsel(1) or RD_in);
|
||||||
state <= "11011"; -- s1B Write
|
rd_op <= RD_in;
|
||||||
|
state <= state + 1;
|
||||||
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
|
|
||||||
|
-- Single read/write - with auto precharge
|
||||||
when "11010" => -- s1A
|
when "11010" => -- s1A
|
||||||
sdr_cmd <= SdrCmd_rd; -- READ (A10 = 1 enable auto precharge; A9..0 = column)
|
MA <= "00100" & col; -- 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;
|
|
||||||
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';
|
||||||
|
CS_n <= '0';
|
||||||
RAS_n <= sdr_cmd(2);
|
RAS_n <= sdr_cmd(2);
|
||||||
CAS_n <= sdr_cmd(1);
|
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;
|
Reference in New Issue
Block a user