OpenCores
URL https://opencores.org/ocsvn/dp_components/dp_components/trunk

Subversion Repositories dp_components

[/] [dp_components/] [trunk/] [dp_block_gen.vhd] - Rev 5

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- Copyright (C) 2011
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
 
-- Purpose : Generate the sosi control for a block of data under flow control
-- Description:
--   When enabled a block of g_nof_data words is output via src_out under flow
--   control by the ready. The ready depends on g_use_src_in:
--
--   . If g_use_src_in=TRUE then the src_in.ready is used and snk_in is
--     ignored. This can be used as a block reference input parallel to a
--     group of user inputs.
--     The g_preserve_* generics do not apply, because the snk_in is ignored.
--
--   . If g_use_src_in=FALSE then the src_in is not used and the snk_in data,
--     re, im are passed on and the snk_in.valid is used as ready. This can
--     be used as a BSN source that creates sync, bsn, sop and eop from
--     snk_in.valid for snk_in.data that has data not valid gaps. The
--     dp_bsn_source is similar but only supports data that is always valid.
--     The g_preserve_* generics can be used to preserve the corresponding
--     snk_in fields or to use the local generated values for this fields.
--
--   The first active ready starts the dp_block_gen. The first output block
--   will have a src_out.sync and every g_nof_blk_per_sync another
--   src_out.sync. Each block is marked by src_out.sop and src_out.eop. The
--   sop also marks the BSN. The BSN is the block sequence number that
--   increments for every block.
--
--   The snk_in.sop and snk_in.eop are always ignored, because g_nof_data
--   will set the src_out.sop/eop blocks.
--   
--   If g_preserve_sync=TRUE then src_out.sync = snk_in.sync, else the
--   src_out.sync is depends on the first ready and on g_nof_blk_per_sync.
--   
--   If g_preserve_bsn=TRUE then src_out.bsn = snk_in.bsn, else the
--   src_out.bsn is depends on the first ready and the initial g_bsn. If
--   g_preserve_bsn=TRUE then g_nof_data needs to match the snk_in.sop/eop
--   blocks.
--
--   If g_preserve_channel=TRUE then src_out.channel = snk_in.channel, else
--   the src_out.channel = g_channel.
--
-- Remarks:
-- . Ready latency (RL) = 1
-- . Alternatively consider using dp_block_gen_valid_arr.vhd or
--   dp_block_reshape.vhd.
 
 
LIBRARY IEEE, common_pkg_lib, dp_pkg_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_pkg_lib.common_pkg.ALL;
USE dp_pkg_lib.dp_stream_pkg.ALL; 
 
ENTITY dp_block_gen IS
  GENERIC (
    g_use_src_in         : BOOLEAN := TRUE;  -- when true use src_in.ready else use snk_in.valid for flow control
    g_nof_data           : POSITIVE := 1;    -- nof data per block
    g_nof_blk_per_sync   : POSITIVE := 8;
    g_empty              : NATURAL := 0;
    g_channel            : NATURAL := 0;
    g_error              : NATURAL := 0;
    g_bsn                : NATURAL := 0;
    g_preserve_sync      : BOOLEAN := FALSE;
    g_preserve_bsn       : BOOLEAN := FALSE;
    g_preserve_channel   : BOOLEAN := FALSE
  );             
  PORT (         
    rst        : IN  STD_LOGIC;
    clk        : IN  STD_LOGIC;
    -- Streaming sink
    snk_out    : OUT t_dp_siso;                   -- pass on src_in.xon, pass on or force snk_out.ready dependend on g_use_src_in
    snk_in     : IN  t_dp_sosi := c_dp_sosi_rst;
    -- Streaming source
    src_in     : IN  t_dp_siso := c_dp_siso_rdy;
    src_out    : OUT t_dp_sosi;
    -- MM control
    en         : IN  STD_LOGIC := '1'
  );
END dp_block_gen;
 
 
ARCHITECTURE rtl OF dp_block_gen IS
 
  TYPE t_state IS (s_sop, s_data, s_eop);
 
  TYPE t_reg IS RECORD  -- local registers
    state     : t_state;
    data_cnt  : NATURAL RANGE 0 TO g_nof_data;
    blk_cnt   : NATURAL RANGE 0 TO g_nof_blk_per_sync;
    bsn       : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
    src_out   : t_dp_sosi;
  END RECORD;
 
  CONSTANT c_reg_rst  : t_reg := (s_sop, 0, 0, TO_DP_BSN(g_bsn), c_dp_sosi_rst);
 
  SIGNAL ready     : STD_LOGIC;
 
  -- Define the local registers in t_reg record
  SIGNAL r         : t_reg;
  SIGNAL nxt_r     : t_reg;
 
