summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames <james.mckenzie@citrix.com>2013-10-14 11:43:01 +0100
committerJames <james.mckenzie@citrix.com>2013-10-14 11:43:01 +0100
commitbbcf3c7f967fd1f63225991cf945644547115f10 (patch)
tree8adcfa7395ecbb0d7f0bb42aff19f5a1c2ccf6e4
parent7d5f96d2e6dd0118226d98b824125d30f0d6e7f3 (diff)
downloadsdram-bbcf3c7f967fd1f63225991cf945644547115f10.tar.gz
sdram-bbcf3c7f967fd1f63225991cf945644547115f10.tar.bz2
sdram-bbcf3c7f967fd1f63225991cf945644547115f10.zip
pre-tidy
-rw-r--r--sdram_ctrl.vhd257
1 files 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;