From a4bf76e9b4408f1d25e706b868f21d809c89abb2 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Thu, 20 Jul 2017 14:25:12 +0000
Subject: [PATCH] Added common_toggle_align.vhd with tb.

---
 libraries/base/common/hdllib.cfg              |   2 +
 .../common/src/vhdl/common_toggle_align.vhd   | 109 +++++++++++++
 .../common/tb/vhdl/tb_common_toggle_align.vhd | 144 ++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 libraries/base/common/src/vhdl/common_toggle_align.vhd
 create mode 100644 libraries/base/common/tb/vhdl/tb_common_toggle_align.vhd

diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg
index 364afa6f1f..ea74660cd7 100644
--- a/libraries/base/common/hdllib.cfg
+++ b/libraries/base/common/hdllib.cfg
@@ -56,6 +56,7 @@ synth_files =
     src/vhdl/common_evt.vhd
     src/vhdl/common_flank_to_pulse.vhd
     src/vhdl/common_toggle.vhd
+    src/vhdl/common_toggle_align.vhd
     src/vhdl/common_switch.vhd
     src/vhdl/common_request.vhd
     src/vhdl/common_counter.vhd
@@ -181,6 +182,7 @@ test_bench_files =
     tb/vhdl/tb_common_spulse.vhd
     tb/vhdl/tb_common_switch.vhd
     tb/vhdl/tb_common_toggle.vhd
+    tb/vhdl/tb_common_toggle_align.vhd
     tb/vhdl/tb_common_transpose.vhd
     tb/vhdl/tb_common_transpose_symbol.vhd
     tb/vhdl/tb_common_zip.vhd
