Skip to content
Snippets Groups Projects
Select Git revision
  • 1657b9bf32753dc7ae0d986b1b4f5e28b7521aa8
  • master default protected
  • L2SDP-1137
  • L2SDP-LIFT
  • L2SDP-1113
  • HPR-158
6 results

mm_pipeline.vhd

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    mm_pipeline.vhd 5.66 KiB
    -------------------------------------------------------------------------------
    --
    -- 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: Pipeline MM mosi
    -- Description:
    --   The mm_pipeline mosi registers the in_mosi if g_pipeline = TRUE, else it
    --   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:
    -- * The mm_pipeline could be optimized regarding the miso.waitrequest flow
    --   control if it would be implemented similar as dp_pipeline.vhd. This
    --   involves using the pipeline register to accept an access when it is
    --   empty. In this way the waitrequest to the in_mosi only needs to apply
    --   when the out_miso is not ready and the pipeline is full. The advantage
    --   of simply registering in_mosi and wiring in_miso is that it is simpler
    --   and does not put extra logic into the combinatorial miso.waitrequest
    --   path.
    
    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_pipeline IS
      GENERIC (
        g_pipeline    : BOOLEAN := TRUE
      );
      PORT (
        mm_rst        : IN  STD_LOGIC;
        mm_clk        : IN  STD_LOGIC;
        in_mosi       : IN  t_mem_mosi;
        in_miso       : OUT t_mem_miso;
        out_mosi      : OUT t_mem_mosi;
        out_miso      : IN  t_mem_miso
      );
    END mm_pipeline;
    
    
    ARCHITECTURE rtl OF mm_pipeline IS
    
      SIGNAL mosi_reg     : t_mem_mosi := c_mem_mosi_rst;
      SIGNAL nxt_mosi_reg : t_mem_mosi;
      SIGNAL ready        : STD_LOGIC;
    
    BEGIN
    
      -- Pass on miso
      in_miso <= out_miso;
    
      -- Pipeline the mosi when g_pipeline = TRUE, else default to wires
      gen_wires : IF g_pipeline = FALSE GENERATE
        out_mosi <= in_mosi;
      END GENERATE;
      
      gen_pipeline : IF g_pipeline = TRUE GENERATE
        p_reg : PROCESS(mm_rst, mm_clk)
        BEGIN
          IF mm_rst = '1' THEN
            mosi_reg <= c_mem_mosi_rst;
          ELSIF rising_edge(mm_clk) THEN
            mosi_reg <= nxt_mosi_reg;
          END IF;
        END PROCESS;
        
        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;