summaryrefslogtreecommitdiffstats
path: root/sdram_ctrl.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'sdram_ctrl.vhd')
-rw-r--r--sdram_ctrl.vhd213
1 files changed, 211 insertions, 2 deletions
diff --git a/sdram_ctrl.vhd b/sdram_ctrl.vhd
index 1c93b13..3342726 100644
--- a/sdram_ctrl.vhd
+++ b/sdram_ctrl.vhd
@@ -5,7 +5,7 @@ use IEEE.NUMERIC_STD.ALL;
entity sdram_ctrl is
port
(
- clock_50 : in std_logic;
+ clock_100 : in std_logic;
reset_n : in std_logic;
b_cs_n : in std_logic;
@@ -36,10 +36,219 @@ end entity;
architecture rtl of sdram_ctrl is
+signal clock : std_logic;
+
+
+signal ack_refresh_request : std_logic;
+signal refresh_request : std_logic;
+subtype uint13_t is integer range 0 to 8191;
+signal refresh_counter : uint13_t;
+signal init_done : std_logic;
+
+
+signal i_addr : std_logic_vector(12 downto 0);
+signal i_cmd : std_logic_vector(3 downto 0);
+subtype uint4_t is integer range 0 to 15;
+signal i_count : uint4_t;
+subtype uint3_t is integer range 0 to 7;
+signal i_next : uint3_t;
+signal i_refs : uint3_t;
+signal i_state :uint3_t;
+
+constant I_ST_RESET_WAIT : uint3_t:=0;
+constant I_ST_PRECHARGE : uint3_t :=1;
+constant I_ST_REFRESH : uint3_t :=2;
+constant I_ST_WAIT_COUNT : uint3_t :=3;
+constant I_ST_SET_MODE : uint3_t :=4;
+constant I_ST_DONE : uint3_t :=5;
+
+
+-- CS_N RAS_N CAS_N WE_N
+
+constant CMD_IGN : std_logic_vector(3 downto 0 ):="1111";
+constant CMD_NOP : std_logic_vector(3 downto 0 ):="0111";
+constant CMD_READ : std_logic_vector(3 downto 0 ):="0101";
+constant CMD_WRIT : std_logic_vector(3 downto 0 ):="0100";
+constant CMD_ACTV : std_logic_vector(3 downto 0 ):="0011";
+constant CMD_PRE : std_logic_vector(3 downto 0 ):="0010";
+constant CMD_REF : std_logic_vector(3 downto 0 ):="0001";
+constant CMD_MRS : std_logic_vector(3 downto 0 ):="0000";
+
+signal m_state : std_logic_vector(8 downto 0);
+
+
+function active_high(constant val : in boolean) return std_logic is begin
+ if val then
+ return '1';
+ else
+ return '0';
+ end if;
+end function active_high;
+
begin
-sdram_clk <=clock_50;
+clock<=clock_100;
+
+refresh_counter_process: process(reset_n,clock) begin
+ if reset_n = '0' then
+ refresh_counter <= 8000;
+ elsif rising_edge(clock) then
+ if refresh_counter = 0 then
+ refresh_counter <= 624;
+ else
+ refresh_counter <= refresh_counter - 1;
+ end if;
+ end if;
+end process;
+
+
+refresh_request_process: process(reset_n,clock,refresh_counter,refresh_request,init_done,ack_refresh_request) begin
+ if reset_n = '0' then
+ refresh_request <= '0';
+ elsif rising_edge(clock) then
+ refresh_request <= (active_high(refresh_counter = 0) or refresh_request) and init_done and not ack_refresh_request;
+ end if;
+end process;
+
+
+init_done_process: process (reset_n,clock,i_state) begin
+ if reset_n = '0' then
+ init_done <= '0';
+ elsif rising_edge(clock) then
+ init_done <= init_done or active_high(i_state = I_ST_DONE );
+ end if;
+end process;
+
+init_fsm: process (reset_n,clock,i_state,i_count,i_next,refresh_counter) begin
+ if reset_n = '0' then
+ i_state <= I_ST_RESET_WAIT;
+ i_next <= I_ST_RESET_WAIT;
+ i_cmd <= CMD_IGN;
+ i_addr <= (others => '1');
+ i_count <= 0;
+ elsif rising_edge(clock) then
+
+ if i_state = I_ST_RESET_WAIT then
+ -- after reset wait until the refresh_counter ticks over for RAM to stabalize
+ i_cmd <= CMD_IGN;
+ i_refs <= 0;
+ if refresh_counter=0 then
+ i_state <= I_ST_PRECHARGE;
+ end if;
+ elsif i_state = I_ST_PRECHARGE then
+ -- precharge all banks, wait one clock, then go to refresh
+ i_cmd <=CMD_PRE;
+ i_state <= I_ST_WAIT_COUNT;
+ i_count <= 1;
+ i_next <= I_ST_REFRESH;
+ elsif i_state =I_ST_REFRESH then
+ -- repeat 7 times { refresh, wait 5 counts }
+ i_cmd <=CMD_REF;
+ i_refs <= i_refs + 1;
+
+ i_state <= I_ST_WAIT_COUNT;
+ i_count <= 5;
+
+ if i_refs = 7 then
+ i_next <= I_ST_SET_MODE;
+ else
+ i_next <= I_ST_REFRESH;
+ end if;
+ elsif i_state = I_ST_WAIT_COUNT then
+ -- wait i_count ticks then goto state i_next
+ i_cmd <= CMD_NOP;
+ if (i_count > 1) then
+ i_count <= i_count -1;
+ else
+ i_state <= i_next;
+ end if;
+
+ elsif i_state=I_ST_SET_MODE then
+ -- set mode, wait 3 ticks then goto done
+ i_cmd <= CMD_MRS;
+
+ -- reserverd 000
+ -- opcode burst read/write 0
+ -- reserved 00
+ -- cas latency 3 011
+ -- sequential burst 0
+ -- burst length 1 000
+
+ i_addr <= "0000000110000";
+ i_count <= 3;
+ i_next <= I_ST_DONE;
+
+ elsif i_state=I_ST_DONE then
+ i_state <= I_ST_DONE;
+ else
+ i_state <= I_ST_RESET_WAIT;
+ end if;
+ end if;
+end process;
+
+main_fsm: process (reset_n,clock,m_state,refresh_counter) begin
+
+end process;
+
+if reset_n ='0' then
+m_state <= M_ST_1;
+m_next <= M_ST_1;
+m_cmd <= CMD_IGN;
+m_bank <= "00";
+m_addr <= "0000000000000";
+m_data <= "0000000000000000";
+m_dqm <= "00";
+m_count <= 0;
+ack_refresh_request <= 0;
+f_pop <= 0;
+oe <= 0;
+elsif rising_edge(clock) then
+if m_state = M_ST_1 then
+ if active_high(init_done) then
+ if active_high(refresh_request) then
+ m_cmd <= CMD_NOP;
+ else
+ m_vmd <= CMD_IGN;
+ end if;
+ ack_refresh_request <='1';
+
+ if active_high(refresh_request) then
+ m_state <= M_ST_7;
+ m_next <= M_ST_8;
+ m_count <= 1;
+ active_cs_n <= '1';
+ elsif (not active_high(f_empty)) then
+ f_pop <= '1';
+ active_cs_n <= f_cs_n;
+ active_rnw <= f_rnw;
+ active_addr <= f_addr;
+ active_data <= f_data;
+ m_state <= M_ST_2;
+ end if;
+ else
+ m_addr <= i_addr;
+ m_state <= M_ST_1;
+ m_next <= M_ST_1;
+ m_cmd <= i_cmd;
+ end if;
+elsif m_state = M_ST_2 then
+ m_state <= M_ST_3;
+ m_cmd(3) <= csn_decode;
+ m_cmd(2 downto 0)="111";
+ m_bank <= active_bank;
+ m_addr <= active_addr(22 downto 10);
+ m_data <= active_data;
+ m_dqm <= active_dqm;
+ m_count <=2;
+ if (active_high(active_rnw)) then
+ m_next <=M_ST_4;
+ else
+ m_next <=M_ST_5;
+ end if;
+elsif m_state = M_ST_3
+
+
end;