diff --git a/libraries/base/common/src/vhdl/common_toggle_align.vhd b/libraries/base/common/src/vhdl/common_toggle_align.vhd
new file mode 100644
index 0000000000..54e66471a5
--- /dev/null
+++ b/libraries/base/common/src/vhdl/common_toggle_align.vhd
@@ -0,0 +1,109 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2017
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Author: Eric Kooistra,  20 jul 2017,   Created
+-- Purpose: Align output to the toggling input and maintain this toggling
+-- Description:
+--   The in_toggle has a toggle period of g_nof_clk_per_period clk cycles.
+--
+--   - When in_align = '1' then the out_toggle follows the in_toggle.
+--   - When in_align = '0' then the out_toggle maintains the current toggling
+--     independent of in_toggle
+--
+--   This compenent can be used to in_align to a certain input phase that is
+--   defined by the toggling in_toggle and then maintain this input phase 
+--   even when in_toggle stops toggling or change phase for some reason.
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+
+ENTITY common_toggle_align IS
+  GENERIC (
+    g_pipeline            : NATURAL := 1;  -- 0 for combinatorial to have out_toggle in phase with in_toggle, > 0 for pipelined out_toggle
+    g_nof_clk_per_period  : NATURAL := 4   -- must be even and >= 2
+  );
+  PORT (
+    rst         : IN  STD_LOGIC := '0';
+    clk         : IN  STD_LOGIC;
+    in_align    : IN  STD_LOGIC;
+    in_toggle   : IN  STD_LOGIC;
+    out_toggle  : OUT STD_LOGIC
+  );
+END;
+
+ARCHITECTURE rtl OF common_toggle_align IS
+  
+  SIGNAL prev_in_toggle       : STD_LOGIC;
+  SIGNAL in_toggle_revt       : STD_LOGIC;
+  
+  SIGNAL cnt_clr              : STD_LOGIC;
+  SIGNAL cnt                  : NATURAL RANGE 0 TO g_nof_clk_per_period-1;
+  SIGNAL nxt_cnt              : NATURAL;
+  
+  SIGNAL nxt_out_toggle       : STD_LOGIC;
+  
+BEGIN
+
+  p_reg : PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      cnt            <= 0;
+    ELSIF rising_edge(clk) THEN
+      cnt            <= nxt_cnt;
+      prev_in_toggle <= in_toggle;
+    END IF;
+  END PROCESS;
+  
+  -- detect rising edge of in_toggle period
+  in_toggle_revt <= '1' WHEN prev_in_toggle='0' AND in_toggle='1' ELSE '0';
+  
+  cnt_clr <= in_align AND in_toggle_revt;
+  
+  nxt_cnt <= 0 WHEN cnt_clr='1' OR cnt=g_nof_clk_per_period-1 ELSE cnt+1;
+  
+  -- align to input toggle or maintain output toggle
+  p_out_toggle : PROCESS (in_align, nxt_cnt)
+  BEGIN
+    IF in_align='1' THEN
+      -- align to incomming in_toggle
+      nxt_out_toggle <= in_toggle;
+    ELSE
+      -- maintain phase and period of incomming in_toggle that it was aligned to
+      IF nxt_cnt<g_nof_clk_per_period/2 THEN
+        nxt_out_toggle <= '1';
+      ELSE
+        nxt_out_toggle <= '0';
+      END IF;
+    END IF;
+  END PROCESS;
+  
+  u_common_pipeline_sl : ENTITY work.common_pipeline_sl
+  GENERIC MAP (
+    g_pipeline => g_pipeline
+  )
+  PORT MAP (
+    rst     => rst,
+    clk     => clk,
+    in_dat  => nxt_out_toggle,
+    out_dat => out_toggle
+  );
+  
+END rtl;
diff --git a/libraries/base/common/tb/vhdl/tb_common_toggle_align.vhd b/libraries/base/common/tb/vhdl/tb_common_toggle_align.vhd
new file mode 100644
index 0000000000..50a885d245
--- /dev/null
+++ b/libraries/base/common/tb/vhdl/tb_common_toggle_align.vhd
@@ -0,0 +1,144 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2017
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Author: Eric Kooistra, 20 jul 2017, Created
+-- Purpose: Test bench for common_toggle_align.vhd
+-- Usage:
+-- > as 10
+-- > run -all
+-- Observe out_toggle in Wave Window in relation to in_toggle and align
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE work.common_pkg.ALL;
+USE work.tb_common_pkg.ALL;
+
+ENTITY tb_common_toggle_align IS
+END tb_common_toggle_align;
+
+ARCHITECTURE tb OF tb_common_toggle_align IS
+
+  CONSTANT clk_period           : TIME := 10 ns;
+  
+  CONSTANT c_interval           : NATURAL := 10;
+  CONSTANT c_pipeline           : NATURAL := 0;
+  CONSTANT c_toggle_period      : NATURAL := 4;
+  CONSTANT c_half_period        : NATURAL := c_toggle_period/2;
+
+  SIGNAL tb_end     : STD_LOGIC := '0';
+  SIGNAL rst        : STD_LOGIC;
+  SIGNAL clk        : STD_LOGIC := '0';
+  SIGNAL in_align   : STD_LOGIC;
+  SIGNAL in_toggle  : STD_LOGIC;
+  SIGNAL out_toggle : STD_LOGIC;
+
+BEGIN
+
+  clk  <= NOT clk OR tb_end AFTER clk_period/2;
+  rst  <= '1', '0' AFTER 7 * clk_period;
+    
+  p_in_stimuli : PROCESS
+  BEGIN
+    in_align <= '1';
+    in_toggle <= '0';
+    proc_common_wait_until_low(clk, rst);
+    proc_common_wait_some_cycles(clk, 10);
+
+    ---------------------------------------------------------------------------
+    -- align
+    ---------------------------------------------------------------------------
+    
+    in_align <= '1';
+
+    -- start toggling    
+    FOR I IN 0 TO c_interval-1 LOOP
+      in_toggle <= NOT in_toggle;
+      proc_common_wait_some_cycles(clk, c_half_period);
+    END LOOP;
+    -- introduce a glitch in the toggling and check that out_toggle remains aligned
+    proc_common_wait_some_cycles(clk, 1);
+    FOR I IN 0 TO c_interval-1 LOOP
+      in_toggle <= NOT in_toggle;
+      proc_common_wait_some_cycles(clk, c_half_period);
+    END LOOP;
+    
+    ---------------------------------------------------------------------------
+    -- maintain
+    ---------------------------------------------------------------------------
+    in_align <= '0';
+
+    -- continue toggling    
+    FOR I IN 0 TO c_interval-1 LOOP
+      in_toggle <= NOT in_toggle;
+      proc_common_wait_some_cycles(clk, c_half_period);
+    END LOOP;
+    -- introduce a glitch in the toggling and check that out_toggle ignores the glitch
+    proc_common_wait_some_cycles(clk, 1);
+    FOR I IN 0 TO c_interval-1 LOOP
+      in_toggle <= NOT in_toggle;
+      proc_common_wait_some_cycles(clk, c_half_period);
+    END LOOP;
+    
+    ---------------------------------------------------------------------------
+    -- align again
+    ---------------------------------------------------------------------------
+    
+    in_align <= '1';
+
+    -- continue toggling and check that out_toggle aligns again
+    FOR I IN 0 TO c_interval-1 LOOP
+      in_toggle <= NOT in_toggle;
+      proc_common_wait_some_cycles(clk, c_half_period);
+    END LOOP;
+
+    ---------------------------------------------------------------------------
+    -- stop in_toggle
+    ---------------------------------------------------------------------------
+    proc_common_wait_some_cycles(clk, c_half_period*c_interval);
+    
+    ---------------------------------------------------------------------------
+    -- maintain after in_toggle has stopped
+    ---------------------------------------------------------------------------
+    in_align <= '0';
+    proc_common_wait_some_cycles(clk, c_half_period*c_interval);
+    
+    ---------------------------------------------------------------------------
+    -- end
+    ---------------------------------------------------------------------------
+    proc_common_wait_some_cycles(clk, 10);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+
+  u_toggle : ENTITY work.common_toggle_align
+  GENERIC MAP (
+    g_pipeline           => c_pipeline,
+    g_nof_clk_per_period => c_toggle_period
+  )
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    in_align    => in_align,
+    in_toggle   => in_toggle,
+    out_toggle  => out_toggle
+  );
+  
+END tb;
-- 
GitLab