diff --git a/libraries/base/common/src/vhdl/common_mem_mux.vhd b/libraries/base/common/src/vhdl/common_mem_mux.vhd index 3ed2542df132512111a9b20310074dbe19bdf241..dcc53e749851b88cd0378f1786ddcb461df63a27 100644 --- a/libraries/base/common/src/vhdl/common_mem_mux.vhd +++ b/libraries/base/common/src/vhdl/common_mem_mux.vhd @@ -25,12 +25,30 @@ -- Description: -- The common_mem_mux unit combines an array of mosi's and miso's to one -- single set of mosi and miso. Should be used to decrease the amount of --- memory interfaces to the SOPC. +-- slave memory interfaces to the MM bus. +-- +-- g_rd_latency +-- ______________ +-- strip index: | | +-- mosi.address[h:w] ---+-->| delay line |--\ +-- | |____________| | +-- | | +-- selected v | +-- mosi -------> mosi_arr.wr[ ]-----------------------------> mosi_arr +-- rd | +-- selected v +-- miso <-------------------------------miso_arr[ ]<--------- miso_arr +-- +-- . not selected mosi_arr get mosi but with wr='0', rd='0' +-- . not selected miso_arr are ignored +-- -- Remarks: -- . In simulation selecting an unused element address will cause a simulation --- failure. Therefore the element_address is only accepted when it is in the +-- failure. Therefore the element index is only accepted when it is in the -- g_nof_mosi-1 DOWNTO 0 range. --- +-- . In case multiple common_mem_mux would be used in series, then only the +-- top one needs to account for g_rd_latency>0, the rest can use 0. +-- ------------------------------------------------------------------------------- @@ -41,8 +59,8 @@ USE common_lib.common_mem_pkg.ALL; ENTITY common_mem_mux IS GENERIC ( - g_nof_mosi : POSITIVE := 256; -- Number of memory interfaces in the array. - g_mult_addr_w : POSITIVE := 8; -- Address width of each memory-interface element in the array. + g_nof_mosi : POSITIVE := 256; -- Number of memory interfaces in the array. + g_mult_addr_w : POSITIVE := 8; -- Address width of each memory-interface element in the muliplexed array. g_rd_latency : NATURAL := 0 ); PORT ( @@ -56,53 +74,59 @@ END common_mem_mux; ARCHITECTURE rtl OF common_mem_mux IS - CONSTANT c_upper_limit : NATURAL := g_mult_addr_w + ceil_log2(g_nof_mosi); + CONSTANT c_index_w : NATURAL := ceil_log2(g_nof_mosi); + CONSTANT c_total_addr_w : NATURAL := c_index_w + g_mult_addr_w; - SIGNAL element_address_arr : t_natural_arr(0 TO g_rd_latency); + SIGNAL index_arr : t_natural_arr(0 TO g_rd_latency); + SIGNAL index_rw : NATURAL; -- read or write access + SIGNAL index_rd : NATURAL; -- read response BEGIN - gen_multiple : IF(g_nof_mosi > 1) GENERATE + gen_single : IF g_nof_mosi=1 GENERATE + mosi_arr(0) <= mosi; + miso <= miso_arr(0); + END GENERATE; + + gen_multiple : IF g_nof_mosi>1 GENERATE -- The activated element of the array is detected here - element_address_arr(0) <= TO_UINT(mosi.address(c_upper_limit-1 DOWNTO g_mult_addr_w)); + index_arr(0) <= TO_UINT(mosi.address(c_total_addr_w-1 DOWNTO g_mult_addr_w)); + + -- Pipeline the index of the activated element to account for the read latency + p_clk : PROCESS(clk) + BEGIN + IF rising_edge(clk) THEN + index_arr(1 TO g_rd_latency) <= index_arr(0 TO g_rd_latency-1); + END IF; + END PROCESS; + + index_rw <= index_arr(0); + index_rd <= index_arr(g_rd_latency); -- Master access, can be write or read - p_mosi_arr : PROCESS(mosi, element_address_arr) + p_mosi_arr : PROCESS(mosi, index_rw) BEGIN FOR I IN 0 TO g_nof_mosi-1 LOOP mosi_arr(I) <= mosi; mosi_arr(I).rd <= '0'; mosi_arr(I).wr <= '0'; - IF I = element_address_arr(0) THEN + IF I = index_rw THEN mosi_arr(I).rd <= mosi.rd; mosi_arr(I).wr <= mosi.wr; END IF; END LOOP; END PROCESS; - -- Pipeline the address of the activated element to account for the read latency - p_clk : PROCESS(clk) - BEGIN - IF rising_edge(clk) THEN - element_address_arr(1 TO g_rd_latency) <= element_address_arr(0 TO g_rd_latency-1); - END IF; - END PROCESS; - -- Slave response to read access after g_rd_latency clk cycles - p_miso : PROCESS(miso_arr, element_address_arr) + p_miso : PROCESS(miso_arr, index_rd) BEGIN miso <= c_mem_miso_rst; FOR I IN 0 TO g_nof_mosi-1 LOOP - IF I = element_address_arr(g_rd_latency) THEN + IF I = index_rd THEN miso <= miso_arr(I); END IF; END LOOP; END PROCESS; END GENERATE; - gen_single : IF(g_nof_mosi = 1) GENERATE - mosi_arr(0) <= mosi; - miso <= miso_arr(0); - END GENERATE; - END rtl;