diff --git a/libraries/base/mm/src/vhdl/mm_master_mux.vhd b/libraries/base/mm/src/vhdl/mm_master_mux.vhd index 1c03f46a71d3245b40eab82e2476b62b978c0ad2..ccfa875c277f65c4395775ed53ffe8f403e23f2d 100644 --- a/libraries/base/mm/src/vhdl/mm_master_mux.vhd +++ b/libraries/base/mm/src/vhdl/mm_master_mux.vhd @@ -1,144 +1,144 @@ -------------------------------------------------------------------------------- --- --- 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 mm_master_mux is a simple multiplexer that allows multiple --- masters to access the same MM port. The mm_master_mux does not --- provide arbitration between the masters in the array. Therefore the --- precondition is that the external application takes care that the MM --- accesses of the multiple masters in the array do not overlap in time. --- --- Write accesses from multiple masters occur may without gaps. After a read --- access from one master the read latency must first be accounted for by --- the application introducing a gap, before a read access by another master --- can be multiplexed. --- --- The mm_master_mux operates combinatorially, so it introduces no --- extra latency. The mm_clk is needed to hold the index of the master that --- is currently active, to ensure that the read data is passed on to the --- master that did the rd access. --- --- Remarks: --- . This resembles common_mem_demux.vhd, but is not identical. The difference --- is that common_mem_demux is the inverse of common_mem_demux and therefore --- assumes that all the mux_mosi spans the entire array whereas for this --- mm_master_mux the mux_mosi spans one element. --- . There is no bus arbitrator. This is sufficient for use cases where e.g. --- one master only does some initialization accesses after reset and the --- other master is the main master that does all subsequent accesses. --- Therefore this mm_master_mux is typically suited per MM slave --- that needs dual master access, rather then to select between two main --- central MM masters. --- . There is no pipelining. The advantage is that the mux_miso.waitrequest is --- supported without extra effort. --- -------------------------------------------------------------------------------- - - -LIBRARY IEEE, common_lib; -USE IEEE.STD_LOGIC_1164.ALL; -USE common_lib.common_pkg.ALL; -USE common_lib.common_mem_pkg.ALL; - -ENTITY mm_master_mux IS - GENERIC ( - g_nof_masters : POSITIVE; -- Number of MM masters - g_rd_latency_min : NATURAL -- Minimum 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 mm_master_mux; - -ARCHITECTURE rtl OF mm_master_mux IS - - SIGNAL index : NATURAL := 0; - SIGNAL index_hold : NATURAL := 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 - -- The pre condition is that the input masters will only start an access - -- when the mux master is free. For a rd access this means that the - -- read latency of the rdval has passed. Therefor it is not necessary - -- that this mm_master_mux maintains an index pipeline - -- from rd until expected rdval. Instead it is sufficient to hold the - -- index of the active master, until the next master does an access. For - -- rd access hold the last active index to ensure that rdval will be - -- directed to the master that orginated the rd access. For wr access - -- hold last active index instead of reset to '0' to ease observation of - -- the index value in wave window. - p_index : PROCESS(master_mosi_arr, index_hold) - BEGIN - index <= index_hold; -- default hold index of last active master - 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 <= I; -- index of active master - EXIT; - END IF; - END LOOP; - END PROCESS; - - index_hold <= index WHEN rising_edge(mm_clk); -- hold index of last active master - - - -- Multiplex master access, can be write or read - mux_mosi <= master_mosi_arr(index); - - -- Multiplex slave read response - p_miso : PROCESS(mux_miso, index) - 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 the minimal read latency is g_rd_latency_min = 0, then the mux - -- has to use the combinatorial index, else it use the registered - -- index, to ease achieving timing closure. - IF g_rd_latency_min=0 THEN - IF I = index THEN - master_miso_arr(I).rdval <= mux_miso.rdval; - END IF; - ELSE - IF I = index_hold THEN - master_miso_arr(I).rdval <= mux_miso.rdval; - END IF; - END IF; - END LOOP; - END PROCESS; - - END GENERATE; - -END rtl; +------------------------------------------------------------------------------- +-- +-- 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 mm_master_mux is a simple multiplexer that allows multiple +-- masters to access the same MM port. The mm_master_mux does not +-- provide arbitration between the masters in the array. Therefore the +-- precondition is that the external application takes care that the MM +-- accesses of the multiple masters in the array do not overlap in time. +-- +-- Write accesses from multiple masters occur may without gaps. After a read +-- access from one master the read latency must first be accounted for by +-- the application introducing a gap, before a read access by another master +-- can be multiplexed. +-- +-- The mm_master_mux operates combinatorially, so it introduces no +-- extra latency. The mm_clk is needed to hold the index of the master that +-- is currently active, to ensure that the read data is passed on to the +-- master that did the rd access. +-- +-- Remarks: +-- . This resembles common_mem_demux.vhd, but is not identical. The difference +-- is that common_mem_demux is the inverse of common_mem_demux and therefore +-- assumes that all the mux_mosi spans the entire array whereas for this +-- mm_master_mux the mux_mosi spans one element. +-- . There is no bus arbitrator. This is sufficient for use cases where e.g. +-- one master only does some initialization accesses after reset and the +-- other master is the main master that does all subsequent accesses. +-- Therefore this mm_master_mux is typically suited per MM slave +-- that needs dual master access, rather then to select between two main +-- central MM masters. +-- . There is no pipelining. The advantage is that the mux_miso.waitrequest is +-- supported without extra effort. +-- +------------------------------------------------------------------------------- + + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; + +ENTITY mm_master_mux IS + GENERIC ( + g_nof_masters : POSITIVE; -- Number of MM masters + g_rd_latency_min : NATURAL -- Minimum 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 mm_master_mux; + +ARCHITECTURE rtl OF mm_master_mux IS + + SIGNAL index : NATURAL := 0; + SIGNAL index_hold : NATURAL := 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 + -- The pre condition is that the input masters will only start an access + -- when the mux master is free. For a rd access this means that the + -- read latency of the rdval has passed. Therefor it is not necessary + -- that this mm_master_mux maintains an index pipeline + -- from rd until expected rdval. Instead it is sufficient to hold the + -- index of the active master, until the next master does an access. For + -- rd access hold the last active index to ensure that rdval will be + -- directed to the master that orginated the rd access. For wr access + -- hold last active index instead of reset to '0' to ease observation of + -- the index value in wave window. + p_index : PROCESS(master_mosi_arr, index_hold) + BEGIN + index <= index_hold; -- default hold index of last active master + 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 <= I; -- index of active master + EXIT; + END IF; + END LOOP; + END PROCESS; + + index_hold <= index WHEN rising_edge(mm_clk); -- hold index of last active master + + + -- Multiplex master access, can be write or read + mux_mosi <= master_mosi_arr(index); + + -- Multiplex slave read response + p_miso : PROCESS(mux_miso, index) + 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 the minimal read latency is g_rd_latency_min = 0, then the mux + -- has to use the combinatorial index, else it use the registered + -- index, to ease achieving timing closure. + IF g_rd_latency_min=0 THEN + IF I = index THEN + master_miso_arr(I).rdval <= mux_miso.rdval; + END IF; + ELSE + IF I = index_hold THEN + master_miso_arr(I).rdval <= mux_miso.rdval; + END IF; + END IF; + END LOOP; + END PROCESS; + + END GENERATE; + +END rtl;