diff --git a/libraries/base/diag/hdllib.cfg b/libraries/base/diag/hdllib.cfg index fe1381d395ffce1d0d4f23aaffb8e15a85634fc1..665e7c025c9d45d5b32789017688bc9fdc4c4671 100644 --- a/libraries/base/diag/hdllib.cfg +++ b/libraries/base/diag/hdllib.cfg @@ -27,7 +27,7 @@ synth_files = $UNB/Firmware/modules/Lofar/diag/src/vhdl/diag_data_buffer.vhd $UNB/Firmware/modules/Lofar/diag/src/vhdl/mms_diag_data_buffer.vhd src/vhdl/diag_block_gen.vhd - $UNB/Firmware/modules/Lofar/diag/src/vhdl/diag_block_gen_reg.vhd + src/vhdl/diag_block_gen_reg.vhd src/vhdl/mms_diag_block_gen.vhd test_bench_files = diff --git a/libraries/base/diag/src/vhdl/diag_block_gen_reg.vhd b/libraries/base/diag/src/vhdl/diag_block_gen_reg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b16f2e04688cde65c75feac34dff6ffa0ff27ded --- /dev/null +++ b/libraries/base/diag/src/vhdl/diag_block_gen_reg.vhd @@ -0,0 +1,166 @@ +----------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- 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; +use IEEE.std_logic_1164.ALL; +use IEEE.numeric_std.ALL; +use common_lib.common_pkg.ALL; +use common_lib.common_mem_pkg.ALL; +use work.diag_pkg.ALL; + +entity diag_block_gen_reg is + generic ( + g_cross_clock_domain : boolean := TRUE; -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain + g_diag_block_gen_rst : t_diag_block_gen := c_diag_block_gen_rst + ); + port ( + mm_rst : in std_logic; -- Clocks and reset + mm_clk : in std_logic; + dp_rst : in std_logic := '0'; + dp_clk : in std_logic; + mm_mosi : in t_mem_mosi; -- Memory Mapped Slave in mm_clk domain + mm_miso : out t_mem_miso := c_mem_miso_rst; + bg_ctrl : out t_diag_block_gen := g_diag_block_gen_rst + ); +end diag_block_gen_reg; + +architecture rtl of diag_block_gen_reg is + + constant c_adrs_width : positive := 3; + signal mm_bg_ctrl : t_diag_block_gen := g_diag_block_gen_rst; + signal dp_bg_ctrl : t_diag_block_gen := g_diag_block_gen_rst; + +begin + + ------------------------------------------------------------------------------ + -- MM register access in the mm_clk domain + -- . Hardcode the shared MM slave register directly in RTL instead of using + -- the common_reg_r_w instance. Directly using RTL is easier when the large + -- MM register has multiple different fields and with different read and + -- write options per field in one MM register. + ------------------------------------------------------------------------------ + + p_mm_reg : process (mm_rst, mm_clk) + begin + if(mm_rst = '1') then + mm_miso <= c_mem_miso_rst; + mm_bg_ctrl <= g_diag_block_gen_rst; + elsif(rising_edge(mm_clk)) then + -- Read access defaults + mm_miso.rdval <= '0'; + -- Write access: set register value + if(mm_mosi.wr = '1') then + case TO_UINT(mm_mosi.address(c_adrs_width-1 downto 0)) is + when 0 => + mm_bg_ctrl.enable <= mm_mosi.wrdata(0); + mm_bg_ctrl.enable_sync <= mm_mosi.wrdata(1); + when 1 => + mm_bg_ctrl.samples_per_packet <= mm_mosi.wrdata(c_diag_bg_samples_per_packet_w -1 downto 0); + when 2 => + mm_bg_ctrl.blocks_per_sync <= mm_mosi.wrdata(c_diag_bg_blocks_per_sync_w -1 downto 0); + when 3 => + mm_bg_ctrl.gapsize <= mm_mosi.wrdata(c_diag_bg_gapsize_w -1 downto 0); + when 4 => + mm_bg_ctrl.mem_low_adrs <= mm_mosi.wrdata(c_diag_bg_mem_low_adrs_w -1 downto 0); + when 5 => + mm_bg_ctrl.mem_high_adrs <= mm_mosi.wrdata(c_diag_bg_mem_high_adrs_w -1 downto 0); + when 6 => + mm_bg_ctrl.bsn_init(31 downto 0) <= mm_mosi.wrdata(31 downto 0); + when 7 => + mm_bg_ctrl.bsn_init(63 downto 32) <= mm_mosi.wrdata(31 downto 0); + when others => null; -- not used MM addresses + end case; + -- Read access: get register value + elsif mm_mosi.rd = '1' then + mm_miso <= c_mem_miso_rst; -- set unused rddata bits to '0' when read + mm_miso.rdval <= '1'; + case TO_UINT(mm_mosi.address(c_adrs_width-1 downto 0)) is + -- Read Block Sync + when 0 => + mm_miso.rddata(0) <= mm_bg_ctrl.enable; + mm_miso.rddata(1) <= mm_bg_ctrl.enable_sync; + when 1 => + mm_miso.rddata(c_diag_bg_samples_per_packet_w -1 downto 0) <= mm_bg_ctrl.samples_per_packet; + when 2 => + mm_miso.rddata(c_diag_bg_blocks_per_sync_w -1 downto 0) <= mm_bg_ctrl.blocks_per_sync; + when 3 => + mm_miso.rddata(c_diag_bg_gapsize_w -1 downto 0) <= mm_bg_ctrl.gapsize; + when 4 => + mm_miso.rddata(c_diag_bg_mem_low_adrs_w -1 downto 0) <= mm_bg_ctrl.mem_low_adrs; + when 5 => + mm_miso.rddata(c_diag_bg_mem_high_adrs_w -1 downto 0) <= mm_bg_ctrl.mem_high_adrs; + when 6 => + mm_miso.rddata(31 downto 0) <= mm_bg_ctrl.bsn_init(31 downto 0); + when 7 => + mm_miso.rddata(31 downto 0) <= mm_bg_ctrl.bsn_init(63 downto 32); + when others => null; -- not used MM addresses + end case; + end if; + end if; + end process; + + ------------------------------------------------------------------------------ + -- Transfer register value between mm_clk and dp_clk domain. + -- If the function of the register ensures that the value will not be used + -- immediately when it was set, then the transfer between the clock domains + -- can be done by wires only. Otherwise if the change in register value can + -- have an immediate effect then the bit or word value needs to be transfered + -- using: + -- + -- . common_async --> for single-bit level signal + -- . common_spulse --> for single-bit pulse signal + -- . common_reg_cross_domain --> for a multi-bit (a word) signal + -- + -- Typically always use a crossing component for the single bit signals (to + -- be on the save side) and only use a crossing component for the word + -- signals if it is necessary (to avoid using more logic than necessary). + ------------------------------------------------------------------------------ + + no_cross : if g_cross_clock_domain = FALSE generate + dp_bg_ctrl <= mm_bg_ctrl; + end generate; -- no_cross + + gen_crossing : if g_cross_clock_domain = TRUE generate + -- Assume diag BG enable gets written last, so when diag BG enable is transfered properly to the dp_clk domain, then + -- the other diag BG control fields are stable as well + u_bg_enable : entity common_lib.common_async + generic map ( + g_rst_level => '0' + ) + port map ( + rst => dp_rst, + clk => dp_clk, + din => mm_bg_ctrl.enable, + dout => dp_bg_ctrl.enable + ); + dp_bg_ctrl.enable_sync <= mm_bg_ctrl.enable_sync; + dp_bg_ctrl.samples_per_packet <= mm_bg_ctrl.samples_per_packet; + dp_bg_ctrl.blocks_per_sync <= mm_bg_ctrl.blocks_per_sync; + dp_bg_ctrl.gapsize <= mm_bg_ctrl.gapsize; + dp_bg_ctrl.mem_low_adrs <= mm_bg_ctrl.mem_low_adrs; + dp_bg_ctrl.mem_high_adrs <= mm_bg_ctrl.mem_high_adrs; + dp_bg_ctrl.bsn_init <= mm_bg_ctrl.bsn_init; + end generate; -- gen_crossing + + bg_ctrl <= dp_bg_ctrl; + +end rtl;