BEGIN
 
  snk_out.ready <= src_in.ready WHEN g_use_src_in=TRUE ELSE '1';  -- force snk_out.ready = '1' when src_in.ready is not used
  snk_out.xon   <= src_in.xon;                                    -- always pass on siso.xon
 
  src_out <= r.src_out;
 
  p_clk : PROCESS(rst, clk)
  BEGIN
    IF rst='1' THEN
      r <= c_reg_rst;
    ELSIF rising_edge(clk) THEN
      r <= nxt_r;
    END IF;
  END PROCESS;  
 
  ready <= src_in.ready WHEN g_use_src_in=TRUE ELSE snk_in.valid;
 
  p_state : PROCESS(r, en, ready, snk_in)
  BEGIN
    nxt_r <= r;
 
    IF g_use_src_in=FALSE THEN
      nxt_r.src_out.data  <= snk_in.data;
      nxt_r.src_out.re    <= snk_in.re;
      nxt_r.src_out.im    <= snk_in.im;
    END IF;
 
    IF g_preserve_sync = FALSE THEN
      nxt_r.src_out.sync  <= '0';
    ELSE
      nxt_r.src_out.sync  <= snk_in.sync;
    END IF;
 
    nxt_r.src_out.valid <= '0';
    nxt_r.src_out.sop   <= '0';
    nxt_r.src_out.eop   <= '0';
 
    IF g_preserve_bsn=TRUE THEN
      nxt_r.src_out.bsn <= snk_in.bsn;
    END IF;
 
    IF g_preserve_channel=TRUE THEN
      nxt_r.src_out.channel <= snk_in.channel;
    END IF;
 
    CASE r.state IS
      WHEN s_sop =>
        nxt_r.data_cnt <= 0;            -- for clarity init data count to 0 (because it will become 1 anyway at sop)
        IF en='0' THEN                  -- if disabled then reset block generator and remain in this state
          nxt_r.blk_cnt <= 0;
          nxt_r.bsn     <= TO_DP_BSN(g_bsn);
        ELSE                            -- enabled block generator
          IF ready='1' THEN             -- once enabled the complete block will be output dependent on the flow control
            -- use input sync or create local sync
            IF g_preserve_sync = FALSE THEN
              IF r.blk_cnt=0 THEN
                nxt_r.src_out.sync  <= '1';              -- use local sync for this block, local sync starts at first ready
              END IF;
              IF r.blk_cnt>=g_nof_blk_per_sync-1 THEN    -- maintain local sync interval
                nxt_r.blk_cnt <= 0;
              ELSE
                nxt_r.blk_cnt <= r.blk_cnt+1;
              END IF;
            END IF;
            nxt_r.src_out.valid   <= '1';
            nxt_r.src_out.sop     <= '1';
 
            -- use input bsn or create local bsn
            IF g_preserve_bsn=FALSE THEN
              nxt_r.bsn             <= INCR_UVEC(r.bsn, 1);  -- increment local bsn for next block
              nxt_r.src_out.bsn     <= r.bsn;                -- use local bsn for this block
            END IF;
 
            -- use input channel or create fixed local channel
            IF g_preserve_channel=FALSE THEN
              nxt_r.src_out.channel <= TO_DP_CHANNEL(g_channel);
            END IF;
 
            IF g_nof_data=1 THEN
              nxt_r.src_out.eop   <= '1';  -- single word block
              nxt_r.src_out.empty <= TO_DP_EMPTY(g_empty);
              nxt_r.src_out.err   <= TO_DP_ERROR(g_error);
            ELSIF g_nof_data=2 THEN
              nxt_r.data_cnt <= 1;      -- start of two word block
              nxt_r.state <= s_eop;
            ELSE
              nxt_r.data_cnt <= 1;      -- start of multi word block
              nxt_r.state <= s_data;
            END IF;
          END IF;
        END IF;
      WHEN s_data =>
        IF ready='1' THEN
          nxt_r.data_cnt <= r.data_cnt+1;
          nxt_r.src_out.valid <= '1';
          IF r.data_cnt=g_nof_data-2 THEN
            nxt_r.state <= s_eop;
          END IF;
        END IF;
      WHEN OTHERS =>  -- s_eop
        IF ready='1' THEN
          nxt_r.src_out.valid <= '1';
          nxt_r.src_out.eop   <= '1';
          nxt_r.src_out.empty <= TO_DP_EMPTY(g_empty);
          nxt_r.src_out.err   <= TO_DP_ERROR(g_error);
          nxt_r.state <= s_sop;
        END IF;
    END CASE;
  END PROCESS;  
 
END rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.