diff --git a/libraries/io/ddr/hdllib.cfg b/libraries/io/ddr/hdllib.cfg index 8f942740c32574e22f64227eebf66c6d62af2b14..9871fb590d9ff0ab7066e21a954e7592b9926a55 100644 --- a/libraries/io/ddr/hdllib.cfg +++ b/libraries/io/ddr/hdllib.cfg @@ -7,6 +7,7 @@ build_dir_sim = $HDL_BUILD_DIR build_dir_synth = $HDL_BUILD_DIR synth_files = + src/vhdl/io_ddr_driver_flush_ctrl.vhd src/vhdl/io_ddr_driver.vhd src/vhdl/io_ddr.vhd diff --git a/libraries/io/ddr/src/vhdl/io_ddr_driver_flush_ctrl.vhd b/libraries/io/ddr/src/vhdl/io_ddr_driver_flush_ctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..47570632ec087859b8155a000e172a45a7c7c315 --- /dev/null +++ b/libraries/io/ddr/src/vhdl/io_ddr_driver_flush_ctrl.vhd @@ -0,0 +1,116 @@ +-------------------------------------------------------------------------------- +-- +-- 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/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY io_ddr_driver_flush_ctrl IS + GENERIC ( + g_sop : BOOLEAN := FALSE; -- Stop flushing on SOP, otherwise stop flushing on valid data + g_sop_channel : BOOLEAN := FALSE; -- When g_sop=TRUE, also check if the channel matches g_sop_start_channel + g_sop_start_channel : NATURAL := 0; + g_nof_channels : NATURAL := 0 + ); + PORT ( + clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + + dvr_en : IN STD_LOGIC := '1'; + dvr_wr_not_rd : IN STD_LOGIC; + dvr_done : IN STD_LOGIC; + + wr_sosi : IN t_dp_sosi; + + dvr_flush : OUT STD_LOGIC + + ); +END io_ddr_driver_flush_ctrl; + + +ARCHITECTURE str OF io_ddr_driver_flush_ctrl IS + + CONSTANT c_channel_w : NATURAL := ceil_log2(g_nof_channels); + + TYPE t_state IS (s_idle, s_flush, s_stop); + + SIGNAL state : t_state; + SIGNAL nxt_state : t_state; + + SIGNAL flush_dis : STD_LOGIC; + +BEGIN + + -- Flush ddr3 module's FIFO (keep sinking the stream but simply discard the + -- data) after reset to prevent ddr3 write fifo from filling up - which would + -- cause problems downstream (dp_mux uses two fifos that cannot be + -- allowed to fill up too much). + -- Also flush the ddr3 module's FIFO when it is reading. + + gen_sop : IF g_sop = TRUE GENERATE -- Disable flushing on arrival of SOP + gen_sop_only: IF g_sop_channel = FALSE GENERATE + flush_dis <= '1' WHEN wr_sosi.sop='1' ELSE '0'; + END GENERATE; + gen_channel : IF g_sop_channel = TRUE GENERATE -- Only disable flushing on arrival of specific channel SOP + flush_dis <= '1' WHEN wr_sosi.sop='1' AND UNSIGNED(wr_sosi.channel(c_channel_w-1 DOWNTO 0))=g_sop_start_channel ELSE '0'; + END GENERATE; + END GENERATE; + + gen_val : IF g_sop = FALSE GENERATE -- Disable flushing on arrival of 1st valid data + flush_dis <= wr_sosi.valid; + END GENERATE; + + p_reg : PROCESS(rst, clk) + BEGIN + IF rst='1' THEN + state <= s_flush; + ELSIF rising_edge(clk) THEN + state <= nxt_state; + END IF; + END PROCESS; + + p_state : PROCESS(state, dvr_done, dvr_en, dvr_wr_not_rd, flush_dis) + BEGIN + nxt_state <= state; + dvr_flush <= '0'; + CASE state IS + WHEN s_idle => + IF dvr_done='1' THEN + dvr_flush <= '1'; + nxt_state <= s_flush; + END IF; + WHEN s_flush => + dvr_flush <= '1'; + IF dvr_en='1' AND dvr_wr_not_rd='1' THEN + nxt_state <= s_stop; + END IF; + WHEN OTHERS => -- s_stop + dvr_flush <= '1'; + IF flush_dis = '1' THEN + nxt_state <= s_idle; + END IF; + END CASE; + END PROCESS; + +END str; +