-------------------------------------------------------------------------------- -- -- 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_end_address, 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 ); PORT ( -- Driver clock domain dvr_clk : IN STD_LOGIC; dvr_rst : IN STD_LOGIC; dvr_en : IN STD_LOGIC; dvr_done : OUT STD_LOGIC; dvr_wr_not_rd : IN STD_LOGIC; dvr_start_address : IN STD_LOGIC_VECTOR; dvr_end_address : 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_en : OUT STD_LOGIC; ctlr_dvr_done : IN STD_LOGIC; ctlr_dvr_wr_not_rd : OUT STD_LOGIC; ctlr_dvr_start_address : OUT STD_LOGIC_VECTOR; ctlr_dvr_end_address : 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_end_address <= dvr_end_address; 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 => c_meta_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_end_address <= dvr_end_address WHEN rising_edge(ctlr_clk); u_common_spulse_ctlr_dvr_wr_flush_en : ENTITY common_lib.common_spulse GENERIC MAP ( g_delay_len => c_meta_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 => c_meta_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;