-- SDRAM Controller -- Target Device: SAMSUNG K4S643232E -- Burst Length=8 CAS Latency=3 -- MBEWARE library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity SDRAM_CTL is port ( CLK: in std_logic; -- System Clock RESET: in std_logic; -- Command INITCMD: in std_logic; -- Start Initialize WRCMD: in std_logic; -- Start Write RDCMD: in std_logic; -- Start Read RFSHCMD: in std_logic; -- Start Refresh INITACK: out std_logic; WRACK: out std_logic; RDACK: out std_logic; RFSHACK: out std_logic; -- SDRAM Signal DQM: out std_logic; CSN: out std_logic; -- CMD(3) RASN: out std_logic; -- CMD(2) CASN: out std_logic; -- CMD(1) WEN: out std_logic; -- CMD(0) TRIRD: out std_logic; -- Tristate Direction -- Address AL: in std_logic_vector(7 downto 3); AH: in std_logic_vector(4 downto 0); AOUT: out std_logic_vector(10 downto 0); BUFA: out std_logic_vector(2 downto 0) ); end SDRAM_CTL; architecture RTL of SDRAM_CTL is signal INITACK_REG: std_logic; signal WRACK_REG: std_logic; signal RDACK_REG: std_logic; signal RFSHACK_REG: std_logic; signal DQMN_REG: std_logic; signal CMD: std_logic_vector(3 downto 0); signal TRIRD_REG: std_logic; signal A_REG: std_logic_vector(10 downto 0); signal BUFA_REG: std_logic_vector(2 downto 0); type state_type is (Idle, Init, Write, Read, Refresh); signal CurrentState, NextState: state_type; signal SEQCNT1: integer range 0 to 15; -- Sequence Counter signal SEQCNT2: integer range 0 to 31; -- Sequence Counter begin INITACK <= INITACK_REG; WRACK <= WRACK_REG; RDACK <= RDACK_REG; RFSHACK <= RFSHACK_REG; DQM <= not DQMN_REG; CSN <= not CMD(3); RASN <= CMD(2); CASN <= CMD(1); WEN <= CMD(0); TRIRD <= TRIRD_REG; AOUT <= A_REG; BUFA <= BUFA_REG; process (CLK, RESET) begin if (RESET='1') then CurrentState <= Init; elsif (CLK'event and CLK = '1') then CurrentState <= NextState; end if; end process; process (CLK, RESET) begin if (RESET='1') then SEQCNT1 <= 0; SEQCNT2 <= 0; elsif (CLK'event and CLK = '1') then case CurrentState is when Idle => SEQCNT1 <= 0; SEQCNT2 <= 0; when Others => SEQCNT1 <= SEQCNT1 + 1; SEQCNT2 <= SEQCNT2 + 1; end case; end if; end process; process (CLK, RESET) begin if (RESET='1') then BUFA_REG <= "000"; elsif (CLK'event and CLK = '1') then case CurrentState is when Write => if (SEQCNT1 > 0) and (SEQCNT1 < 9) then BUFA_REG <= BUFA_REG + 1; end if; when Read => if SEQCNT1 > 6 then BUFA_REG <= BUFA_REG + 1; end if; when Others => BUFA_REG <= "000"; end case; end if; end process; process (CLK, RESET) begin if (RESET='1') then TRIRD_REG <= '0'; elsif (CLK'event and CLK = '1') then case CurrentState is when Read => case SEQCNT1 is when 5 => TRIRD_REG <= '1'; when others => TRIRD_REG <= TRIRD_REG; end case; when Others => TRIRD_REG <= '0'; end case; end if; end process; process (CLK, RESET) begin if (RESET='1') then INITACK_REG <= '0'; WRACK_REG <= '0'; RDACK_REG <= '0'; RFSHACK_REG <= '0'; elsif (CLK'event and CLK = '1') then case CurrentState is when Init => case SEQCNT1 is when 0 => INITACK_REG <= '1'; when others => INITACK_REG <= '0'; end case; when Write => case SEQCNT1 is when 0 => WRACK_REG <= '1'; when others => WRACK_REG <= '0'; end case; when Read => case SEQCNT1 is when 0 => RDACK_REG <= '1'; when others => RDACK_REG <= '0'; end case; when Refresh => case SEQCNT1 is when 0 => RFSHACK_REG <= '1'; when others => RFSHACK_REG <= '0'; end case; when Others => INITACK_REG <= '0'; WRACK_REG <= '0'; RDACK_REG <= '0'; RFSHACK_REG <= '0'; end case; end if; end process; process (CLK, RESET) begin if (RESET='1') then DQMN_REG <= '0'; CMD <= "0111"; -- DESL NextState <= Init; elsif (CLK'event and CLK = '1') then case CurrentState is when Idle => CMD <= "0111"; -- DESL if (INITCMD='1') then NextState <= Init; elsif (WRCMD='1') then NextState <= Write; elsif (RDCMD='1') then NextState <= Read; elsif (RFSHCMD='1') then NextState <= Refresh; end if; when Init => case SEQCNT2 is when 1 => CMD <= "1010"; -- PALL A_REG <= "10000000000"; when 4 => CMD <= "1001"; -- REF when 15 => CMD <= "1001"; -- REF when 26 => CMD <= "1000"; -- MRS A_REG <= "00000110011"; -- CAS Latency=3 Burst Length=8 when 28 => CMD <= "0111"; -- DESL DQMN_REG <= '1'; NextState <= Idle; when others => CMD <= "0111"; -- DESL end case; when Write => case SEQCNT1 is when 0 => CMD <= "1011"; -- ACT A_REG <= "000000" & AH; -- Row Address when 3 => CMD <= "1100"; -- WRITA A_REG <= "100" & AL & "000"; -- Auto Precharge & Column Address when 12 => CMD <= "0111"; -- DESL NextState <= Idle; when others => CMD <= "0111"; -- DESL end case; when Read => case SEQCNT1 is when 0 => CMD <= "1011"; -- ACT A_REG <= "000000" & AH; -- Row Address when 3 => CMD <= "1101"; -- READA A_REG <= "100" & AL & "000"; -- Auto Precharge & Column Address when 13 => CMD <= "0111"; -- DESL NextState <= Idle; when others => CMD <= "0111"; -- DESL end case; when Refresh => case SEQCNT1 is when 0 => CMD <= "1001"; -- Auto Refresh when 12 => CMD <= "0111"; -- DESL NextState <= Idle; when others => CMD <= "0111"; -- DESL end case; when others => CMD <= "0111"; -- DESL NextState <= Idle; end case; end if; end process; end RTL;