-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
io_ddr_cross_domain.vhd 4.66 KiB
--------------------------------------------------------------------------------
--
-- Copyright (C) 2014
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Purpose: Cross clock domain between dvr_clk and ctlr_clk
-- Description:
--
-- Remarks:
-- . If the dvr_clk=ctlr_clk then the clock domain crossing logic defaults
-- to wires. However dvr_clk could also be the dp_clk or the mm_clk and then
-- the clock domain crossing logic is needed.
-- No need to cross dvr_start_address and dvr_nof_data, because these
-- are stable when the dvr_en is stable.
LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
ENTITY io_ddr_cross_domain IS
GENERIC (
g_cross_domain : BOOLEAN := TRUE;
g_delay_len : NATURAL := c_meta_delay_len
);
PORT (
-- Driver clock domain
dvr_clk : IN STD_LOGIC;
dvr_rst : IN STD_LOGIC;
dvr_done : OUT STD_LOGIC;
dvr_en : IN STD_LOGIC;
dvr_wr_not_rd : IN STD_LOGIC;
dvr_start_address : IN STD_LOGIC_VECTOR;
dvr_nof_data : IN STD_LOGIC_VECTOR;
dvr_wr_flush_en : IN STD_LOGIC := '0';
-- DDR controller clock domain
ctlr_clk : IN STD_LOGIC;
ctlr_rst : IN STD_LOGIC;
ctlr_dvr_done : IN STD_LOGIC;
ctlr_dvr_en : OUT STD_LOGIC;
ctlr_dvr_wr_not_rd : OUT STD_LOGIC;
ctlr_dvr_start_address : OUT STD_LOGIC_VECTOR;
ctlr_dvr_nof_data : OUT STD_LOGIC_VECTOR;
ctlr_dvr_wr_flush_en : OUT STD_LOGIC := '0'
);
END io_ddr_cross_domain;
ARCHITECTURE str OF io_ddr_cross_domain IS
SIGNAL dvr_en_busy : STD_LOGIC;
SIGNAL new_dvr_done : STD_LOGIC;
BEGIN
no_cross : IF g_cross_domain=FALSE GENERATE
-- dvr_clk --> ctlr_clk
ctlr_dvr_en <= dvr_en;
ctlr_dvr_wr_not_rd <= dvr_wr_not_rd;
ctlr_dvr_start_address <= dvr_start_address;
ctlr_dvr_nof_data <= dvr_nof_data;
ctlr_dvr_wr_flush_en <= dvr_wr_flush_en;
-- ctlr_clk --> dvr_clk
dvr_done <= ctlr_dvr_done;
END GENERATE;
gen_cross : IF g_cross_domain=TRUE GENERATE
-- dvr_clk --> ctlr_clk
u_common_spulse_ctlr_dvr_en : ENTITY common_lib.common_spulse
GENERIC MAP (
g_delay_len => g_delay_len
)
PORT MAP (
in_rst => dvr_rst,
in_clk => dvr_clk,
in_pulse => dvr_en,
in_busy => dvr_en_busy,
out_rst => ctlr_rst,
out_clk => ctlr_clk,
out_pulse => ctlr_dvr_en
);
-- Only register into the other clock domain
ctlr_dvr_wr_not_rd <= dvr_wr_not_rd WHEN rising_edge(ctlr_clk);
ctlr_dvr_start_address <= dvr_start_address WHEN rising_edge(ctlr_clk);
ctlr_dvr_nof_data <= dvr_nof_data WHEN rising_edge(ctlr_clk);
u_common_spulse_ctlr_dvr_wr_flush_en : ENTITY common_lib.common_spulse
GENERIC MAP (
g_delay_len => g_delay_len
)
PORT MAP (
in_rst => dvr_rst,
in_clk => dvr_clk,
in_pulse => dvr_wr_flush_en,
out_rst => ctlr_rst,
out_clk => ctlr_clk,
out_pulse => ctlr_dvr_wr_flush_en
);
-- ctlr_clk --> dvr_clk
u_common_async_dvr_done : ENTITY common_lib.common_async
GENERIC MAP (
g_rst_level => '0',
g_delay_len => g_delay_len
)
PORT MAP (
rst => dvr_rst,
clk => dvr_clk,
din => ctlr_dvr_done,
dout => new_dvr_done
);
-- Ensure previous dvr_done goes low after new dvr_en
dvr_done <= new_dvr_done AND NOT dvr_en_busy;
END GENERATE;
END str;