Skip to content
Snippets Groups Projects
Commit 95a771bd authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Use mm_bus as core MM bus and mm_latency_adapter and mm_slave_enable per slave...

Use mm_bus as core MM bus and mm_latency_adapter and mm_slave_enable per slave port. Separate p_verify from p_stimuli to support rd at every cycle.
parent be39a8ce
Branches
No related tags found
2 merge requests!28Master,!15Resolve L2SDP-27
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
-- . g_nof_slaves >= 1 -- . g_nof_slaves >= 1
-- . g_waitrequest for g_pipeline_miso_wait = FALSE -- . g_waitrequest for g_pipeline_miso_wait = FALSE
-- . g_pipeline_mosi -- . g_pipeline_mosi
-- . g_pipeline_miso_rd -- . g_pipeline_miso_rdval
-- . g_pipeline_miso_wait = FALSE -- . g_pipeline_miso_wait = FALSE
-- . g_rd_latency >= 1 (using 0 is supported by mm_bus, but not by -- . g_rd_latency >= 1 (using 0 is supported by mm_bus, but not by
-- the common_ram_r_w in u_slaves) -- the common_ram_r_w in u_slaves)
...@@ -54,13 +54,13 @@ USE common_lib.tb_common_mem_pkg.ALL; ...@@ -54,13 +54,13 @@ USE common_lib.tb_common_mem_pkg.ALL;
ENTITY tb_mm_bus IS ENTITY tb_mm_bus IS
GENERIC ( GENERIC (
g_nof_slaves : POSITIVE := 1; -- Number of slave memory interfaces on the MM bus array. g_nof_slaves : POSITIVE := 2; -- Number of slave memory interfaces on the MM bus array.
g_base_offset : NATURAL := 0; -- Address of first slave on the MM bus g_base_offset : NATURAL := 0; -- Address of first slave on the MM bus
g_width_w : POSITIVE := 4; -- Address width of each slave memory in the MM bus array. g_width_w : POSITIVE := 4; -- Address width of each slave memory in the MM bus array.
g_rd_latency : NATURAL := 1; -- Read latency of the slaves slave g_rd_latency : NATURAL := 1; -- Read latency of the slaves
g_waitrequest : BOOLEAN := TRUE; -- When TRUE model waitrequest by MM slaves, else fixed '0' g_waitrequest : BOOLEAN := FALSE; -- When TRUE model waitrequest by MM slaves, else fixed '0'
g_pipeline_mosi : BOOLEAN := FALSE; g_pipeline_mosi : BOOLEAN := FALSE;
g_pipeline_miso_rd : BOOLEAN := TRUE; g_pipeline_miso_rdval : BOOLEAN := FALSE;
g_pipeline_miso_wait : BOOLEAN := FALSE g_pipeline_miso_wait : BOOLEAN := FALSE
); );
END tb_mm_bus; END tb_mm_bus;
...@@ -80,10 +80,13 @@ ARCHITECTURE tb OF tb_mm_bus IS ...@@ -80,10 +80,13 @@ ARCHITECTURE tb OF tb_mm_bus IS
CONSTANT c_width_arr : t_nat_natural_arr := array_init( g_width_w, g_nof_slaves); -- Address width 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_rd_latency_arr : t_nat_natural_arr := array_init( g_rd_latency, g_nof_slaves); -- Read latency per slave
CONSTANT c_bus_pipelining : BOOLEAN := g_pipeline_mosi OR g_pipeline_miso_rdval OR g_pipeline_miso_wait;
CONSTANT c_pipeline_mosi : NATURAL := sel_a_b(g_pipeline_mosi, 1, 0); CONSTANT c_pipeline_mosi : NATURAL := sel_a_b(g_pipeline_mosi, 1, 0);
CONSTANT c_pipeline_miso_rd : NATURAL := sel_a_b(g_pipeline_miso_rd, 1, 0); CONSTANT c_pipeline_miso_rdval : NATURAL := sel_a_b(g_pipeline_miso_rdval, 1, 0);
CONSTANT c_pipeline_miso_wait : NATURAL := sel_a_b(g_pipeline_miso_wait, 1, 0); CONSTANT c_pipeline_miso_wait : NATURAL := sel_a_b(g_pipeline_miso_wait, 1, 0);
CONSTANT c_read_latency : NATURAL := c_pipeline_mosi + g_rd_latency + c_pipeline_miso_rd; CONSTANT c_read_latency : NATURAL := c_pipeline_mosi + g_rd_latency + c_pipeline_miso_rdval;
CONSTANT c_adapt_waitrequest : BOOLEAN := g_waitrequest AND g_pipeline_miso_wait;
CONSTANT c_data_w : NATURAL := 32; CONSTANT c_data_w : NATURAL := 32;
CONSTANT c_test_ram : t_c_mem := (latency => g_rd_latency, CONSTANT c_test_ram : t_c_mem := (latency => g_rd_latency,
...@@ -95,8 +98,15 @@ ARCHITECTURE tb OF tb_mm_bus IS ...@@ -95,8 +98,15 @@ ARCHITECTURE tb OF tb_mm_bus IS
SIGNAL mm_clk : STD_LOGIC := '1'; SIGNAL mm_clk : STD_LOGIC := '1';
SIGNAL tb_end : STD_LOGIC; SIGNAL tb_end : STD_LOGIC;
-- MM bus
SIGNAL master_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL master_mosi : t_mem_mosi := c_mem_mosi_rst;
SIGNAL master_miso : t_mem_miso := c_mem_miso_rst; SIGNAL master_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL bus_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst);
SIGNAL bus_miso_arr : t_mem_miso_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_miso_rst);
-- MM slaves with waitrequest latency adapters for ports that have pipelined flow control
SIGNAL busw_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst);
SIGNAL busw_miso_arr : t_mem_miso_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_miso_rst);
-- MM slaves with waitrequest for ports that are enabled and NC for ports that are not connected
SIGNAL slave_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst); SIGNAL slave_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst);
SIGNAL slave_miso_arr : t_mem_miso_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_miso_rst); SIGNAL slave_miso_arr : t_mem_miso_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_miso_rst);
SIGNAL ram_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst); SIGNAL ram_mosi_arr : t_mem_mosi_arr(0 TO g_nof_slaves-1) := (OTHERS=>c_mem_mosi_rst);
...@@ -109,13 +119,16 @@ ARCHITECTURE tb OF tb_mm_bus IS ...@@ -109,13 +119,16 @@ ARCHITECTURE tb OF tb_mm_bus IS
BEGIN BEGIN
ASSERT NOT(g_nof_slaves=1 AND c_bus_pipelining=TRUE) REPORT "No support for MM bus pipelining with g_nof_slaves=1, because then the mm_bus reduces to wires." SEVERITY FAILURE;
mm_clk <= NOT mm_clk OR tb_end AFTER mm_clk_period/2; mm_clk <= NOT mm_clk OR tb_end AFTER mm_clk_period/2;
mm_rst <= '1', '0' AFTER mm_clk_period*5; mm_rst <= '1', '0' AFTER mm_clk_period*5;
-----------------------------------------------------------------------------
-- Write stimuli and readback to verify
-----------------------------------------------------------------------------
p_stimuli : PROCESS p_stimuli : PROCESS
VARIABLE v_wrdata : INTEGER; -- write data VARIABLE v_wrdata : INTEGER; -- write data
VARIABLE v_rddata : INTEGER; -- read data
VARIABLE v_expdata : INTEGER; -- expected data
BEGIN BEGIN
tb_end <= '0'; tb_end <= '0';
master_mosi <= c_mem_mosi_rst; master_mosi <= c_mem_mosi_rst;
...@@ -126,7 +139,6 @@ BEGIN ...@@ -126,7 +139,6 @@ BEGIN
-- Repeat twice to have wr all, rd all, wr all, rd all -- Repeat twice to have wr all, rd all, wr all, rd all
v_wrdata := 0; v_wrdata := 0;
v_expdata := 0;
FOR vR IN 0 TO c_repeat-1 LOOP FOR vR IN 0 TO c_repeat-1 LOOP
-- Write the whole memory range -- Write the whole memory range
FOR vI IN 0 TO g_nof_slaves-1 LOOP FOR vI IN 0 TO g_nof_slaves-1 LOOP
...@@ -134,21 +146,16 @@ BEGIN ...@@ -134,21 +146,16 @@ BEGIN
proc_mem_mm_bus_wr(g_base_offset + vI*c_slave_span + vJ, v_wrdata, mm_clk, master_miso, master_mosi); proc_mem_mm_bus_wr(g_base_offset + vI*c_slave_span + vJ, v_wrdata, mm_clk, master_miso, master_mosi);
v_wrdata := v_wrdata + 1; v_wrdata := v_wrdata + 1;
END LOOP; END LOOP;
--proc_common_wait_some_cycles(mm_clk, 10); proc_common_wait_some_cycles(mm_clk, 10);
END LOOP; END LOOP;
-- Read back the whole range and check if data is as expected -- Read back the whole range and check if data is as expected
FOR vI IN 0 TO g_nof_slaves-1 LOOP FOR vI IN 0 TO g_nof_slaves-1 LOOP
FOR vJ IN 0 TO c_slave_span-1 LOOP FOR vJ IN 0 TO c_slave_span-1 LOOP
proc_mem_mm_bus_rd(g_base_offset + vI*c_slave_span + vJ, mm_clk, master_miso, master_mosi); proc_mem_mm_bus_rd(g_base_offset + vI*c_slave_span + vJ, mm_clk, master_miso, master_mosi);
proc_common_wait_some_cycles(mm_clk, c_read_latency); --proc_common_wait_some_cycles(mm_clk, c_read_latency); -- not needed, see p_verify
v_rddata := TO_UINT(master_miso.rddata(c_data_w-1 DOWNTO 0));
IF v_rddata /= v_expdata THEN
REPORT "Error! Readvalue is not as expected" SEVERITY ERROR;
END IF;
v_expdata := v_expdata + 1;
--proc_common_wait_some_cycles(mm_clk, 10);
END LOOP; END LOOP;
proc_common_wait_some_cycles(mm_clk, 10);
END LOOP; END LOOP;
END LOOP; END LOOP;
...@@ -157,7 +164,91 @@ BEGIN ...@@ -157,7 +164,91 @@ BEGIN
WAIT; WAIT;
END PROCESS; END PROCESS;
u_slaves : FOR I IN 0 TO g_nof_slaves-1 GENERATE -- Use miso.rdval to know when to verify the rddata, rather than to wait for a fixed c_read_latency after
-- the mosi.rd. The advantage is that then rd accesses can be done on every mm_clk, without having to
-- wait for the c_read_latency. In case of g_pipeline_mosi = TRUE or g_pipeline_miso_wait = TRUE it is
-- even essential to use rdval, because then the latency between rd and rdval can become larger than
-- c_read_latency and even variable (in case of g_waitrequest = TRUE). The disadvantage is that the MM
-- slave must support rdval, but that is ensured by mm_slave_enable.
p_verify : PROCESS
VARIABLE v_expdata : INTEGER := 0; -- expected data
VARIABLE v_rddata : INTEGER; -- read data
BEGIN
WAIT UNTIL rising_edge(mm_clk);
IF master_miso.rdval = '1' THEN
v_rddata := TO_UINT(master_miso.rddata(c_data_w-1 DOWNTO 0));
IF v_rddata /= v_expdata THEN
REPORT "Error! Readvalue is not as expected" SEVERITY ERROR;
END IF;
v_expdata := v_expdata + 1;
END IF;
END PROCESS;
-----------------------------------------------------------------------------
-- The MM bus
-----------------------------------------------------------------------------
u_mm_bus: ENTITY work.mm_bus
GENERIC MAP (
g_nof_slaves => g_nof_slaves,
g_base_arr => c_base_arr,
g_width_arr => c_width_arr,
g_rd_latency_arr => c_rd_latency_arr,
g_pipeline_mosi => g_pipeline_mosi,
g_pipeline_miso_rdval => g_pipeline_miso_rdval,
g_pipeline_miso_wait => g_pipeline_miso_wait
)
PORT MAP (
mm_clk => mm_clk,
master_mosi => master_mosi,
master_miso => master_miso,
slave_mosi_arr => bus_mosi_arr,
slave_miso_arr => bus_miso_arr
);
-----------------------------------------------------------------------------
-- The MM bus interface with the MM slaves
-----------------------------------------------------------------------------
gen_slave_ports : FOR I IN 0 TO g_nof_slaves-1 GENERATE
-- Adapt the miso.waitrequest for slaves that use mosi flow control if the miso.waitrequest is pipelined in the mm_bus
u_slave_latency_adapter : ENTITY work.mm_latency_adapter
GENERIC MAP (
g_adapt => c_adapt_waitrequest
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
-- MM input RL = 1
in_mosi => bus_mosi_arr(I),
in_miso => bus_miso_arr(I),
-- MM output RL = 0
out_mosi => busw_mosi_arr(I),
out_miso => busw_miso_arr(I)
);
-- Rewire not connected slaves and slave that do not need mosi flow control via miso.waitrequest
u_slave_enable : ENTITY work.mm_slave_enable
GENERIC MAP (
g_enable => TRUE,
g_waitrequest => g_waitrequest,
g_rd_latency => c_rd_latency_arr(I)
)
PORT MAP (
mm_rst => mm_rst,
mm_clk => mm_clk,
-- MM input RL = 1
in_mosi => busw_mosi_arr(I),
in_miso => busw_miso_arr(I),
-- MM output RL = 0
out_mosi => slave_mosi_arr(I),
out_miso => slave_miso_arr(I)
);
END GENERATE;
-----------------------------------------------------------------------------
-- Model the MM slaves
-----------------------------------------------------------------------------
gen_slaves : FOR I IN 0 TO g_nof_slaves-1 GENERATE
u_waitrequest_model : ENTITY work.mm_waitrequest_model u_waitrequest_model : ENTITY work.mm_waitrequest_model
GENERIC MAP ( GENERIC MAP (
g_waitrequest => g_waitrequest, g_waitrequest => g_waitrequest,
...@@ -190,22 +281,4 @@ BEGIN ...@@ -190,22 +281,4 @@ BEGIN
); );
END GENERATE; END GENERATE;
d_dut: ENTITY work.mm_bus
GENERIC MAP (
g_nof_slaves => g_nof_slaves,
g_base_arr => c_base_arr,
g_width_arr => c_width_arr,
g_rd_latency_arr => c_rd_latency_arr,
g_pipeline_mosi => g_pipeline_mosi,
g_pipeline_miso_rd => g_pipeline_miso_rd,
g_pipeline_miso_wait => g_pipeline_miso_wait
)
PORT MAP (
mm_clk => mm_clk,
master_mosi => master_mosi,
master_miso => master_miso,
slave_mosi_arr => slave_mosi_arr,
slave_miso_arr => slave_miso_arr
);
END tb; END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment