Skip to content
Snippets Groups Projects
Select Git revision
  • bc0939d2c64da11bdece092eb7ff6e269ba4dae5
  • master default protected
  • L2SS-1914-fix_job_dispatch
  • TMSS-3170
  • TMSS-3167
  • TMSS-3161
  • TMSS-3158-Front-End-Only-Allow-Changing-Again
  • TMSS-3133
  • TMSS-3319-Fix-Templates
  • test-fix-deploy
  • TMSS-3134
  • TMSS-2872
  • defer-state
  • add-custom-monitoring-points
  • TMSS-3101-Front-End-Only
  • TMSS-984-choices
  • SDC-1400-Front-End-Only
  • TMSS-3079-PII
  • TMSS-2936
  • check-for-max-244-subbands
  • TMSS-2927---Front-End-Only-PXII
  • Before-Remove-TMSS
  • LOFAR-Release-4_4_318 protected
  • LOFAR-Release-4_4_317 protected
  • LOFAR-Release-4_4_316 protected
  • LOFAR-Release-4_4_315 protected
  • LOFAR-Release-4_4_314 protected
  • LOFAR-Release-4_4_313 protected
  • LOFAR-Release-4_4_312 protected
  • LOFAR-Release-4_4_311 protected
  • LOFAR-Release-4_4_310 protected
  • LOFAR-Release-4_4_309 protected
  • LOFAR-Release-4_4_308 protected
  • LOFAR-Release-4_4_307 protected
  • LOFAR-Release-4_4_306 protected
  • LOFAR-Release-4_4_304 protected
  • LOFAR-Release-4_4_303 protected
  • LOFAR-Release-4_4_302 protected
  • LOFAR-Release-4_4_301 protected
  • LOFAR-Release-4_4_300 protected
  • LOFAR-Release-4_4_299 protected
41 results

