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

Fixed mm_pipeline to support g_pipeline_mosi.

parent 3a1170b8
No related branches found
No related tags found
2 merge requests!28Master,!15Resolve L2SDP-27
...@@ -37,9 +37,6 @@ ...@@ -37,9 +37,6 @@
-- pulse would yield a different pipelining of the address for write and -- pulse would yield a different pipelining of the address for write and
-- for read, which is akward. Therefore assume that both mosi write and -- for read, which is akward. Therefore assume that both mosi write and
-- mosi read have the same pipelining. -- mosi read have the same pipelining.
-- When g_pipeline_miso_wait = TRUE then it is not necessary to use
-- g_pipeline_mosi = TRUE, because the MM latency adapter that recovers
-- the timing of the waitrequest also pipelines the mosi.
-- --
-- * g_pipeline_miso_rdval -- * g_pipeline_miso_rdval
-- Pipelining the miso read data increases the read latency. -- Pipelining the miso read data increases the read latency.
...@@ -57,9 +54,28 @@ ...@@ -57,9 +54,28 @@
-- Usage: -- Usage:
-- See mm_bus.vhd -- See mm_bus.vhd
-- --
-- Remark:
-- * It is not allowed to simultaneously use g_pipeline_miso_wait = TRUE
-- and g_pipeline_mosi = TRUE, because this leads to a combinatorial loop
-- of the miso.waitrequest that is used at the output of the mm_pipeline
-- and at the input of the mm_latency adapter:
-- - at the mm_pipeline output the waitrequest gates the mosi.wr and rd
-- - at the mm_latency_adapter input in common_rl_decrease in the wr or
-- rd strobe is used to set the waitrequest.
-- This combinatorial loop seems unavoidable when the interface between
-- mm_pipeline and mm_latency_adpater is at RL = 0. A solution could be
-- to increase the RL at the output of the mm_pipeline to RL = 1 by
-- registering the waitrequest from the mm_latency_adapter. The total
-- RL for the input of the MM latency adapter then becomes RL = 2, so
-- then the mm_latency_adapter needs t oadapt from RL = 2 to 0.
-- Currently the mm_latency_adapter only supports RL 1 to 0. Is possible
-- to extent this to RL = N to 0, similar as in dp_latency_adapter.
-- However fortunately it is not necessary to support g_pipeline_mosi =
-- TRUE when g_pipeline_miso_wait = TRUE, because g_pipeline_miso_wait =
-- TRUE by itself already also pipeplines the mosi.
--
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
LIBRARY IEEE, common_lib; LIBRARY IEEE, common_lib;
USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL; USE common_lib.common_pkg.ALL;
...@@ -101,6 +117,10 @@ ARCHITECTURE str OF mm_bus_pipe IS ...@@ -101,6 +117,10 @@ ARCHITECTURE str OF mm_bus_pipe IS
BEGIN BEGIN
ASSERT NOT(g_pipeline_miso_wait = TRUE AND g_pipeline_mosi = TRUE)
REPORT "Do not use g_pipeline_mosi = TRUE if g_pipeline_miso_wait = TRUE"
SEVERITY FAILURE;
-- Master side -- Master side
m_mosi <= master_mosi; m_mosi <= master_mosi;
...@@ -145,10 +165,8 @@ BEGIN ...@@ -145,10 +165,8 @@ BEGIN
PORT MAP ( PORT MAP (
mm_rst => mm_rst, mm_rst => mm_rst,
mm_clk => mm_clk, mm_clk => mm_clk,
-- MM input RL = 1
in_mosi => bus_mosi_arr(I), in_mosi => bus_mosi_arr(I),
in_miso => bus_miso_arr(I), in_miso => bus_miso_arr(I),
-- MM output RL = 0
out_mosi => pipe_mosi_arr(I), out_mosi => pipe_mosi_arr(I),
out_miso => pipe_miso_arr(I) out_miso => pipe_miso_arr(I)
); );
......
...@@ -25,6 +25,57 @@ ...@@ -25,6 +25,57 @@
-- Description: -- Description:
-- The mm_pipeline mosi registers the in_mosi if g_pipeline = TRUE, else it -- The mm_pipeline mosi registers the in_mosi if g_pipeline = TRUE, else it
-- defaults to wires. -- defaults to wires.
--
-- Background information
-- The MM waitrequest resembles the behaviour of the streaming backpressure
-- ready for ready latency RL = 0. For RL = 0 the ready acts as an
-- acknowledge to pending data. For RL > 0 the ready acts as a request for
-- new data. The miso.waitrequest is defined for RL = 0 but for analysis
-- the timing diagrams below show an example of both RL = 0 and RL = 1.
--
-- * RL=1
-- _ _ _ _ _ _ _ _ _ _ _ _
-- clk _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
--
-- in_dat |a |b |c |d
-- _________ ___ ___
-- in_val |_______| |_______| |_______________
-- _____ ___ _______ ___________
-- ready |_______| |___|... |_______|...........
-- _________ ___ _______ _______
-- reg_ready |_______| |___|... |_______|.......
--
-- reg_dat |a |b |c |d
-- _____________________________ ___________
-- reg_val |___| |___
-- _________ ___ ___ ___
-- out_val |a |_______|b |___|c |___________|d |___
--
--
-- * RL=0
-- _ _ _ _ _ _ _ _ _ _ _ _ _
-- clk _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
--
-- in_dat |a |b |c |d |e
-- _________ _______________ ___
-- in_val |_______| |_______| |_______
-- _____________ ___ _______ ___________
-- ack |_______| |___| |___|
--
-- reg_dat |a |b |c |d |e
-- _____________ ___________ ___
-- reg_val |___________| |_______| |___
-- _____________ _______ ___
-- out_val |a |b |_______________|c |d |_______|e |___
--
-- In these timing diagrams the out_ready is wired to the in_ready, so
-- therefore they are identical and called ready.
-- The ready for RL = 0 or the reg_ready for RL = 1 is used to gate the
-- out_val. The ready/reg_ready is used and not the in_val, because by
-- using the ready/reg_ready the pipeline register is emptied as soon
-- as the ready is active, rather than to wait for a next in_val to push
-- it out.
--
-- Remark: -- Remark:
-- * The mm_pipeline could be optimized regarding the miso.waitrequest flow -- * The mm_pipeline could be optimized regarding the miso.waitrequest flow
-- control if it would be implemented similar as dp_pipeline.vhd. This -- control if it would be implemented similar as dp_pipeline.vhd. This
...@@ -47,10 +98,8 @@ ENTITY mm_pipeline IS ...@@ -47,10 +98,8 @@ ENTITY mm_pipeline IS
PORT ( PORT (
mm_rst : IN STD_LOGIC; mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC; mm_clk : IN STD_LOGIC;
-- MM input RL = 1
in_mosi : IN t_mem_mosi; in_mosi : IN t_mem_mosi;
in_miso : OUT t_mem_miso; in_miso : OUT t_mem_miso;
-- MM output RL = 0
out_mosi : OUT t_mem_mosi; out_mosi : OUT t_mem_mosi;
out_miso : IN t_mem_miso out_miso : IN t_mem_miso
); );
...@@ -59,24 +108,42 @@ END mm_pipeline; ...@@ -59,24 +108,42 @@ END mm_pipeline;
ARCHITECTURE rtl OF mm_pipeline IS ARCHITECTURE rtl OF mm_pipeline IS
SIGNAL in_mosi_reg : t_mem_mosi := c_mem_mosi_rst; SIGNAL mosi_reg : t_mem_mosi := c_mem_mosi_rst;
SIGNAL nxt_mosi_reg : t_mem_mosi;
SIGNAL ready : STD_LOGIC;
BEGIN BEGIN
-- Pass on miso -- Pass on miso
in_miso <= out_miso; in_miso <= out_miso;
-- Optionally pipeline the mosi -- Pipeline the mosi when g_pipeline = TRUE, else default to wires
--in_mosi_reg <= in_mosi WHEN rising_edge(mm_clk); -- without mm_rst gen_wires : IF g_pipeline = FALSE GENERATE
p_reg : PROCESS(mm_rst, mm_clk) -- with mm_rst out_mosi <= in_mosi;
END GENERATE;
gen_pipeline : IF g_pipeline = TRUE GENERATE
p_reg : PROCESS(mm_rst, mm_clk)
BEGIN BEGIN
IF mm_rst = '1' THEN IF mm_rst = '1' THEN
in_mosi_reg <= c_mem_mosi_rst; mosi_reg <= c_mem_mosi_rst;
ELSIF rising_edge(mm_clk) THEN ELSIF rising_edge(mm_clk) THEN
in_mosi_reg <= in_mosi; mosi_reg <= nxt_mosi_reg;
END IF; END IF;
END PROCESS; END PROCESS;
out_mosi <= in_mosi_reg WHEN g_pipeline = TRUE ELSE in_mosi; ready <= NOT out_miso.waitrequest;
nxt_mosi_reg <= in_mosi WHEN ready = '1' ELSE mosi_reg;
p_out_mosi : PROCESS(mosi_reg, ready)
BEGIN
out_mosi <= mosi_reg;
IF ready /= '1' THEN
out_mosi.wr <= '0'; -- out_mosi.wr = mosi_reg.wr AND ready
out_mosi.rd <= '0'; -- out_mosi.rd = mosi_reg.rd AND ready
END IF;
END PROCESS;
END GENERATE;
END rtl; END rtl;
...@@ -48,20 +48,20 @@ BEGIN ...@@ -48,20 +48,20 @@ BEGIN
-- g_pipeline_miso_rdval : BOOLEAN := TRUE; -- g_pipeline_miso_rdval : BOOLEAN := TRUE;
-- g_pipeline_miso_wait : BOOLEAN := FALSE -- g_pipeline_miso_wait : BOOLEAN := FALSE
--u_no_pipe : ENTITY work.tb_mm_bus GENERIC MAP (16, 0, 3, 1, FALSE, FALSE, FALSE, FALSE); u_no_pipe : ENTITY work.tb_mm_bus GENERIC MAP (16, 0, 3, 1, FALSE, FALSE, FALSE, FALSE);
--u_no_pipe_base_offset : ENTITY work.tb_mm_bus GENERIC MAP (16, 3*2**4, 4, 1, FALSE, FALSE, FALSE, FALSE); u_no_pipe_base_offset : ENTITY work.tb_mm_bus GENERIC MAP (16, 3*2**4, 4, 1, FALSE, FALSE, FALSE, FALSE);
--u_pipe_mosi : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, FALSE, TRUE, FALSE, FALSE); u_pipe_mosi : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, FALSE, TRUE, FALSE, FALSE);
--u_pipe_mosi_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, FALSE, TRUE, TRUE, FALSE); u_pipe_mosi_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, FALSE, TRUE, TRUE, FALSE);
--u_waitrequest_no_pipe : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, TRUE, FALSE, FALSE, FALSE); u_waitrequest_no_pipe : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, TRUE, FALSE, FALSE, FALSE);
--u_waitrequest_pipe_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, TRUE, FALSE, TRUE, FALSE); u_waitrequest_pipe_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 1, TRUE, FALSE, TRUE, FALSE);
--u_waitrequest_pipe_miso_rdval2 : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 2, TRUE, FALSE, TRUE, FALSE); u_waitrequest_pipe_miso_rdval2 : ENTITY work.tb_mm_bus GENERIC MAP ( 3, 0, 4, 2, TRUE, FALSE, TRUE, FALSE);
--u_waitrequest_pipe_miso_wait : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, FALSE, FALSE, TRUE); u_waitrequest_pipe_miso_wait : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, FALSE, FALSE, TRUE);
u_waitrequest_pipe_mosi_one : ENTITY work.tb_mm_bus GENERIC MAP ( 1, 0, 4, 1, TRUE, TRUE, FALSE, FALSE);
u_waitrequest_pipe_mosi : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, FALSE, FALSE);
u_waitrequest_pipe_mosi_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, TRUE, FALSE);
-- To do: -- Do not support simultaneous g_pipeline_mosi = TRUE and g_pipeline_miso_wait = TRUE, see mm_bus_pipe.vhd.
u_waitrequest_pipe_mosi : ENTITY work.tb_mm_bus GENERIC MAP ( 1, 0, 4, 1, TRUE, TRUE, FALSE, FALSE);
--u_waitrequest_pipe_mosi : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, FALSE, FALSE);
--u_waitrequest_pipe_mosi_miso_rdval : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, TRUE, FALSE);
--u_waitrequest_pipe_mosi_miso_wait : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, FALSE, TRUE); --u_waitrequest_pipe_mosi_miso_wait : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, FALSE, TRUE);
--u_waitrequest_pipe_mosi_miso : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, TRUE, TRUE); --u_waitrequest_pipe_all : ENTITY work.tb_mm_bus GENERIC MAP ( 2, 0, 4, 1, TRUE, TRUE, TRUE, TRUE);
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