diff --git a/libraries/base/common/src/vhdl/common_mem_bus.vhd b/libraries/base/common/src/vhdl/common_mem_bus.vhd index 72313c36936f5fbfa2f45d9f578f6e63f40e153b..32078476336ad8c684d3ec53fafc0d2231994b51 100644 --- a/libraries/base/common/src/vhdl/common_mem_bus.vhd +++ b/libraries/base/common/src/vhdl/common_mem_bus.vhd @@ -46,11 +46,33 @@ -- when the MM bus uses pipelining. -- -- * Read latency --- For read accesses a slave will --- typically have a read latency, which means that when the rd and address --- are active, then it takes read latency number of clock cycles until the --- rddata becomes available. The read latency can be specified per slave via --- g_rd_latency_arr. +-- For read accesses a slave will typically have a read latency > 0, which +-- means that when the rd and address are active, then it takes read +-- latency number of clock cycles until the rddata becomes available. The +-- read latency can be specified per slave via g_rd_latency_arr. +-- The index_pipeline is used to support that a new wr access or rd access +-- can already start, while a current rd access still has to finish with +-- a rdval. Without the index_pipeline the master would have to wait with +-- a new rd or wr access to another slave until the read response from the +-- current slave has finished. +-- ________ +-- | pipe | +-- master_mosi.address[h:w] = index --+-->| line |--\ +-- | |______| | +-- | | +-- v | +-- master_mosi --> slave_mosi_arr.wr[ ]----------------> slave_mosi_arr +-- rd | +-- v +-- master_miso <--------------------slave_miso_arr[ ]<-- slave_miso_arr +-- +-- A limitation is that if one slave has a read latency of 2 and another +-- slave has a read latency of 1 then it is not possible to access them +-- without a gap of 1 mm_clk cycle, because the rdval will then be active +-- simultaneously from both slaves. Therefore the master can only use +-- random read access between slaves if all slaves have the same read +-- latency. For slaves that have larger read latency the master must +-- insert an gap, before it can read a slave that has less read latency. -- -- * Pipelining -- Default the common_mm_bus is combinatorial, so there is no pipelining @@ -72,20 +94,6 @@ -- The total read latency from master via slave back to master is -- c_mosi_latency + g_rd_latency_arr of the selected slave + c_miso_latency. -- --- ______________ --- strip index: | | --- master_mosi.address[h:w] ---+-->| delay line |--\ --- | |____________| | --- | | --- selected v | --- master_mosi --> slave_mosi_arr.wr[ ]----------------------> slave_mosi_arr --- rd | --- selected v --- master_miso <--------------------------slave_miso_arr[ ]<-- slave_miso_arr --- --- . not selected slave_mosi_arr get master_mosi but with wr='0', rd='0' --- . not selected slave_miso_arr are ignored --- -- Remarks: -- . The common_mem_bus resembles common_mem_mux, but the difference is that -- with common_mem_mux all slaves have the same address range and are @@ -106,10 +114,10 @@ USE common_lib.common_mem_pkg.ALL; ENTITY common_mem_bus IS GENERIC ( - g_nof_slaves : POSITIVE; -- Number of MM slave interfaces on the bus - g_base_arr : t_natural_arr; -- Address base per slave - g_width_arr : t_natural_arr; -- Address width per slave - g_rd_latency_arr : t_natural_arr; -- Read latency per slave + g_nof_slaves : POSITIVE; -- Number of MM slave interfaces on the bus + g_base_arr : t_nat_natural_arr; -- Address base per slave + g_width_arr : t_nat_natural_arr; -- Address width per slave + g_rd_latency_arr : t_nat_natural_arr; -- Read latency per slave g_pipeline_mosi : BOOLEAN := FALSE; g_pipeline_miso : BOOLEAN := FALSE ); @@ -125,7 +133,7 @@ END common_mem_bus; ARCHITECTURE rtl OF common_mem_bus IS -- Determine the address range of all slaves on the MM bus. - FUNCTION func_derive_mm_bus_addr_w(g_base_arr, g_width_arr : t_natural_arr) RETURN NATURAL IS + FUNCTION func_derive_mm_bus_addr_w(g_base_arr, g_width_arr : t_nat_natural_arr) RETURN NATURAL IS VARIABLE v_base : NATURAL := 0; VARIABLE v_width : NATURAL; VARIABLE v_mm_bus_addr_max : NATURAL; @@ -149,7 +157,7 @@ ARCHITECTURE rtl OF common_mem_bus IS CONSTANT c_miso_latency : NATURAL := sel_a_b(g_pipeline_miso, 1, 0); CONSTANT c_index_latency_max : NATURAL := c_mosi_latency + largest(g_rd_latency_arr); - SIGNAL index_pipeline : t_natural_arr(0 TO c_index_latency_max) := (OTHERS=>0); + SIGNAL index_pipeline : t_nat_natural_arr(0 TO c_index_latency_max) := (OTHERS=>0); SIGNAL slave_mosi_arr_comb : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst); SIGNAL master_miso_comb : t_mem_miso := c_mem_miso_rst; diff --git a/libraries/base/common/tb/vhdl/tb_common_mem_bus.vhd b/libraries/base/common/tb/vhdl/tb_common_mem_bus.vhd index eb3531a37521c1441c9c9721ceca637a0616c78e..ed4bb56f4d0a4556f216165683a8dd45b02a8c9d 100644 --- a/libraries/base/common/tb/vhdl/tb_common_mem_bus.vhd +++ b/libraries/base/common/tb/vhdl/tb_common_mem_bus.vhd @@ -31,12 +31,14 @@ -- . same g_rd_latency for all slaves -- . same g_width for all slaves -- . regular base address spacing of slaves in c_base_arr --- . The common_mem_bus.vhd can support a list of arbitrary width slaves. This --- test bench is derived from tb_common_mem_mux.vhd and therefore it uses an --- array of fixed width slaves. For now it is considered sufficient --- coverage for this tb and the corresponding multi tb_tb to also only --- support regular c_base_arr, same g_rd_latency, and same g_width for all --- slaves. +-- . The common_mem_bus.vhd can support a list of arbitrary width slaves, but +-- this tb_common_mem_bus test bench uses an array of fixed width slaves. +-- It is considered sufficient coverage for this tb and the corresponding +-- multi tb_tb to also only support regular c_base_arr, same g_rd_latency, +-- and same g_width for all slaves. The tb_common_mem_master_mux also uses a +-- common_mem_bus.vhd and the tb_common_mem_master_mux does uses an array of +-- arbitrary width slaves. +-- ------------------------------------------------------------------------------- LIBRARY IEEE; @@ -68,9 +70,9 @@ ARCHITECTURE tb OF tb_common_mem_bus IS CONSTANT mm_clk_period : TIME := 10 ns; CONSTANT c_slave_span : NATURAL := 2**g_width_w; - CONSTANT c_base_arr : t_natural_arr := array_init(g_base_offset, g_nof_slaves, c_slave_span); -- Address base per slave - CONSTANT c_width_arr : t_natural_arr := array_init( g_width_w, g_nof_slaves); -- Address width per slave - CONSTANT c_rd_latency_arr : t_natural_arr := array_init( g_rd_latency, g_nof_slaves); -- Read latency per slave + CONSTANT c_base_arr : t_nat_natural_arr := array_init(g_base_offset, g_nof_slaves, c_slave_span); -- Address base per slave + CONSTANT c_width_arr : t_nat_natural_arr := array_init( g_width_w, g_nof_slaves); -- Address width per slave + CONSTANT c_rd_latency_arr : t_nat_natural_arr := array_init( g_rd_latency, g_nof_slaves); -- Read latency per slave CONSTANT c_mosi_latency : NATURAL := sel_a_b(g_pipeline_mosi, 1, 0); CONSTANT c_miso_latency : NATURAL := sel_a_b(g_pipeline_miso, 1, 0); @@ -92,9 +94,9 @@ ARCHITECTURE tb OF tb_common_mem_bus IS SIGNAL miso : t_mem_miso := c_mem_miso_rst; -- Debug signals for monitoring in simulation Wave window - SIGNAL dbg_c_base_arr : t_natural_arr(0 TO g_nof_slaves-1) := c_base_arr; - SIGNAL dbg_c_width_arr : t_natural_arr(0 TO g_nof_slaves-1) := c_width_arr; - SIGNAL dbg_c_rd_latency_arr : t_natural_arr(0 TO g_nof_slaves-1) := c_rd_latency_arr; + SIGNAL dbg_c_base_arr : t_nat_natural_arr(0 TO g_nof_slaves-1) := c_base_arr; + SIGNAL dbg_c_width_arr : t_nat_natural_arr(0 TO g_nof_slaves-1) := c_width_arr; + SIGNAL dbg_c_rd_latency_arr : t_nat_natural_arr(0 TO g_nof_slaves-1) := c_rd_latency_arr; BEGIN @@ -102,7 +104,7 @@ BEGIN mm_rst <= '1', '0' AFTER mm_clk_period*5; p_stimuli : PROCESS - VARIABLE temp : INTEGER; + VARIABLE v_data : INTEGER; BEGIN tb_end <= '0'; mosi <= c_mem_mosi_rst; @@ -123,8 +125,8 @@ BEGIN FOR J IN 0 TO 2**g_width_w-1 LOOP proc_mem_mm_bus_rd(g_base_offset + I*2**g_width_w + J, mm_clk, mosi); proc_common_wait_some_cycles(mm_clk, c_read_latency); - temp := TO_UINT(miso.rddata(31 DOWNTO 0)); - IF temp /= I+J THEN + v_data := TO_UINT(miso.rddata(31 DOWNTO 0)); + IF v_data /= I+J THEN REPORT "Error! Readvalue is not as expected" SEVERITY ERROR; END IF; END LOOP;