library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity memory_controller is port ( -- clocks sys_clk0: in std_logic; sys_clk90: in std_logic; sys_clkdiv0: in std_logic; sys_clk_locked: in std_logic; sys_clk_idelay: in std_logic; sys_reset: in std_logic; -- read and write requests request_addr: in std_logic_vector(27 downto 0); -- 256 MiB, no CS (SR) request_type: in std_logic; -- read (1) or write (0) request_data: in std_logic_vector(255 downto 0); request_mask: in std_logic_vector(31 downto 0); request_valid: in std_logic; request_ready: out std_logic; -- read responses response_data: out std_logic_vector(255 downto 0); response_valid: out std_logic; -- only asserted for one cycle, no ready -- physical ddr2 interface ddr2_dq: inout std_logic_vector(63 downto 0); ddr2_a: out std_logic_vector(12 downto 0); ddr2_ba: out std_logic_vector(1 downto 0); ddr2_ras_n: out std_logic; ddr2_cas_n: out std_logic; ddr2_we_n: out std_logic; ddr2_cs_n: out std_logic_vector(0 downto 0); ddr2_odt: out std_logic_vector(0 downto 0); ddr2_cke: out std_logic_vector(0 downto 0); ddr2_dm: out std_logic_vector(7 downto 0); ddr2_dqs: inout std_logic_vector(7 downto 0); ddr2_dqs_n: inout std_logic_vector(7 downto 0); ddr2_ck: out std_logic_vector(1 downto 0); ddr2_ck_n: out std_logic_vector(1 downto 0) ); end memory_controller; architecture rtl of memory_controller is signal clk: std_logic; signal reset_p: std_logic; type request_states is ( REQ_IDLE, REQ_WRITE ); signal request_state: request_states := REQ_IDLE; type response_states is ( RES_IDLE, RES_WAIT_SECOND ); signal response_state: response_states := RES_IDLE; signal ram_init_done: std_logic; signal ram_address: std_logic_vector(30 downto 0); signal ram_command: std_logic_vector(2 downto 0); signal ram_data_in: std_logic_vector(127 downto 0); signal ram_mask_in: std_logic_vector(15 downto 0); signal ram_data_out: std_logic_vector(127 downto 0); signal ram_enq_address: std_logic; signal ram_enq_data: std_logic; signal ram_address_afull: std_logic; signal ram_data_afull: std_logic; signal ram_data_valid: std_logic; signal is_request_ready: std_logic; signal data_in_high: std_logic_vector(127 downto 0); signal mask_in_high: std_logic_vector(15 downto 0); signal data_out_low: std_logic_vector(127 downto 0); begin reset_p <= not sys_reset; -- the lowest three bits pick one of the 8 bytes inside the 64b ram width ram_address <= "000000" & request_addr(27 downto 3); -- WRITE is 000 and READ is 001 ram_command <= "00" & request_type; -- we directly pass the lower half to the mig fifo and only store the -- upper half for writing on a second cycle (this works because we can -- still write 12 words to the fifo when the *almost full* signal is -- asserted by the mig) ram_data_in <= request_data(127 downto 0) when request_state = REQ_IDLE else data_in_high; ram_mask_in <= request_mask(15 downto 0) when request_state = REQ_IDLE else mask_in_high; -- to directly pass data to the fifos (see above) we also have to enable -- the fifo write signals combinatorially, otherwise we miss the first part ram_enq_address <= is_request_ready and request_valid; -- the data write signal is only high for write requests and also has to -- be kept high for a second cycle to write the upper half of the data ram_enq_data <= '1' when ( (is_request_ready and request_valid) = '1' and (request_type = '0') ) or (request_state = REQ_WRITE) else '0'; -- we are only ready if we can write to *both* fifos and everything is -- fully initialized (we could theoretically only look at the address fifo -- for read requests) is_request_ready <= '1' when (ram_init_done = '1') and (ram_address_afull = '0') and (ram_data_afull = '0') and (request_state = REQ_IDLE) else '0'; request_ready <= is_request_ready; input: process(clk, sys_reset) begin if sys_reset = '1' then request_state <= REQ_IDLE; elsif rising_edge(clk) then case request_state is when REQ_IDLE => if is_request_ready = '1' and request_valid = '1' then if request_type = '1' then -- READ request_state <= REQ_IDLE; else -- WRITE data_in_high <= request_data(255 downto 128); mask_in_high <= request_mask(31 downto 16); request_state <= REQ_WRITE; end if; end if; when REQ_WRITE => request_state <= REQ_IDLE; end case; end if; end process input; -- we pass the higher half directly from the mig response_data <= ram_data_out & data_out_low; -- read_valid only asserted for one cycle, must be read immediately response_valid <= '1' when (response_state = RES_WAIT_SECOND) and (ram_data_valid = '1') else '0'; output: process(clk, sys_reset) begin if sys_reset = '1' then response_state <= RES_IDLE; elsif rising_edge(clk) then case response_state is when RES_IDLE => if ram_data_valid = '1' then data_out_low <= ram_data_out; response_state <= RES_WAIT_SECOND; end if; when RES_WAIT_SECOND => if ram_data_valid = '1' then response_state <= RES_IDLE; end if; end case; end if; end process output; ddr2_controller: entity work.ddr2_controller port map ( clk0 => sys_clk0, clk90 => sys_clk90, clkdiv0 => sys_clkdiv0, clk200 => sys_clk_idelay, locked => sys_clk_locked, sys_rst_n => reset_p, rst0_tb => open, clk0_tb => clk, phy_init_done => ram_init_done, app_wdf_afull => ram_data_afull, app_af_afull => ram_address_afull, rd_data_valid => ram_data_valid, app_wdf_wren => ram_enq_data, app_af_wren => ram_enq_address, app_af_addr => ram_address, app_af_cmd => ram_command, rd_data_fifo_out => ram_data_out, app_wdf_data => ram_data_in, app_wdf_mask_data => ram_mask_in, ddr2_dq => ddr2_dq, ddr2_a => ddr2_a, ddr2_ba => ddr2_ba, ddr2_ras_n => ddr2_ras_n, ddr2_cas_n => ddr2_cas_n, ddr2_we_n => ddr2_we_n, ddr2_cs_n => ddr2_cs_n, ddr2_odt => ddr2_odt, ddr2_cke => ddr2_cke, ddr2_dm => ddr2_dm, ddr2_dqs => ddr2_dqs, ddr2_dqs_n => ddr2_dqs_n, ddr2_ck => ddr2_ck, ddr2_ck_n => ddr2_ck_n ); --~ sys_clk_p : in std_logic; --~ sys_clk_n : in std_logic; --~ clk200_p : in std_logic; --~ clk200_n : in std_logic; --~ sys_rst_n : in std_logic; --~ rst0_tb : out std_logic; --~ clk0_tb : out std_logic; --~ phy_init_done : out std_logic; --~ app_wdf_afull : out std_logic; --~ app_af_afull : out std_logic; --~ app_wdf_wren : in std_logic; --~ app_af_wren : in std_logic; --~ app_af_addr : in std_logic_vector(30 downto 0); --~ app_af_cmd : in std_logic_vector(2 downto 0); --~ app_wdf_data : in std_logic_vector(127 downto 0); --~ app_wdf_mask_data : in std_logic_vector(15 downto 0); --~ rd_data_fifo_out : out std_logic_vector(127 downto 0); --~ rd_data_valid : out std_logic; --~ ddr2_dq : inout std_logic_vector(63 downto 0); --~ ddr2_a : out std_logic_vector(12 downto 0); --~ ddr2_ba : out std_logic_vector(1 downto 0); --~ ddr2_ras_n : out std_logic; --~ ddr2_cas_n : out std_logic; --~ ddr2_we_n : out std_logic; --~ ddr2_cs_n : out std_logic_vector(0 downto 0); --~ ddr2_odt : out std_logic_vector(0 downto 0); --~ ddr2_cke : out std_logic_vector(0 downto 0); --~ ddr2_dm : out std_logic_vector(7 downto 0); --~ ddr2_dqs : inout std_logic_vector(7 downto 0); --~ ddr2_dqs_n : inout std_logic_vector(7 downto 0); --~ ddr2_ck : out std_logic_vector(1 downto 0); --~ ddr2_ck_n : out std_logic_vector(1 downto 0) end rtl;