From 6406f6eb1502dfda0b0c928a4fc4589f0cb9e6c8 Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Wed, 19 Jul 2017 10:12:47 +0000
Subject: [PATCH] Initial commit of dp_xonoff_reg_timeout, amodified version of
 dp_xonoff_reg to allow a timeout. Also modified mms_dp_xonoff to be able to
 use the timeout function by setting the g_timeout_time generic

---
 libraries/base/dp/hdllib.cfg                  |   2 +
 .../dp/src/vhdl/dp_xonoff_reg_timeout.vhd     | 158 ++++++++++++++++++
 libraries/base/dp/src/vhdl/mms_dp_xonoff.vhd  |  68 +++++---
 .../dp/tb/vhdl/tb_dp_xonoff_reg_timeout.vhd   | 125 ++++++++++++++
 4 files changed, 333 insertions(+), 20 deletions(-)
 create mode 100644 libraries/base/dp/src/vhdl/dp_xonoff_reg_timeout.vhd
 create mode 100644 libraries/base/dp/tb/vhdl/tb_dp_xonoff_reg_timeout.vhd

diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index c6dc1c195a..d9b58f17da 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -17,6 +17,7 @@ synth_files =
     src/vhdl/dp_frame_busy_arr.vhd
     src/vhdl/dp_xonoff.vhd
     src/vhdl/dp_xonoff_reg.vhd
+    src/vhdl/dp_xonoff_reg_timeout.vhd
     src/vhdl/mms_dp_xonoff.vhd
     src/vhdl/dp_flush.vhd
     src/vhdl/dp_latency_increase.vhd
@@ -210,6 +211,7 @@ test_bench_files =
     tb/vhdl/tb_dp_shiftram.vhd
     tb/vhdl/tb_dp_xonoff.vhd
     tb/vhdl/tb_mms_dp_xonoff.vhd
+    tb/vhdl/tb_dp_xonoff_reg_timeout.vhd
     tb/vhdl/tb_dp_sync_insert.vhd
     tb/vhdl/tb_dp_folder.vhd
     tb/vhdl/tb_dp_switch.vhd
diff --git a/libraries/base/dp/src/vhdl/dp_xonoff_reg_timeout.vhd b/libraries/base/dp/src/vhdl/dp_xonoff_reg_timeout.vhd
new file mode 100644
index 0000000000..8ba17d2991
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_xonoff_reg_timeout.vhd
@@ -0,0 +1,158 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2013
+-- 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: Provide MM slave register for dp_xonoff with timeout
+-- Description:
+--
+--  Read/write register for stream enable/disable, disables <g_default_value> seconds after last enable write
+--
+--   31             24 23             16 15              8 7               0  wi
+--  |-----------------|-----------------|-----------------|-----------------|
+--  |                                                                     |X|  0
+--  |-----------------------------------------------------------------------|
+--
+--
+--
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+ENTITY dp_xonoff_reg_timeout IS
+  GENERIC ( 
+    g_default_value : STD_LOGIC := '1';
+    g_mm_timeout    : NATURAL   := 10; -- 10 Seconds, Max = 42
+    g_sim           : BOOLEAN   := FALSE -- When True, use micro seconds instead of seconds
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst            : IN  STD_LOGIC;
+    mm_clk            : IN  STD_LOGIC;
+    st_rst            : IN  STD_LOGIC;
+    st_clk            : IN  STD_LOGIC;
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in            : IN  t_mem_mosi;
+    sla_out           : OUT t_mem_miso;
+    
+    -- MM registers in st_clk domain
+    xonoff_reg        : OUT STD_LOGIC_VECTOR(0 DOWNTO 0)
+  );
+END dp_xonoff_reg_timeout;
+
+
+ARCHITECTURE str OF dp_xonoff_reg_timeout IS
+
+  CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
+                                  adr_w    => 1,
+                                  dat_w    => c_word_w,
+                                  nof_dat  => 1,
+                                  init_sl  => g_default_value);
+  CONSTANT c_mm_max_counter : NATURAL := sel_a_b(g_sim, g_mm_timeout * 50, g_mm_timeout * (50*10**6)); -- @50MHz                                
+  
+
+  SIGNAL mm_xonoff_reg     : STD_LOGIC_VECTOR(0 DOWNTO 0);
+  SIGNAL mm_xonoff_reg_out : STD_LOGIC_VECTOR(0 DOWNTO 0);
+  SIGNAL counter           : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+  SIGNAL cnt_clr           : STD_LOGIC := '0';
+  SIGNAL cnt_en            : STD_LOGIC := '1';
+  
+  
+
+BEGIN
+
+  p_mm_reg : PROCESS (mm_rst, mm_clk)
+  BEGIN
+    IF mm_rst = '1' THEN
+      -- Read access
+      sla_out   <= c_mem_miso_rst;
+      -- Write access, register values
+      mm_xonoff_reg(0) <= g_default_value; 
+   
+    ELSIF rising_edge(mm_clk) THEN
+      -- Read access defaults
+      sla_out.rdval <= '0';
+      cnt_clr <= '0';
+      -- Check if timeout is reached
+      IF TO_UINT(counter) >= c_mm_max_counter THEN
+        cnt_en <= '0';
+        mm_xonoff_reg_out(0) <= '0';
+      ELSE
+        mm_xonoff_reg_out <= mm_xonoff_reg;
+      END IF;
+      
+      -- Write access: set register value
+      IF sla_in.wr = '1' THEN
+        CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS
+          WHEN 0 =>            
+            mm_xonoff_reg(0) <= sla_in.wrdata(0);
+            IF sla_in.wrdata(0) = '1' THEN
+               cnt_clr <= '1';
+               cnt_en  <= '1';
+            END IF;
+                  
+          WHEN OTHERS => NULL;  -- not used MM addresses
+        END CASE;
+        
+      -- Read access: get register value
+      ELSIF sla_in.rd = '1' THEN
+        sla_out       <= c_mem_miso_rst;    -- set unused rddata bits to '0' when read
+        sla_out.rdval <= '1';               -- c_mm_reg.latency = 1
+        CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS
+          -- Read Block Sync
+          WHEN 0 =>            
+            sla_out.rddata(0) <= mm_xonoff_reg(0);
+   
+          WHEN OTHERS => NULL;  
+        END CASE;
+      END IF;
+    END IF;
+  END PROCESS;
+  
+  
+  
+  u_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_latency  => 0
+  )
+  PORT MAP (
+    rst        => mm_rst,
+    clk        => mm_clk,    
+    cnt_clr    => cnt_clr,
+    cnt_en     => cnt_en,
+    count      => counter 
+  );
+    
+  u_reg_cross_domain : ENTITY common_lib.common_reg_cross_domain
+  PORT MAP (
+    in_rst     => mm_rst,
+    in_clk     => mm_clk,
+
+    in_dat     => mm_xonoff_reg_out,
+
+    out_rst    => st_rst,
+    out_clk    => st_clk,
+
+    out_dat    => xonoff_reg
+  );
+
+END str;
diff --git a/libraries/base/dp/src/vhdl/mms_dp_xonoff.vhd b/libraries/base/dp/src/vhdl/mms_dp_xonoff.vhd
index f75d56a371..c413ec5a69 100644
--- a/libraries/base/dp/src/vhdl/mms_dp_xonoff.vhd
+++ b/libraries/base/dp/src/vhdl/mms_dp_xonoff.vhd
@@ -31,7 +31,9 @@ ENTITY mms_dp_xonoff IS
     g_nof_streams     : NATURAL := 1;
     g_combine_streams : BOOLEAN := FALSE;
     g_bypass          : BOOLEAN := FALSE;
