242 lines
9.2 KiB
VHDL
242 lines
9.2 KiB
VHDL
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;
|
|
|