summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames <james.mckenzie@citrix.com>2013-10-14 14:09:47 +0100
committerJames <james.mckenzie@citrix.com>2013-10-14 14:09:47 +0100
commitb34674c513c61f426111e6d698440ec6978b7f22 (patch)
tree188df2e28f283201fc733a41bee56bdc4b7b7b11
parentd42c62b84db2da7dbaf1e17d17b12116e2e712fe (diff)
downloadsdram-b34674c513c61f426111e6d698440ec6978b7f22.tar.gz
sdram-b34674c513c61f426111e6d698440ec6978b7f22.tar.bz2
sdram-b34674c513c61f426111e6d698440ec6978b7f22.zip
finished
-rw-r--r--sdram_ctrl.vhd808
1 files changed, 461 insertions, 347 deletions
diff --git a/sdram_ctrl.vhd b/sdram_ctrl.vhd
index 55c1cae..b89ece5 100644
--- a/sdram_ctrl.vhd
+++ b/sdram_ctrl.vhd
@@ -5,42 +5,6 @@ use IEEE.NUMERIC_STD.ALL;
-- a simple dram controller (no pipelineing)
-- that looks like a slow static ram
-entity sdram_ctrl is
-port
-(
- clock_100 : in std_logic;
- reset_n : in std_logic;
-
- b_cs_n : in std_logic;
- b_rd_n : in std_logic;
- b_wr_n : in std_logic;
-
- b_wait_n : out std_logic;
-
- b_addr : in std_logic_vector(15 downto 0);
- b_data : inout std_logic_vector(15 downto 0);
-
-
- sdram_clk : out std_logic;
-
- sdramem_cs_n : out std_logic;
- sdram_cas_n : out std_logic;
- sdram_ras_n : out std_logic;
- sdram_we_n : out std_logic;
- sdram_cke : out std_logic;
-
- sdramem_addr : out std_logic_vector(12 downto 0);
- sdram_ba : out std_logic_vector(1 downto 0);
-
- sdram_dq : inout std_logic_vector(15 downto 0);
- sdramem_dqm : out std_logic_vector(1 downto 0)
-);
-end entity;
-
-architecture rtl of sdram_ctrl is
-
-signal clock : std_logic;
-
subtype uint3_t is integer range 0 to 7;
subtype uint4_t is integer range 0 to 15;
subtype uint13_t is integer range 0 to 8191;
@@ -50,395 +14,545 @@ subtype data_t is std_logic_vector(15 downto 0);
subtype dqm_t is std_logic_vector(1 downto 0);
--- bits in the CMD register RAS_N CAS_N WE_N
-
-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";
-
-constant CS_N_ALL : cs_n_t := "0";
-constant CS_N_NONE : cs_n_t := "1";
-
--- refresh logic
-
-signal need_refresh : std_logic;
-signal refresh_counter : uint13_t;
-
--- init logic
-
-signal init_done : std_logic;
-signal i_addr : std_logic_vector(12 downto 0);
-signal i_cs_n: cs_n_t;
-signal i_cmd : std_logic_vector(2 downto 0);
-signal i_count : uint4_t;
-signal i_next : uint3_t;
-signal i_refs : uint3_t;
-
--- init fsm
-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;
-
-
--- memory interface wires
-signal mem_cs_n : cs_n_t;
-signal mem_bank : std_logic_vector(1 downto 0);
-signal mem_cmd : std_logic_vector(2 downto 0);
-signal mem_addr : std_logic_vector(12 downto 0);
-signal mem_data : data_t;
-signal mem_dqm : dqm_t;
-
--- main logic
-signal ack_refresh : std_logic;
-signal ack_request : std_logic;
-signal mem_oe: std_logic;
-signal m_count: uint3_t;
-
-signal active_cs_n : cs_n_t;
-signal active_addr : addr_t;
-signal active_data : data_t;
-signal active_rnw : std_logic;
-signal active_dqm : dqm_t;
-
--- main fsm
-signal m_state : std_logic_vector(9 downto 0);
-signal m_next : std_logic_vector(9 downto 0);
-
-constant M_ST_WAITING_INIT : std_logic_vector(9 downto 0 ):="0000000001";
-constant M_ST_IDLE : std_logic_vector(9 downto 0 ):="0000000010";
-constant M_ST_RAS : std_logic_vector(9 downto 0 ):="0000000100";
-constant M_ST_NOP_COUNT : std_logic_vector(9 downto 0 ):="0000001000";
-constant M_ST_READ : std_logic_vector(9 downto 0 ):="0000010000";
-constant M_ST_WRITE : std_logic_vector(9 downto 0 ):="0000100000";
-constant M_ST_ACTIVE : std_logic_vector(9 downto 0 ):="0001000000";
-constant M_ST_WAIT_FOR_PRECHARGE : std_logic_vector(9 downto 0 ):="0010000000";
-constant M_ST_PRECHARGE : std_logic_vector(9 downto 0 ):="0100000000";
-constant M_ST_REFRESH : std_logic_vector(9 downto 0 ):="1000000000";
-
--- bus logic
-signal request_ready: std_logic;
-signal request_cs_n : cs_n_t;
-signal request_addr : addr_t;
-signal request_data : data_t;
-signal request_rnw : std_logic;
-signal request_dqm : dqm_t;
-
-
--- convert boolean to active high logic
-function b2l_h(constant val : in boolean) return std_logic is begin
- if val then
- return '1';
- else
- return '0';
- end if;
-end function;
+entity sdram_ctrl is
+ port
+ (
+ clock_100 : in std_logic;
+ reset_n : in std_logic;
+ bus_cs_n : in std_logic;
+ bus_rd_n : in std_logic;
+ bus_wr_n : in std_logic;
--- convert active high logic to boolean value
-function l2b_h(constant val : in std_logic) return boolean is begin
- return val='1';
-end function;
+ bus_wait_n : out std_logic;
-function same_bank_and_row(
- constant a1: in addr_t;
- constant a2: in addr_t
-) return boolean is begin
- return a1(23 downto 9) = a2(23 downto 9);
-end function;
+ bus_addr : in addr_t;
+ bus_data : inout data_t;
-begin
+ sdram_clk : out std_logic;
+ sdram_cke : out std_logic;
-clock<=clock_100;
+ sdram_cs_n : out std_logic;
-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;
+ sdram_cas_n : out std_logic;
+ sdram_ras_n : out std_logic;
+ sdram_we_n : out std_logic;
+ sdram_addr : out std_logic_vector(12 downto 0);
+ sdram_ba : out std_logic_vector(1 downto 0);
-need_refresh_process: process(reset_n,clock,refresh_counter,need_refresh,init_done,ack_refresh) begin
- if reset_n = '0' then
- need_refresh <= '0';
- elsif rising_edge(clock) then
- need_refresh <= (b2l_h(refresh_counter = 0) or need_refresh) and init_done and not ack_refresh;
- end if;
-end process;
+ sdram_dq : inout data_t;
+ sdram_dqm : out dqm_t;
+ );
+end entity;
-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 b2l_h(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_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_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;
-
- 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_cs_n <=CS_N_ALL;
- i_cmd <= CMD_NOP;
- if (i_count > 1) then
- i_count <= i_count -1;
- else
- i_state <= i_next;
- end if;
+architecture rtl of sdram_ctrl is
- 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
- -- 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;
+ signal clock : std_logic;
+
+ -- bits in the MEM_CMD register RAS_N CAS_N WE_N
+
+ constant MEM_CMD_NOP : std_logic_vector(2 downto 0 ):="111";
+ constant MEM_CMD_READ : std_logic_vector(2 downto 0 ):="101";
+ constant MEM_CMD_WRIT : std_logic_vector(2 downto 0 ):="100";
+ constant MEM_CMD_ACTV : std_logic_vector(2 downto 0 ):="011";
+ constant MEM_CMD_PRE : std_logic_vector(2 downto 0 ):="010";
+ constant MEM_CMD_REF : std_logic_vector(2 downto 0 ):="001";
+ constant MEM_CMD_MRS : std_logic_vector(2 downto 0 ):="000";
+
+ constant MEM_CS_N_ALL : cs_n_t := "0";
+ constant MEM_CS_N_NONE : cs_n_t := "1";
+
+ -- refresh logic
+
+ signal need_refresh : std_logic;
+ signal refresh_counter : uint13_t;
+
+ -- init logic
+
+ signal init_done : std_logic;
+ signal i_addr : std_logic_vector(12 downto 0);
+ signal i_cs_n: cs_n_t;
+ signal i_cmd : std_logic_vector(2 downto 0);
+ signal i_count : uint4_t;
+ signal i_next : uint3_t;
+ signal i_refs : uint3_t;
+
+ -- init fsm
+ 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;
+
+ -- memory interface wires
+ signal mem_cs_n : cs_n_t;
+ signal mem_bank : std_logic_vector(1 downto 0);
+ signal mem_cmd : std_logic_vector(2 downto 0);
+ signal mem_addr : std_logic_vector(12 downto 0);
+ signal mem_data_out : data_t;
+ signal mem_data_in : data_t;
+ signal mem_dqm : dqm_t;
+ signal mem_oe: std_logic;
+
+ -- main logic
+ signal ack_refresh : std_logic;
+ signal ack_request : std_logic;
+ signal m_count: uint3_t;
+
+ signal active_cs_n : cs_n_t;
+ signal active_addr : addr_t;
+ signal active_data : data_t;
+ signal active_rnw : std_logic;
+ signal active_dqm : dqm_t;
+
+ -- main fsm
+ signal m_state : std_logic_vector(9 downto 0);
+ signal m_next : std_logic_vector(9 downto 0);
+
+ constant M_ST_WAITING_INIT : std_logic_vector(9 downto 0 ):="0000000001";
+ constant M_ST_IDLE : std_logic_vector(9 downto 0 ):="0000000010";
+ constant M_ST_RAS : std_logic_vector(9 downto 0 ):="0000000100";
+ constant M_ST_NOP_COUNT : std_logic_vector(9 downto 0 ):="0000001000";
+ constant M_ST_READ : std_logic_vector(9 downto 0 ):="0000010000";
+ constant M_ST_WRITE : std_logic_vector(9 downto 0 ):="0000100000";
+ constant M_ST_ACTIVE : std_logic_vector(9 downto 0 ):="0001000000";
+ constant M_ST_WAIT_FOR_PRECHARGE : std_logic_vector(9 downto 0 ):="0010000000";
+ constant M_ST_PRECHARGE : std_logic_vector(9 downto 0 ):="0100000000";
+ constant M_ST_REFRESH : std_logic_vector(9 downto 0 ):="1000000000";
+
+
+ -- request logic
+ signal request_pending: std_logic;
+ signal request_cs_n : cs_n_t;
+ signal request_addr : addr_t;
+ signal request_data : data_t;
+ signal request_rnw : std_logic;
+ signal request_dqm : dqm_t;
+
+ -- read state logic
+ signal r_data_valid: std_logic_vector(2 downto 0);
+
+ -- bus logic
+ signal request_post: std_logic;
+
+ -- bus fsm
+ signal b_state : std_logic_vector(4 downto 0);
+
+ constant B_ST_WAIT_CS_LOW : std_logic_vector(4 downto 0):="00001";
+ constant B_ST_LODGE_REQUEST : std_logic_vector(4 downto 0):="00010";
+ constant B_ST_WAIT_ACK : std_logic_vector(4 downto 0):="00100";
+ constant B_ST_WAIT_DATA : std_logic_vector(4 downto 0):="01000";
+ constant B_ST_WAIT_CS_HIGH : std_logic_vector(4 downto 0):="10000";
+
+ -- convert boolean to active high logic
+ function b2l_ah(constant val : in boolean) return std_logic is begin
+ if val then
+ return '1';
+ else
+ return '0';
+ end if;
+ end function;
+
+
+ -- convert active high logic to boolean value
+ function l2b_ah(constant val : in std_logic) return boolean is begin
+ return val='1';
+ end function;
+
+ function l2b_al(constant val : in std_logic) return boolean is begin
+ return val='0';
+ end function;
+
+
+ function same_bank_and_row ( constant a1: in addr_t; constant a2: in addr_t ) return boolean is begin
+ return a1(23 downto 9) = a2(23 downto 9);
+ end function;
+
+begin
+
+ clock<=clock_100;
+
+ refresh_counter_process: process(reset_n,clock) begin
+ if l2b_al(reset_n) 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;
+
+
+ need_refresh_process: process(reset_n,clock,refresh_counter,need_refresh,init_done,ack_refresh) begin
+ if l2b_al(reset_n) then
+ need_refresh <= '0';
+ elsif rising_edge(clock) then
+ need_refresh <= (b2l_ah(refresh_counter = 0) or need_refresh) and init_done and not ack_refresh;
+ end if;
+ end process;
+
+ request_pending_process: process(reset_n, clock, post_request, request_pending,ack_request) begin
+ if l2b_al(reset_n) then
+ request_pending <= '0';
+ elsif rising_edge(clock) then
+ request_pending <= post_request or (request_pending and not ack_request);
+ end if;
+ end process;
+
+
+ init_done_process: process (reset_n,clock,i_state) begin
+ if l2b_al(reset_n) then
+ init_done <= '0';
+ elsif rising_edge(clock) then
+ init_done <= init_done or b2l_ah(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 l2b_al(reset_n) then
+ i_state <= I_ST_RESET_WAIT;
+ i_next <= I_ST_RESET_WAIT;
+ i_cs_n <=MEM_CS_N_NONE;
+ i_cmd <= MEM_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_cs_n <=MEM_CS_N_NONE;
+ i_cmd <= MEM_CMD_NOP;
+ i_refs <= 0;
+ if refresh_counter=0 then
+ i_state <= I_ST_PRECHARGE;
end if;
-end process;
-
-main_fsm: process (reset_n,clock,m_state,need_refresh,request_ready,request_addr,request_data,request_cs_n,request_rnw,request_dqm) begin
-
-if reset_n ='0' then
-m_state <= M_ST_WAITING_INIT;
-m_next <= M_ST_WAITING_INIT;
-mem_cmd <= CMD_NOP;
-mem_cs_n <= CS_N_NONE;
-mem_bank <= (others => '0');
-mem_addr <= (others => '0');
-mem_data <= (others => '0');
-mem_dqm <= (others => '0');
-m_count <= 0;
-ack_refresh <= '0';
-ack_request <= '0';
-mem_oe <= '0';
-elsif rising_edge(clock) then
-if m_state =M_ST_WAITING_INIT then
+ elsif i_state = I_ST_PRECHARGE then
+ -- precharge all banks, wait one clock, then go to refresh
+ i_cs_n <=MEM_CS_N_ALL;
+ i_cmd <=MEM_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 <=MEM_CS_N_ALL;
+ i_cmd <=MEM_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_cs_n <=MEM_CS_N_ALL;
+ i_cmd <= MEM_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_cs_n <=MEM_CS_N_ALL;
+ i_cmd <= MEM_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,need_refresh,request_pending,request_addr,request_data,request_cs_n,request_rnw,request_dqm) begin
+
+ if reset_n ='0' then
+ m_state <= M_ST_WAITING_INIT;
+ m_next <= M_ST_WAITING_INIT;
+ mem_cmd <= MEM_CMD_NOP;
+ mem_cs_n <= MEM_CS_N_NONE;
+ mem_bank <= (others => '0');
+ mem_addr <= (others => '0');
+ mem_data_out <= (others => '0');
+ mem_dqm <= (others => '0');
+ m_count <= 0;
+ ack_refresh <= '0';
+ ack_request <= '0';
+ mem_oe <= '0';
+ elsif rising_edge(clock) then
+ if m_state =M_ST_WAITING_INIT then
mem_addr <= i_addr;
mem_cmd <= i_cmd;
mem_cs_n <= i_cs_n;
-
- if l2b_h(init_done) then
- m_state <= M_ST_IDLE;
+
+ if l2b_ah(init_done) then
+ m_state <= M_ST_IDLE;
end if;
-elsif m_state = M_ST_IDLE then
- mem_cmd <= CMD_NOP;
+ elsif m_state = M_ST_IDLE then
+ mem_cmd <= MEM_CMD_NOP;
ack_refresh <='0';
- if l2b_h(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
+ if l2b_ah(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
- mem_cs_n<=CS_N_ALL;
+ mem_cs_n<=MEM_CS_N_ALL;
- -- precharge everyone (putting back
- -- the open row if we did come from a read
- -- or write) then refresh everyone.
+ -- 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;
+ m_state <= M_ST_PRECHARGE;
+ m_next <= M_ST_REFRESH;
else
- -- idle to all chips (CMD_IGN)
- mem_cs_n<=CS_N_NONE;
-
- -- find out if anyone wants us
- if l2b_h(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;
+ -- idle to all chips (MEM_CMD_IGN)
+ mem_cs_n<=MEM_CS_N_NONE;
+
+ -- find out if anyone wants us
+ if l2b_ah(request_pending) 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;
end if;
-elsif m_state = M_ST_RAS then
- -- activate the relevant ROW, wait 3 clocks, then go and do the read or write
+ 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';
mem_cs_n <= active_cs_n;
- mem_cmd <= CMD_ACTV;
+ mem_cmd <= MEM_CMD_ACTV;
mem_bank(1) <= active_addr(23);
mem_bank(0) <= active_addr(9);
mem_addr <= active_addr(22 downto 10);
- mem_data <= active_data;
+ mem_data_out <= active_data;
mem_dqm <= active_dqm;
m_state <= M_ST_NOP_COUNT;
m_count <= 2; --t 3 clocks : FIXME
- if l2b_h(active_rnw) then
- m_next <= M_ST_READ;
+ if l2b_ah(active_rnw) then
+ m_next <= M_ST_READ;
else
- m_next <= M_ST_WRITE;
+ 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
- mem_cmd <=CMD_NOP;
+ elsif m_state = M_ST_NOP_COUNT then
+ -- send nops for m_count, then go to state m_next
+ mem_cmd <=MEM_CMD_NOP;
if m_count > 1 then
- m_count <= m_count - 1;
+ m_count <= m_count - 1;
else
- m_state <= m_next;
+ m_state <= m_next;
end if;
-elsif m_state = M_ST_READ then
+ elsif m_state = M_ST_READ then
ack_request <='0';
- mem_cmd <=CMD_READ;
+ mem_cmd <=MEM_CMD_READ;
mem_addr(12 downto 9) <= (others => '0');
mem_addr(8 downto 0) <= active_addr(8 downto 0);
m_next <= M_ST_ACTIVE;
-elsif m_state = M_ST_WRITE then
+ elsif m_state = M_ST_WRITE then
ack_request <='0';
- mem_cmd<=CMD_WRIT;
+ mem_cmd<=MEM_CMD_WRIT;
mem_addr(12 downto 9) <= (others => '0');
mem_addr(8 downto 0) <= active_addr(8 downto 0);
mem_oe <= '1';
- mem_data <= active_data;
+ mem_data_out <= active_data;
m_state <=M_ST_ACTIVE;
-elsif m_state = M_ST_ACTIVE then
- -- turn off drivers (we might have come from a write)
+ elsif m_state = M_ST_ACTIVE then
+ -- turn off drivers (we might have come from a write)
mem_oe <= '0';
- -- sit doing NOPS on this row until either we get a new request
- -- or we need a refresh
- mem_cmd <= M_CMD_NOP;
-
- if l2b_h(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 l2b_h(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 l2b_h(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;
+ -- sit doing NOPS on this row until either we get a new request
+ -- or we need a refresh
+ mem_cmd <= MEM_CMD_NOP;
+
+ if l2b_ah(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 l2b_ah(request_pending) 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 l2b_ah(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
- mem_cmd <= CMD_NOP;
+ elsif m_state = M_ST_WAIT_FOR_PRECHARGE then
+ -- wait count then do a precharge
+ mem_cmd <= MEM_CMD_NOP;
if m_count > 1 then
- m_count <= m_count -1;
+ m_count <= m_count -1;
else
- m_state<=M_ST_PRECHARGE;
+ m_state<=M_ST_PRECHARGE;
end if;
-elsif m_state = M_ST_PRECHARGE then
+ elsif m_state = M_ST_PRECHARGE then
-- do a precharge, wait two clocks, then goto m_next
mem_addr <= (others => '1');
- mem_cmd <= CMD_PRE;
+ mem_cmd <= MEM_CMD_PRE;
m_count <= 1;
m_state <= M_ST_NOP_COUNT;
-elsif m_state=M_ST_REFRESH then
+ elsif m_state=M_ST_REFRESH then
-- do a refresh, wait six clocks, return to idle
- mem_cmd <= CMD_REF;
+ mem_cmd <= MEM_CMD_REF;
m_count <=5;
m_next <=M_ST_IDLE;
m_state <= M_ST_NOP_COUNT;
-- tell the gubbins we did the refresh
ack_refresh <= '1';
-else
+ else
-- shouldn't be here - crash
- mem_cmd <=CMD_NOP;
- mem_cs_n <= M_CS_NONE;
+ mem_cmd <=MEM_CMD_NOP;
+ mem_cs_n <= MEM_CS_N_NONE;
mem_oe <= '0';
-end if;
-end if;
+ end if;
+ end if;
+
+ end process;
+
+ -- drive the memory lines
+ sdram_clk <= clock;
+ sdram_cke <= '1';
+ sdram_cs_n <= mem_cs_n(0);
+ sdram_ras_n <= mem_cmd(2);
+ sdram_cas_n <= mem_cmd(1);
+ sdram_we_n <= mem_cmd(0);
+ sdram_addr <= mem_addr;
+ sdram_ba <= mem_bank;
+
+ if l2b_ah(mem_oe) then
+ sdram_dq <= mem_data_out;
+ else
+ sdram_dq <= (others => 'Z' );
+ end if;
+ mem_data_in <= sdram_dq;
+
+ sdram_dqm <= mem_dqm;
+
+ -- a shift register to track the reads
+ read_process: process(reset_n,clock, mem_cmd) begin
+ if l2b_al(reset_n) then
+ r_data_valid <= (others => '0');
+ elsif rising_edge(clock) then
+ r_data_valid(1 downto 0)=r_data_valid(2 downto 1);
+ r_data_valid(2) <= b2l_ah(mem_cmd = MEM_CMD_READ);
+ end if;
+ end process;
+
-end process;
+ bus: process (reset_n,clock,b_state,bus_cs_n,bus_rnw,bus_addr,bus_data,ack_request,r_data_valid) begin
+ if l2b_al(reset_n) then
+ request_pending <= '0';
+ bus_data_out <= (others => '0');
+ request_data <= (others => '0');
+ request_addr <= (others => '0');
+ request_rnw <= '0';
+ request_cs_n <= CS_N_NONE;
+ request_dqm <= "00";
+ b_state <= B_ST_WAIT_CS_N_LOW;
+ elsif rising_edge(clock) then
+ if b_state = B_ST_WAIT_CS_N_LOW then
+ if l2b_al(bus_cs_n) then
+ -- new request ship it to the main state machine
+ post_request <='1';
+ request_addr <= bus_addr;
+ request_rnw <= bus_rnw;
+ request_data <= bus_data_in;
+ request_rnw <= '0';
+
+ -- send to first chip and all bytes
+ request_cs_n <= "0" (others => '1');
+ request_dqm <= "00";
+
+ bus_wait_n <= '0';
+ b_state <= B_ST_LODGE_REQUEST;
+ end if;
+ elsif b_state =B_ST_LODGE_REQUEST then
+ post_request <='0';
+ b_state <= B_ST_WAIT_ACK;
+ elsif b_state =B_ST_WAIT_ACK then
+ if not l2b_ah(request_pending) then
+ -- the logic has pushed the request to the ram
+ if l2b_al(request_rnw) then
+ -- if it's a write we're all done
+ bus_wait_n <= '1';
+ b_state <= B_ST_WAIT_CS_N_HIGH;
+ else
+ -- if it's a read we have to wait for the data
+ b_state <= B_ST_WAIT_DATA;
+ end if;
+ end if;
+ elsif b_state = B_ST_WAIT_DATA then
+ if l2b_ah(r_data_valid(0)) then
+ bus_data_out <= mem_data_in;
+ bus_wait_n <= '1';
+ b_state <= B_ST_WAIT_CS_N_HIGH;
+ end if;
+ elsif b_state = B_ST_WAIT_CS_N_HIGH:
+ if not l2b_al(bus_cs_n) then
+ b_state <=B_ST_WAIT_CS_N_LOW;
+ end if;
+ else
+ b_state <=B_ST_WAIT_CS_N_LOW;
+ end if;
+ end if;
+ end process;
end;