Select Git revision
validatesip
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
mmp_st_histogram.vhd 9.14 KiB
-------------------------------------------------------------------------------
--
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-- Author:
-- . Daniel van der Schuur
-- Purpose:
-- . MMP-wrapper that adds MM clock domain RAM readout and and multi-instance
-- support to st_histogram.
-- Description:
-- . Adds logic to move st_histogram RAM contents into the dual clock RAM for
-- readout in MM clock domain.
-- . Per instance there are at least (or more dependent on g_nof_bins) two
-- block RAM:
-- . one dual page block RAM in st_histogram in the dp_clk domain that
-- accumulate or hold the bin values for every sync interval,
-- . one dual clock block RAM here to provide the read access to the
-- page with the hold bin values via the mm_clk domain.
LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY mmp_st_histogram IS
GENERIC (
g_nof_instances : NATURAL;
g_data_w : NATURAL;
g_nof_bins : NATURAL;
g_nof_data_per_sync : NATURAL;
g_nof_data_per_sync_diff : NATURAL
);
PORT (
dp_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
snk_in_arr : IN t_dp_sosi_arr(g_nof_instances-1 DOWNTO 0);
mm_clk : IN STD_LOGIC;
mm_rst : IN STD_LOGIC;
ram_copi : IN t_mem_copi;
ram_cipo : OUT t_mem_cipo
);
END mmp_st_histogram;
ARCHITECTURE str OF mmp_st_histogram IS
-------------------------------------------------------------------------------
-- st_histogram instances
-------------------------------------------------------------------------------
SIGNAL st_histogram_ram_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0);
SIGNAL st_histogram_ram_cipo_arr : t_mem_cipo_arr(g_nof_instances-1 DOWNTO 0);
-------------------------------------------------------------------------------
-- Dual clock RAM
-------------------------------------------------------------------------------
CONSTANT c_reg_adr_w : NATURAL := 1;
CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins);
CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync+1);
CONSTANT c_ram : t_c_mem := (latency => 1,
adr_w => c_ram_adr_w,
dat_w => c_ram_dat_w,
nof_dat => g_nof_bins,
init_sl => '0');
CONSTANT c_addr_high : NATURAL := g_nof_bins-1;
SIGNAL wr_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0);
-------------------------------------------------------------------------------
-- Logic to move st_histogram RAM contents into the dual clock RAM
-------------------------------------------------------------------------------
SIGNAL ram_fill : STD_LOGIC;
SIGNAL ram_filling : STD_LOGIC;
SIGNAL nxt_ram_filling : STD_LOGIC;
SIGNAL ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0);
SIGNAL nxt_ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0);
SIGNAL prv_ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0);
-------------------------------------------------------------------------------
-- MM multiplexing
-------------------------------------------------------------------------------
SIGNAL ram_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0);
SIGNAL ram_cipo_arr : t_mem_cipo_arr(g_nof_instances-1 DOWNTO 0);
BEGIN
-------------------------------------------------------------------------------
-- st_histogram instances
-------------------------------------------------------------------------------
gen_st_histogram : FOR i IN 0 TO g_nof_instances-1 GENERATE
u_st_histogram : ENTITY work.st_histogram
GENERIC MAP(
g_data_w => g_data_w,
g_nof_bins => g_nof_bins,
g_nof_data_per_sync => g_nof_data_per_sync,
g_nof_data_per_sync_diff => g_nof_data_per_sync_diff
)
PORT MAP (
dp_clk => dp_clk,
dp_rst => dp_rst,
snk_in => snk_in_arr(i),
ram_mosi => st_histogram_ram_copi_arr(i),
ram_miso => st_histogram_ram_cipo_arr(i)
);
END GENERATE;
-------------------------------------------------------------------------------
-- Dual clock RAM: DP write side, MM read side
-- . How do we get the st_histogram RAM contents into the RAMs below?
-- . DPRAM -> read>write process -> MM RAM
-------------------------------------------------------------------------------
gen_common_ram_crw_cw : FOR i IN 0 TO g_nof_instances-1 GENERATE
u_common_ram_crw_cw : ENTITY common_lib.common_ram_crw_cw
GENERIC MAP (
g_technology => c_tech_select_default,
g_ram => c_ram,
g_init_file => "UNUSED"
)
PORT MAP (
mm_clk => mm_clk,
mm_rst => mm_rst,
mm_wr_en => ram_copi_arr(i).wr,
mm_wr_dat => ram_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0),
mm_adr => ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0),
mm_rd_en => ram_copi_arr(i).rd,
mm_rd_dat => ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0),
mm_rd_val => ram_cipo_arr(i).rdval,
st_clk => dp_clk,
st_rst => dp_rst,
st_wr_en => wr_copi_arr(i).wr,
st_adr => wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0),
st_wr_dat => wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0)
);
END GENERATE;
-------------------------------------------------------------------------------
-- Use snk_in Sync pulse to trigger RAM copy
-- . use pipeline>=st_histogram I/O latency - don't copy too soon (clash with clear)
-------------------------------------------------------------------------------
u_common_pipeline_sl : ENTITY common_lib.common_pipeline_sl
GENERIC MAP (
g_pipeline => 10
)
PORT MAP (
clk => dp_clk,
rst => dp_rst,
in_dat => snk_in_arr(0).sync, -- Use only the status signal of st_histogram instance 0
out_dat => ram_fill
);
-------------------------------------------------------------------------------
-- Logic to move st_histogram RAM contents into the dual clock RAM above
-------------------------------------------------------------------------------
-- Keep track of ram_filling status and ram_address (used for reading and writing)
nxt_ram_filling <= '0' WHEN TO_UINT(ram_address)=c_addr_high ELSE '1' WHEN ram_fill='1' ELSE ram_filling;
nxt_ram_address <= (OTHERS=>'0') WHEN ram_filling='0' ELSE INCR_UVEC(ram_address, 1) WHEN ram_filling='1' ELSE ram_address;
-- Do read request on ram_copi when ram_filling
gen_copi_arr: FOR i IN 0 TO g_nof_instances-1 GENERATE
st_histogram_ram_copi_arr(i).wr <= '0';
st_histogram_ram_copi_arr(i).wrdata <= (OTHERS=>'0');
st_histogram_ram_copi_arr(i).rd <= ram_filling;
st_histogram_ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= ram_address;
END GENERATE;
-- Forward the read histogram data from ram_cipo into write copi of dual clock RAM
gen_rd_cipo_to_wr_copi: FOR i IN 0 TO g_nof_instances-1 GENERATE
wr_copi_arr(i).wr <= st_histogram_ram_cipo_arr(i).rdval;
wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) <= st_histogram_ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0);
wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= prv_ram_address;
END GENERATE;
-- Registers
p_clk : PROCESS(dp_clk, dp_rst) IS
BEGIN
IF dp_rst = '1' THEN
ram_address <= (OTHERS=>'0');
prv_ram_address <= (OTHERS => '0');
ram_filling <= '0';
ELSIF RISING_EDGE(dp_clk) THEN
ram_address <= nxt_ram_address;
prv_ram_address <= ram_address;
ram_filling <= nxt_ram_filling;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
-- MM multiplexing
-------------------------------------------------------------------------------
u_common_mem_mux : ENTITY common_lib.common_mem_mux
GENERIC MAP (
g_nof_mosi => g_nof_instances,
g_mult_addr_w => c_ram_adr_w
)
PORT MAP (
mosi => ram_copi,
miso => ram_cipo,
mosi_arr => ram_copi_arr,
miso_arr => ram_cipo_arr
);
END str;