diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg index 7b6228f14dc373da0cf3cc5a437e9fafbfde32fe..f62ff6389abc265b1fc5b55173359a581f483e52 100644 --- a/libraries/base/common/hdllib.cfg +++ b/libraries/base/common/hdllib.cfg @@ -109,6 +109,7 @@ synth_files = src/vhdl/common_fifo_rd.vhd src/vhdl/common_blockreg.vhd src/vhdl/common_fifo_dc_lock_control.vhd + src/vhdl/common_mem_master_mux.vhd src/vhdl/common_mem_bus.vhd src/vhdl/common_mem_mux.vhd src/vhdl/common_mem_demux.vhd diff --git a/libraries/base/common/src/vhdl/common_mem_master_mux.vhd b/libraries/base/common/src/vhdl/common_mem_master_mux.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a896efd8a1b3d430377d320045bee001f6848f08 --- /dev/null +++ b/libraries/base/common/src/vhdl/common_mem_master_mux.vhd @@ -0,0 +1,119 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- 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: E. Kooistra +-- Purpose: Multiplex an array of MM master interfaces to a single MM master +-- interface +-- Description: +-- This common_mem_master_mux is a simple multiplexer and does not provide +-- arbitration between the masters in the array. Therefore the precondition +-- is that the application takes care that the MM accesses of the multiple +-- masters in the array do not overlap. +-- For read accesses the g_rd_latency defines how much idle time there needs +-- to be after the last read access by one master and a next MM access by +-- another master. +-- The common_mem_master_mux operates combinatorially, so it introduces no +-- extra latency. The mm_clk is needed to time the g_rd_latency of the +-- external mux_miso, to ensure that the read data.is passed on to the +-- master that did the rd access. +-- Remarks: +-- . The mux_miso.waitrequest is not supported. +-- +------------------------------------------------------------------------------- + + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; + +ENTITY common_mem_master_mux IS + GENERIC ( + g_nof_masters : POSITIVE; -- Number of MM masters + g_rd_latency : NATURAL -- Maximum read latency + ); + PORT ( + mm_clk : IN STD_LOGIC; + master_mosi_arr : IN t_mem_mosi_arr(0 TO g_nof_masters-1) := (OTHERS=>c_mem_mosi_rst); + master_miso_arr : OUT t_mem_miso_arr(0 TO g_nof_masters-1) := (OTHERS=>c_mem_miso_rst); + mux_mosi : OUT t_mem_mosi; + mux_miso : IN t_mem_miso + ); +END common_mem_master_mux; + +ARCHITECTURE rtl OF common_mem_master_mux IS + + SIGNAL index_reg : NATURAL := 0; + SIGNAL index_pipeline : t_natural_arr(0 TO g_rd_latency) := (OTHERS=>0); + +BEGIN + + gen_single : IF g_nof_masters=1 GENERATE + mux_mosi <= master_mosi_arr(0); + master_miso_arr(0) <= mux_miso; + END GENERATE; + + gen_multiple : IF g_nof_masters>1 GENERATE + + -- Detect which master in the array is active + p_index : PROCESS(master_mosi_arr, index_reg) + BEGIN + -- default hold last active index instead of reset to 0 to ease observing index in wave window + index_pipeline(0) <= index_reg; + FOR I IN 0 TO g_nof_masters-1 LOOP + IF master_mosi_arr(I).wr='1' OR master_mosi_arr(I).rd='1' THEN + index_pipeline(0) <= I; -- index of active master + EXIT; + END IF; + END LOOP; + END PROCESS; + + index_reg <= index_pipeline(0) WHEN rising_edge(mm_clk); -- hold index + index_pipeline(1 TO g_rd_latency) <= index_pipeline(0 TO g_rd_latency-1) WHEN rising_edge(mm_clk); + + + -- Master access, can be write or read + p_mosi : PROCESS(master_mosi_arr) + BEGIN + mux_mosi <= c_mem_mosi_rst; -- default clear, to avoid latches + FOR I IN 0 TO g_nof_masters-1 LOOP + IF I = index_pipeline(0) THEN -- pass on selected master + mux_mosi <= master_mosi_arr(I); + END IF; + END LOOP; + END PROCESS; + + -- Slave response to read access after g_rd_latency mm_clk cycles + p_miso : PROCESS(mux_miso, index_pipeline) + BEGIN + master_miso_arr <= (OTHERS=>mux_miso); -- default assign to all, to avoid latches + FOR I IN 0 TO g_nof_masters-1 LOOP + master_miso_arr(I).rdval <= '0'; + IF I = index_pipeline(g_rd_latency) THEN -- check index for read response + master_miso_arr(I).rdval <= mux_miso.rdval; + END IF; + END LOOP; + END PROCESS; + + END GENERATE; + +END rtl;