constraints.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ddrctrl_output_unpack.vhd 14.47 KiB
    -------------------------------------------------------------------------------
    --
    -- Copyright 2022
    -- 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: Job van Wee
    -- Purpose: resize the data into a single sosi with a width of g_out_data_w.
    --
    -- Description:
    --  The data gets collected into a vector(c_v) and from this vector the output
    --  data gets read. When the reading passes the halfway point of c_v new data
    --  is requested and the whole vector shifts g_in_data_w amount of bits to fit
    --  the new data at the end.
    --
    -- Remark:
    --  Use VHDL coding template from:
    --  https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
    --  The output vector must be larger than the input vector.
    
    LIBRARY IEEE, dp_lib, tech_ddr_lib, common_lib;
    USE IEEE.std_logic_1164.ALL;
    USE dp_lib.dp_stream_pkg.ALL;
    USE tech_ddr_lib.tech_ddr_pkg.ALL;
    USE common_lib.common_pkg.ALL;
    
    ENTITY ddrctrl_output_unpack IS
      GENERIC (
        g_tech_ddr      : t_c_tech_ddr;
        g_in_data_w     : NATURAL;
        g_out_data_w    : NATURAL;
        g_block_size    : NATURAL;
        g_bim           : NATURAL
      );
      PORT (
        clk             : IN  STD_LOGIC;
        rst             : IN  STD_LOGIC;
        in_sosi         : IN  t_dp_sosi   := c_dp_sosi_init;
        in_bsn          : IN  STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
        out_sosi        : OUT t_dp_sosi   := c_dp_sosi_init;
        out_ready       : OUT STD_LOGIC   := '0'
      );
    END ddrctrl_output_unpack;
    
    
    ARCHITECTURE rtl OF ddrctrl_output_unpack IS
    
      CONSTANT c_v_w  : NATURAL := g_in_data_w*2;
    
      -- type for statemachine
      TYPE t_state IS ( READING, FIRST_READ, OVER_HALF, BSN, RESET, IDLE, OFF);
    
      -- record for readability
      TYPE t_reg IS RECORD
      state           : t_state;
      a_of            : NATURAL;
      op_data_cnt     : NATURAL;
      delay_data      : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0);
      dd_fresh        : STD_LOGIC;
      valid_data      : STD_LOGIC;
      c_v             : STD_LOGIC_VECTOR(c_v_w-1 DOWNTO 0);
      bsn_cnt         : NATURAL;
      out_sosi        : t_dp_sosi;
      out_ready       : STD_LOGIC;
      END RECORD;
    
      CONSTANT c_t_reg_init   : t_reg     := (RESET, 0, 0, (OTHERS => '0'), '0', '0', (OTHERS => '0'), 0, c_dp_sosi_init, '0');
    
      -- signals for readability
      SIGNAL d_reg            : t_reg     := c_t_reg_init;
      SIGNAL q_reg            : t_reg     := c_t_reg_init;
    
    BEGIN
    
      q_reg <= d_reg WHEN rising_edge(clk);
    
      -- put the input data into c_v and fill the output vector from c_v
      p_state : PROCESS(q_reg, rst, in_sosi)
    
        VARIABLE v            : t_reg;
    
      BEGIN
    
        v := q_reg;
    
        CASE q_reg.state IS
        WHEN READING =>
          -- generating output from the data already present in c_v
          v.out_ready := '0';
          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
          v.out_sosi.valid := '1';
          v.bsn_cnt := q_reg.bsn_cnt+1;
          v.op_data_cnt := q_reg.op_data_cnt+1;
    
          IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh      := '0';
            v.valid_data    := '1';
          END IF;
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh := '1';
          END IF;
    
    
          IF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1')THEN
            v.state := OVER_HALF;
          ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '0' AND v.valid_data = '0' THEN
            v.state := IDLE;
          ELSE
            v.state := READING;
          END IF;
    
    
          IF q_reg.out_sosi.eop = '1' THEN
            v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := INCR_UVEC(q_reg.out_sosi.bsn, 1);
            v.out_sosi.eop  := '0';
            v.out_sosi.sop  := '1';
            v.bsn_cnt       := 0;
          ELSIF q_reg.out_sosi.sop = '1' THEN
            v.out_sosi.sop  := '0';
          END IF;
    
          IF q_reg.bsn_cnt = g_block_size-3 THEN
            v.state         := BSN;
            v.out_ready     := '1';
          END IF;
    
    
    
        WHEN OVER_HALF =>
          -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added
          IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
            v.out_ready       := '1';
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            -- put the delay data into the first half of c_v
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh        := '0';
            v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
            v.op_data_cnt     := 0;
          ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
            v.out_ready       := '1';
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            -- put zeros into the second half of c_v beceause dd_fresh is '0'
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
            v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
            v.op_data_cnt     := 0;
            v.valid_data      := '0';
          ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
            v.out_ready       := '1';
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            v.dd_fresh        := '0';
            v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
            v.op_data_cnt     := 0;
          END IF;
    
    
     
    
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh      := '1';
          END IF;
    
          IF (g_out_data_w*(v.op_data_cnt+1))+v.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') THEN
            v.state         := OVER_HALF;
          ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' THEN
            v.state         := IDLE;
          ELSE
            v.state         := READING;
          END IF;
    
          IF q_reg.out_sosi.sop = '1' THEN
            v.out_sosi.sop  := '0';
          END IF;
    
          IF q_reg.bsn_cnt = g_block_size-3 THEN
            v.state         := BSN;
            v.dd_fresh      := '1';
          END IF;
    
    
        WHEN FIRST_READ =>
          -- fills the first half of c_v and generates a output from it.
          v.out_ready       := '0';
          v.c_v(c_v_w-1 DOWNTO 0)       := (OTHERS => '0');
          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
          v.dd_fresh        := '0';
          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v(g_out_data_w+v.a_of-1 DOWNTO v.a_of);
          v.out_sosi.valid  := '0';
          v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := in_bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
          v.out_sosi.sop    := '1';
          v.out_sosi.eop    := '0';
          v.bsn_cnt         := 0;
          v.op_data_cnt     := q_reg.op_data_cnt+1;
    
          IF v.dd_fresh = '1' AND v.valid_data = '0' THEN
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh      := '0';
            v.valid_data    := '1';
          END IF;
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh      := '1';
          END IF;
    
    
          v.state         := READING;
    
        WHEN BSN =>
          v.out_sosi.valid := '0';
          -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added
          IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            -- put the delay data into the first half of c_v
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh        := '0';
            v.op_data_cnt     := 0;
          ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            -- put zeros into the second half of c_v beceause dd_fresh is '0'
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
            v.op_data_cnt     := 0;
            v.valid_data      := '0';
          ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            -- put the second half of c_v into the first half of c_v
            v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;
            v.dd_fresh        := '0';
            v.op_data_cnt     := 0;
          ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w THEN
            -- generate output from the middle of c_v
            v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
            v.out_sosi.valid  := '1';
            v.bsn_cnt         := q_reg.bsn_cnt+1;        
          END IF;
    
          v.out_ready         := '0';
          v.out_sosi.eop      := '1';
          v.a_of              := 0;
          v.bsn_cnt           := q_reg.bsn_cnt+1;
    
          IF v.dd_fresh = '1' AND v.valid_data = '0' THEN
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh        := '0';
            v.valid_data      := '1';
          END IF;
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh        := '1';
          END IF;
    
          IF g_bim+TO_UINT(in_bsn)-1 = TO_UINT(v.out_sosi.bsn) THEN
            v.state           := OFF;
          ELSE
            v.state           := READING;
          END IF;
    
        WHEN RESET =>
          v := c_t_reg_init;
    
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh := '1';
          END IF;
          v.state := OFF;
    
    
        WHEN IDLE =>
          -- the statemachine goes to Idle when its finished or when its waiting on other components.
          v.out_ready := '1';
          v.out_sosi.valid := '0';
    
          IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
            -- put the delay data into the second half of c_v beceause these are now zeros
            v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh      := '0';
            v.valid_data    := '1';
          END IF;
          IF in_sosi.valid = '1' THEN
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh := '1';
          END IF;
    
    
          IF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '1'THEN
            v.state := OVER_HALF;
          ELSE
            v.state := IDLE;
          END IF;
    
    
    
        WHEN OFF =>
          -- the stamachine has a state off so it knows when to go to first read, it can't go to first read from IDLE
          v.out_ready := '1';
          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
          v.out_sosi  := c_dp_sosi_init;
    
          IF in_sosi.valid = '1' THEN
            v.state := FIRST_READ;
            v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
            v.dd_fresh := '1';
          ELSE
            v.state := OFF;
          END IF;
    
    
    
        END CASE;
    
        IF rst = '1' THEN
          v.state := RESET;
        END IF;
        d_reg <= v;
      END PROCESS;
    
      -- fill outputs
      out_sosi <= q_reg.out_sosi;
      out_ready <= q_reg.out_ready;
    
    
    END rtl;