diff --git a/libraries/base/diag/hdllib.cfg b/libraries/base/diag/hdllib.cfg index 9c2da2f578e84f40bfb9867257f61160e16bf048..fe1381d395ffce1d0d4f23aaffb8e15a85634fc1 100644 --- a/libraries/base/diag/hdllib.cfg +++ b/libraries/base/diag/hdllib.cfg @@ -26,7 +26,7 @@ synth_files = $UNB/Firmware/modules/Lofar/diag/src/vhdl/mms_diag_wg_wideband.vhd $UNB/Firmware/modules/Lofar/diag/src/vhdl/diag_data_buffer.vhd $UNB/Firmware/modules/Lofar/diag/src/vhdl/mms_diag_data_buffer.vhd - $UNB/Firmware/modules/Lofar/diag/src/vhdl/diag_block_gen.vhd + src/vhdl/diag_block_gen.vhd $UNB/Firmware/modules/Lofar/diag/src/vhdl/diag_block_gen_reg.vhd src/vhdl/mms_diag_block_gen.vhd diff --git a/libraries/base/diag/src/vhdl/diag_block_gen.vhd b/libraries/base/diag/src/vhdl/diag_block_gen.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d40a7e33a6686a893086fae9b0afe5849d4aa30d --- /dev/null +++ b/libraries/base/diag/src/vhdl/diag_block_gen.vhd @@ -0,0 +1,237 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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 IEEE.NUMERIC_STD.ALL; +use common_lib.common_pkg.ALL; +use work.diag_pkg.ALL; +use dp_lib.dp_stream_pkg.ALL; + +entity diag_block_gen is + generic ( + g_blk_sync : boolean := false; -- when true use active sync during entire block, else use single clock cycle sync pulse + g_buf_dat_w : natural := 32; + g_buf_addr_w : natural := 7 + ); + port ( + rst : in std_logic; + clk : in std_logic; + buf_addr : out std_logic_vector(g_buf_addr_w-1 downto 0); + buf_rden : out std_logic; + buf_rddat : in std_logic_vector(g_buf_dat_w-1 downto 0); + buf_rdval : in std_logic; + ctrl : in t_diag_block_gen; + en_sync : in std_logic := '1'; + out_siso : in t_dp_siso := c_dp_siso_rdy; + out_sosi : out t_dp_sosi + ); + +end diag_block_gen; + +architecture rtl of diag_block_gen is + + type state_type is (s_idle, s_block, s_gap); + + type reg_type is record + blk_en : std_logic; -- enable at block level + blk_xon : std_logic; -- siso.xon at block level, the BG continues but the sosi control depend on xon (the BG does not support siso.ready) + blk_sync : std_logic; -- block sync alternative of the pulse sync + pls_sync : std_logic; -- pulse sync + valid : std_logic; + sop : std_logic; + eop : std_logic; + rd_ena : std_logic; + samples_cnt : natural range 0 to 2**c_diag_bg_samples_per_packet_w-1; + blocks_cnt : natural range 0 to 2**c_diag_bg_blocks_per_sync_w-1; + bsn_cnt : std_logic_vector(c_diag_bg_bsn_init_w-1 downto 0); -- = c_dp_stream_bsn_w + mem_cnt : natural range 0 to 2**g_buf_addr_w-1; + state : state_type; -- The state machine. + end record; + + signal r, rin : reg_type; + signal out_sosi_i : t_dp_sosi := c_dp_sosi_rst; -- Signal used to assign reset values to output + +begin + + p_comb : process(r, rst, ctrl, en_sync, out_siso) + variable v : reg_type; + variable v_samples_per_packet : natural; + variable v_gapsize : natural; + variable v_blocks_per_sync : natural; + variable v_mem_low_adrs : natural; + variable v_mem_high_adrs : natural; + begin + + v_samples_per_packet := TO_UINT(ctrl.samples_per_packet); + v_gapsize := TO_UINT(ctrl.gapsize); + v_blocks_per_sync := TO_UINT(ctrl.blocks_per_sync); + v_mem_low_adrs := TO_UINT(ctrl.mem_low_adrs); + v_mem_high_adrs := TO_UINT(ctrl.mem_high_adrs); + + v := r; -- default hold all r fields + v.pls_sync := '0'; + v.valid := '0'; + v.sop := '0'; + v.eop := '0'; + v.rd_ena := '0'; + + -- Control block generator enable + if ctrl.enable='0' then + v.blk_en := '0'; -- disable immediately + elsif ctrl.enable_sync='0' then + v.blk_en := '1'; -- enable immediately or keep enabled + elsif en_sync='1' then + v.blk_en := '1'; -- enable at input sync pulse or keep enabled + end if; + + -- The pulse sync is high at the sop of the first block, the block sync is high during the entire block until the eop + if r.eop='1' then + v.blk_sync := '0'; + end if; + + -- Increment the block sequence number counter after each block + if r.eop='1' then + v.bsn_cnt := incr_uvec(r.bsn_cnt, 1); + end if; + + case r.state is + when s_idle => + v.blk_xon := out_siso.xon; + v.blk_sync := '0'; + v.samples_cnt := 0; + v.blocks_cnt := 0; + v.bsn_cnt := ctrl.bsn_init; + v.mem_cnt := v_mem_low_adrs; + if(r.blk_en = '1') then -- Wait until enabled + v.rd_ena := '1'; + v.state := s_block; + end if; + + when s_block => + v.rd_ena := '1'; + if(r.samples_cnt = 0 and r.blocks_cnt = 0) then + v.pls_sync := '1'; -- Always start with a pulse sync + v.blk_sync := '1'; + v.sop := '1'; + v.samples_cnt := v.samples_cnt + 1; + elsif(r.samples_cnt = 0) then + v.sop := '1'; + v.samples_cnt := v.samples_cnt + 1; + elsif(r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0 and r.blocks_cnt >= v_blocks_per_sync-1) then + v.eop := '1'; + v.samples_cnt := 0; + v.blocks_cnt := 0; + elsif(r.samples_cnt >= v_samples_per_packet-1 and v_gapsize = 0) then + v.eop := '1'; + v.samples_cnt := 0; + v.blocks_cnt := r.blocks_cnt + 1; + elsif(r.samples_cnt >= v_samples_per_packet-1) then + v.eop := '1'; + v.samples_cnt := 0; + v.rd_ena := '0'; + v.state := s_gap; + else + v.samples_cnt := r.samples_cnt + 1; + end if; + v.valid := '1'; + + if(r.mem_cnt >= v_mem_high_adrs) then + v.mem_cnt := v_mem_low_adrs; + else + v.mem_cnt := r.mem_cnt + 1; + end if; + + if(v.eop = '1' and r.blk_en = '0') then + v.state := s_idle; -- accept disable after eop, not during block + end if; + if(r.eop = '1') then + v.blk_xon := out_siso.xon; -- accept XOFF after eop, not during block + end if; + + when s_gap => + if(r.samples_cnt >= v_gapsize-1 and r.blocks_cnt >= v_blocks_per_sync-1) then + v.samples_cnt := 0; + v.blocks_cnt := 0; + v.rd_ena := '1'; + v.state := s_block; + elsif(r.samples_cnt >= v_gapsize-1) then + v.samples_cnt := 0; + v.blocks_cnt := r.blocks_cnt + 1; + v.rd_ena := '1'; + v.state := s_block; + else + v.samples_cnt := r.samples_cnt + 1; + end if; + + if(r.blk_en = '0') then + v.state := s_idle; + end if; + v.blk_xon := out_siso.xon; + + when others => + v.state := s_idle; + + end case; + + if(rst = '1') then + v.blk_en := '0'; + v.blk_xon := '0'; + v.blk_sync := '0'; + v.pls_sync := '0'; + v.valid := '0'; + v.sop := '0'; + v.eop := '0'; + v.rd_ena := '0'; + v.samples_cnt := 0; + v.blocks_cnt := 0; + v.bsn_cnt := (others=>'0'); + v.mem_cnt := 0; + v.state := s_idle; + end if; + + rin <= v; + + end process; + + p_regs : process(rst, clk) + begin + if rising_edge(clk) then + r <= rin; + end if; + end process; + + -- Connect to the outside world + out_sosi_i.sop <= r.sop and r.blk_xon; + out_sosi_i.eop <= r.eop and r.blk_xon; + out_sosi_i.sync <= r.pls_sync and r.blk_xon when g_blk_sync=false else r.blk_sync and r.blk_xon; + out_sosi_i.valid <= r.valid and r.blk_xon; + out_sosi_i.bsn <= r.bsn_cnt; + out_sosi_i.re <= RESIZE_DP_DSP_DATA(buf_rddat(g_buf_dat_w/2-1 downto 0)); -- treat as signed + out_sosi_i.im <= RESIZE_DP_DSP_DATA(buf_rddat(g_buf_dat_w-1 downto g_buf_dat_w/2)); -- treat as signed + out_sosi_i.data <= RESIZE_DP_DATA( buf_rddat(g_buf_dat_w-1 downto 0)); -- treat as unsigned + + out_sosi <= out_sosi_i; + buf_addr <= TO_UVEC(r.mem_cnt, g_buf_addr_w); + buf_rden <= r.rd_ena; + +end rtl;