From bbcf3c7f967fd1f63225991cf945644547115f10 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 14 Oct 2013 11:43:01 +0100 Subject: pre-tidy --- sdram_ctrl.vhd | 257 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 202 insertions(+), 55 deletions(-) diff --git a/sdram_ctrl.vhd b/sdram_ctrl.vhd index 3342726..457364a 100644 --- a/sdram_ctrl.vhd +++ b/sdram_ctrl.vhd @@ -39,8 +39,8 @@ architecture rtl of sdram_ctrl is signal clock : std_logic; -signal ack_refresh_request : std_logic; -signal refresh_request : std_logic; +signal ack_need_refresh : std_logic; +signal need_refresh : std_logic; subtype uint13_t is integer range 0 to 8191; signal refresh_counter : uint13_t; signal init_done : std_logic; @@ -63,29 +63,53 @@ constant I_ST_SET_MODE : uint3_t :=4; constant I_ST_DONE : uint3_t :=5; --- CS_N RAS_N CAS_N WE_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"; +constant CMD_NOP : std_logic_vector(2 downto 0 ):="111"; +constant CMD_READ : std_logic_vector(2 downto 0 ):="101"; +constant CMD_WRIT : std_logic_vector(2 downto 0 ):="100"; +constant CMD_ACTV : std_logic_vector(2 downto 0 ):="011"; +constant CMD_PRE : std_logic_vector(2 downto 0 ):="010"; +constant CMD_REF : std_logic_vector(2 downto 0 ):="001"; +constant CMD_MRS : std_logic_vector(2 downto 0 ):="000"; signal m_state : std_logic_vector(8 downto 0); +constant M_ST_IDLE : std_logic_vector(8 downto 0 ):="000000001"; +constant M_ST_RAS : std_logic_vector(8 downto 0 ):="000000010"; +constant M_ST_NOP_COUNT : std_logic_vector(8 downto 0 ):="000000100"; +constant M_ST_READ : std_logic_vector(8 downto 0 ):="000001000"; +constant M_ST_WRITE : std_logic_vector(8 downto 0 ):="000010000"; +constant M_ST_WAIT_FOR_PRECHARGE : std_logic_vector(8 downto 0 ):="000100000"; +constant M_ST_PRECHARGE : std_logic_vector(8 downto 0 ):="001000000"; +constant M_ST_REFRESH : std_logic_vector(8 downto 0 ):="010000000"; +constant M_ST_FETCH_NEXT : std_logic_vector(8 downto 0 ):="100000000"; + + + 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; +end function; + +function ternary( + constant val : in boolean, + constant if_true : in std_logic, + constant if_false : in std_logic +) return std_logic is begin + if val then + return if_true; + else + return if_false; + end if; +end function; + begin clock<=clock_100; @@ -103,11 +127,11 @@ refresh_counter_process: process(reset_n,clock) begin end process; -refresh_request_process: process(reset_n,clock,refresh_counter,refresh_request,init_done,ack_refresh_request) begin +need_refresh_process: process(reset_n,clock,refresh_counter,need_refresh,init_done,ack_need_refresh) begin if reset_n = '0' then - refresh_request <= '0'; + need_refresh <= '0'; elsif rising_edge(clock) then - refresh_request <= (active_high(refresh_counter = 0) or refresh_request) and init_done and not ack_refresh_request; + need_refresh <= (active_high(refresh_counter = 0) or need_refresh) and init_done and not ack_need_refresh; end if; end process; @@ -124,26 +148,30 @@ 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_cs_n <=CS_N_NONE; + i_cmd <= CMD_NOP; 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_cs_n <=CS_N_NONE; + i_cmd <= CMD_NOP; 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_cs_n <=CS_N_ALL; 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_cs_n <=CS_N_ALL; i_cmd <=CMD_REF; i_refs <= i_refs + 1; @@ -157,6 +185,7 @@ init_fsm: process (reset_n,clock,i_state,i_count,i_next,refresh_counter) begin end if; elsif i_state = I_ST_WAIT_COUNT then -- wait i_count ticks then goto state i_next + i_cs_n <=CS_N_ALL; i_cmd <= CMD_NOP; if (i_count > 1) then i_count <= i_count -1; @@ -166,6 +195,7 @@ init_fsm: process (reset_n,clock,i_state,i_count,i_next,refresh_counter) begin elsif i_state=I_ST_SET_MODE then -- set mode, wait 3 ticks then goto done + i_cs_n <=CS_N_ALL; i_cmd <= CMD_MRS; -- reserverd 000 @@ -192,62 +222,179 @@ 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_state <= M_ST_WAITING_INIT; +m_next <= M_ST_WAITING_INIT; +m_cmd <= CMD_NOP; +m_cs_n <= '1'; m_bank <= "00"; m_addr <= "0000000000000"; m_data <= "0000000000000000"; m_dqm <= "00"; m_count <= 0; -ack_refresh_request <= 0; +ack_need_refresh <= 0; f_pop <= 0; oe <= 0; +bus_busy<=1; elsif rising_edge(clock) then -if m_state = M_ST_1 then +if m_state =M_ST_WAITING_INIT then + m_addr <= i_addr; + m_cmd <= i_cmd; + m_cs_n <= i_cs_n; + 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; + m_state <= M_ST_IDLE; + end if; +elsif m_state = M_ST_IDLE then + m_cmd <= CMD_NOP; + + ack_need_refresh <='0'; + + if active_high(need_refresh) then + -- If we got here needing a refresh + -- we may have come straight from a + -- read so leave CS on so we get + -- that data + + m_cs_n<=CS_N_ALL; + + -- precharge everyone (putting back + -- the open row if we did come from a read + -- or write) then refresh everyone. + + m_state <= M_ST_PRECHARGE; + m_next <= M_ST_REFRESH; + else + -- idle to all chips (CMD_IGN) + m_cs_n<=CS_N_NONE; + + -- find out if anyone wants us + if active_high(request_ready) then + active_cs_n <= request_cs_n; + active_rnw <= request_rnw; + active_addr <= request_addr; + active_data <= request_data; + active_dqm <= request_dqm; + m_state <= M_ST_RAS; + ack_request <='1'; 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"; +elsif m_state = M_ST_RAS then + -- activate the relevant ROW, wait 3 clocks, then go and do the read or write + + ack_request <='0'; + + m_cs_n <= active_cs_n; + m_cmd <= CMD_ACTV; m_bank <= active_bank; m_addr <= active_addr(22 downto 10); m_data <= active_data; - m_dqm <= active_dqm; - m_count <=2; + m_dqm <= active_dqm; + + m_state <= M_ST_NOP_COUNT; + m_count <= 2; --t 3 clocks : FIXME if (active_high(active_rnw)) then - m_next <=M_ST_4; + m_next <= M_ST_READ; + else + m_next <= M_ST_WRITE; + end if; +elsif m_state = M_ST_NOP_COUNT then + -- send nops for m_count, then go to state m_next + m_cmd <=CMD_NOP; + if m_count > 1 then + m_count <= m_count - 1; else - m_next <=M_ST_5; + m_state <= m_next; end if; -elsif m_state = M_ST_3 +elsif m_state = M_ST_READ then + ack_request <='0'; + + m_cmd <=CMD_READ; + + m_addr(13 downto 10) <= (others => '0'); + m_addr(9 downto 0) <= active_addr[8:0]; + + m_next <= M_ST_ACTIVE +elsif m_state = M_ST_WRITE then + ack_request <='0'; + + m_cmd<=CMD_WRIT; + m_addr(13 downto 10) <= (others => '0'); + m_addr(9 downto 0) <= active_addr[8:0]; + + oe <= '1'; + m_data <= active_data; + + m_state <=M_ST_ACTIVE +elsif m_state = M_ST_ACTIVE then + -- turn off drivers (we might have come from a write) + oe <= '0'; + + -- sit doing NOPS on this row until either we get a new request + -- or we need a refresh + m_cmd <= M_CMD_NOP; + + if active_high(need_refresh) then + -- the refresh will first precharge everything, so no need to precharge + -- just this row. + m_state <= M_ST_NOP_COUNT; + m_next <= M_ST_IDLE; + m_count <= 1; + elsif active_high(request_ready) then + if (active_cs_n = request_cs_n) and (active_rnw == request_rnw) and same_bank_and_row(active_addr,request_addr) then + -- this request matches our currently active row + -- we can process it + + active_addr <= request_addr; + active_data <= request_data; + active_dqm <= request_dqm; + + ack_request <='1'; + + if active_high(request_rnw) then + m_state <= M_ST_READ; + else + m_state <= M_ST_WRITE; + end if; + else + -- new request doesn't match, precharge and go to idle + m_state <= M_ST_WAIT_FOR_PRECHARGE; + m_next <= M_ST_IDLE; + end if; + end if; + +elsif m_state = M_ST_WAIT_FOR_PRECHARGE then + -- wait count then do a precharge + m_cmd <= CMD_NOP; + if m_count > 1 then + m_count <= m_count -1; + else + m_state=M_ST_PRECHARGE; + end; +elsif m_state = M_ST_PRECHARGE then + -- do a precharge, wait two clocks, then goto m_next + m_addr <= (others => '1'); + m_cmd <= CMD_PRE; + m_count = 1; + m_state <= M_ST_NOP_COUNT; +elsif m_state=M_ST_REFRESH then + -- do a refresh, wait six clocks, return to idle + + m_cmd <= CMD_REF; + m_count <=5; + m_next <=M_ST_IDLE; + m_state <= M_ST_NOP_COUNT; + + -- tell the gubbins we did the refresh + ack_need_refresh <= '1'; +else + -- shouldn't be here - crash + m_cmd <=CMD_NOP; + m_cs_n <= M_CS_NONE + oe <= '0'; +end if; + +end process; end; -- cgit v1.2.3