We cannot add the full repository here, because it contains the mig core, which is not allowed to be redistributed publicy.
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;
|
|
|