-    g_default_value   : STD_LOGIC := '1'
+    g_default_value   : STD_LOGIC := '1';
+    g_timeout_time    : NATURAL := 0;
+    g_sim             : BOOLEAN := FALSE
   );
   PORT (
     -- Memory-mapped clock domain
@@ -82,25 +84,51 @@ BEGIN
   );
 
   gen_reg : FOR i IN 0 TO c_nof_ctrl_streams-1 GENERATE
-    u_reg : ENTITY work.dp_xonoff_reg
-    GENERIC MAP(
-      g_default_value => g_default_value
-    )
-    PORT MAP (
-      -- Clocks and reset
-      mm_rst       => mm_rst,
-      mm_clk       => mm_clk,
-      st_rst       => dp_rst,
-      st_clk       => dp_clk,
-      
-      -- Memory Mapped Slave in mm_clk domain
-      sla_in       => reg_mosi_arr(i),
-      sla_out      => reg_miso_arr(i),
-      
-      -- MM registers in dp_clk domain
-      -- . control
-      xonoff_reg   => xonoff_reg(i DOWNTO i)
-    );
+    gen_no_timeout : IF g_timeout_time = 0 GENERATE 
+      u_reg : ENTITY work.dp_xonoff_reg
+      GENERIC MAP(
+        g_default_value => g_default_value
+      )
+      PORT MAP (
+        -- Clocks and reset
+        mm_rst       => mm_rst,
+        mm_clk       => mm_clk,
+        st_rst       => dp_rst,
+        st_clk       => dp_clk,
+        
+        -- Memory Mapped Slave in mm_clk domain
+        sla_in       => reg_mosi_arr(i),
+        sla_out      => reg_miso_arr(i),
+        
+        -- MM registers in dp_clk domain
+        -- . control
+        xonoff_reg   => xonoff_reg(i DOWNTO i)
+      );
+    END GENERATE;
+    
+    gen_with_timeout : IF g_timeout_time > 0 GENERATE
+      u_reg : ENTITY work.dp_xonoff_reg_timeout
+      GENERIC MAP(
+        g_default_value => g_default_value,
+        g_mm_timeout    => g_timeout_time,
+        g_sim           => g_sim
+      )
+      PORT MAP (
+        -- Clocks and reset
+        mm_rst       => mm_rst,
+        mm_clk       => mm_clk,
+        st_rst       => dp_rst,
+        st_clk       => dp_clk,
+        
+        -- Memory Mapped Slave in mm_clk domain
+        sla_in       => reg_mosi_arr(i),
+        sla_out      => reg_miso_arr(i),
+        
+        -- MM registers in dp_clk domain
+        -- . control
+        xonoff_reg   => xonoff_reg(i DOWNTO i)
+      );   
+    END GENERATE; 
   END GENERATE;    
 
   xonoff_reg_i <= xonoff_reg WHEN g_combine_streams = FALSE ELSE (OTHERS => xonoff_reg(0));
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_xonoff_reg_timeout.vhd b/libraries/base/dp/tb/vhdl/tb_dp_xonoff_reg_timeout.vhd
new file mode 100644
index 0000000000..f59127d7b8
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_xonoff_reg_timeout.vhd
@@ -0,0 +1,125 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>.
+--
+-------------------------------------------------------------------------------
+
+
+--
+-- Usage:
+--   > as 10
+--   > run -all
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+
+
+ENTITY tb_dp_xonoff_reg_timeout IS
+END tb_dp_xonoff_reg_timeout;
+
+
+ARCHITECTURE tb OF tb_dp_xonoff_reg_timeout IS
+
+  CONSTANT clk_period : TIME := 20 ns;  -- 50 MHz
+  CONSTANT st_clk_period : TIME := 5000 ps;  -- 200 MHz
+  
+  
+  -- Minimum nof clk cycles between eop and sop
+  CONSTANT c_500ns_latency : NATURAL := 500/20;
+  CONSTANT c_timeout_2us   : NATURAL := 2000/20; 
+
+  SIGNAL tb_end        : STD_LOGIC := '0';
+  SIGNAL clk           : STD_LOGIC := '1';
+  SIGNAL st_clk        : STD_LOGIC := '1';
+  SIGNAL rst           : STD_LOGIC;
+  
+  SIGNAL sla_in_mosi   : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL sla_out_miso  : t_mem_miso := c_mem_miso_rst;
+  
+  SIGNAL xonoff_reg    : STD_LOGIC_VECTOR(0 DOWNTO 0);
+    
+BEGIN
+
+  clk <= NOT clk OR tb_end AFTER clk_period/2;
+  st_clk <= NOT st_clk OR tb_end AFTER st_clk_period/2;
+  rst <= '1', '0' AFTER 3*clk_period;
+  
+  p_stimuli : PROCESS
+  BEGIN
+
+    WAIT UNTIL rst='0';
+    FOR I IN 0 TO c_500ns_latency-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
+    
+    ----------------------------------------------------------------------------
+    -- First
+    ----------------------------------------------------------------------------
+    sla_in_mosi.wrdata(0) <= '1';
+    sla_in_mosi.wr <= '1';
+    WAIT UNTIL rising_edge(clk);
+    sla_in_mosi.wrdata(0) <= '0';
+    sla_in_mosi.wr <= '0';
+    FOR I IN 0 TO c_500ns_latency-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
+    ASSERT xonoff_reg(0)='1' REPORT "xonoff_reg was not set correctly" SEVERITY ERROR;
+    
+    sla_in_mosi.wrdata(0) <= '1';
+    sla_in_mosi.wr <= '1';
+    WAIT UNTIL rising_edge(clk);
+    sla_in_mosi.wrdata(0) <= '0';
+    sla_in_mosi.wr <= '0';
+    FOR I IN 0 TO c_timeout_2us-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
+    ASSERT xonoff_reg(0)='0' REPORT "Timeout did not work" SEVERITY ERROR;
+    
+    sla_in_mosi.wrdata(0) <= '1';
+    sla_in_mosi.wr <= '1';
+    WAIT UNTIL rising_edge(clk);
+    sla_in_mosi.wrdata(0) <= '0';
+    sla_in_mosi.wr <= '0';
+    FOR I IN 0 TO c_500ns_latency-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
+    ASSERT xonoff_reg(0)='1' REPORT "xonoff_reg was not set correctly after recovering from timeout" SEVERITY ERROR;
+    tb_end <= '1';
+    ASSERT FALSE REPORT "Simulation tb_dp_xonoff_reg_timeout finished." SEVERITY NOTE;
+    WAIT;
+  END PROCESS;
+  
+  
+
+  
+  u_dut : ENTITY work.dp_xonoff_reg_timeout
+  GENERIC MAP (
+    g_mm_timeout  => 1,
+    g_sim         => TRUE
+  )
+  PORT MAP (
+    mm_rst        => rst,
+    mm_clk        => clk,
+    st_rst        => rst,
+    st_clk        => st_clk,
+    
+    sla_in        => sla_in_mosi,
+    sla_out       => sla_out_miso,
+    
+    xonoff_reg    => xonoff_reg
+  );
+
+END tb;
-- 
GitLab