From 4da3811ead0ddbd71272908629138e7c7e6ec8a8 Mon Sep 17 00:00:00 2001
From: Daniel van der Schuur <schuur@astron.nl>
Date: Tue, 28 Feb 2017 14:14:26 +0000
Subject: [PATCH] -Instantiated mms_common_pulse_delay in ctrl_unb1_board;
 -Finished self-checking tb_common_pulse_delay.

---
 .../unb1_board/src/vhdl/ctrl_unb1_board.vhd   |  46 +++++--
 .../common/src/vhdl/common_pulse_delay.vhd    |  10 +-
 .../src/vhdl/mms_common_pulse_delay.vhd       |   3 +-
 .../common/tb/vhdl/tb_common_pulse_delay.vhd  | 112 ++++++++++++++----
 4 files changed, 134 insertions(+), 37 deletions(-)

diff --git a/boards/uniboard1/libraries/unb1_board/src/vhdl/ctrl_unb1_board.vhd b/boards/uniboard1/libraries/unb1_board/src/vhdl/ctrl_unb1_board.vhd
index ebaf63731a..db5d686f54 100644
--- a/boards/uniboard1/libraries/unb1_board/src/vhdl/ctrl_unb1_board.vhd
+++ b/boards/uniboard1/libraries/unb1_board/src/vhdl/ctrl_unb1_board.vhd
@@ -103,9 +103,7 @@ ENTITY ctrl_unb1_board IS
     ----------------------------------------------------------------------------
     -- PPS delay
     -- . Maximum number of dp_clk cycles that pps can be delayed. Actual number
-    --   is determined dynamically by MM register.
-    --   . 0  : Don't instantiate delay component. Does not add extra MM register.
-    --   . >0 : Instantiate delay component. Adds an extra MM register.
+    --   is determined dynamically by MM register reg_common_pulse_delay.
     ----------------------------------------------------------------------------
     g_pps_delay_max      : NATURAL := 0;
 
@@ -217,6 +215,10 @@ ENTITY ctrl_unb1_board IS
     -- PPSH
     reg_ppsh_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;
     reg_ppsh_miso          : OUT t_mem_miso;
+
+    -- Pulse (PPS) delay
+    reg_common_pulse_delay_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_common_pulse_delay_miso : OUT t_mem_miso := c_mem_miso_rst;
     
     -- eth1g control&monitoring
     eth1g_tse_clk_out      : OUT STD_LOGIC;
@@ -299,7 +301,8 @@ ARCHITECTURE str OF ctrl_unb1_board IS
   SIGNAL ext_clk                : STD_LOGIC;
   SIGNAL ext_pps                : STD_LOGIC;
   SIGNAL dp_dis                 : STD_LOGIC;
- 
+  SIGNAL mms_ppsh_pps_sys       : STD_LOGIC;
+
   SIGNAL node_ctrl_dp_clk_in    : STD_LOGIC := '0';
   SIGNAL node_ctrl_dp_rst_out   : STD_LOGIC;
  
@@ -595,11 +598,9 @@ BEGIN
   ------------------------------------------------------------------------------
   -- PPS input
   ------------------------------------------------------------------------------
-  
   u_mms_ppsh : ENTITY ppsh_lib.mms_ppsh
   GENERIC MAP (
-    g_st_clk_freq     => g_dp_clk_freq,
-    g_pps_delay_max   => g_pps_delay_max
+    g_st_clk_freq     => g_dp_clk_freq
   )
   PORT MAP (
     -- Clocks and reset
@@ -614,10 +615,35 @@ BEGIN
     reg_miso         => reg_ppsh_miso,
     
     -- Streaming clock domain
-    pps_sys          => dp_pps
+    pps_sys          => mms_ppsh_pps_sys
   );
-  
-  
+
+  ------------------------------------------------------------------------------
+  -- PPS delay
+  ------------------------------------------------------------------------------
+  gen_mms_common_pulse_delay : IF g_pps_delay_max>0 GENERATE
+    u_mms_common_pulse_delay : ENTITY common_lib.mms_common_pulse_delay
+    GENERIC MAP (
+      g_pulse_delay_max => g_pps_delay_max,
+      g_register_out    => TRUE 
+    )
+    PORT MAP (
+      pulse_clk => dp_clk_in,
+      pulse_rst => dp_rst_in,
+      pulse_in  => mms_ppsh_pps_sys,
+      pulse_out => dp_pps,
+
+      mm_clk    => mm_clk,
+      mm_rst    => i_mm_rst,
+      reg_mosi  => reg_common_pulse_delay_mosi,
+      reg_miso  => reg_common_pulse_delay_miso
+    );
+  END GENERATE;
+
+  no_mms_common_pulse_delay : IF g_pps_delay_max=0 GENERATE
+    dp_pps <= mms_ppsh_pps_sys;
+  END GENERATE;
+   
   ------------------------------------------------------------------------------
   -- I2C control for UniBoard sensors
   ------------------------------------------------------------------------------
diff --git a/libraries/base/common/src/vhdl/common_pulse_delay.vhd b/libraries/base/common/src/vhdl/common_pulse_delay.vhd
index 0fdc2489f5..19653c95fd 100644
--- a/libraries/base/common/src/vhdl/common_pulse_delay.vhd
+++ b/libraries/base/common/src/vhdl/common_pulse_delay.vhd
@@ -31,24 +31,24 @@ USE work.common_pkg.ALL;
 
 ENTITY common_pulse_delay IS
   GENERIC (
-    g_pulse_delay_max : NATURAL; -- Maximum delay value supported; determines internal counter width.
+    g_pulse_delay_max : NATURAL; -- Maximum delay value desired by user; determines internal counter width.
     g_register_out    : BOOLEAN  -- TRUE adds output register, adding 1 cycle of delay to the pulse_delay setting.
   );
   PORT (
     clk         : IN  STD_LOGIC;
     rst         : IN  STD_LOGIC;
     pulse_in    : IN  STD_LOGIC;
-    pulse_delay : IN  STD_LOGIC_VECTOR(ceil_log2(g_pulse_delay_max)-1 DOWNTO 0);
+    pulse_delay : IN  STD_LOGIC_VECTOR(ceil_log2(g_pulse_delay_max+1)-1 DOWNTO 0);
     pulse_out   : OUT STD_LOGIC
   );
 END ENTITY common_pulse_delay;
 
 ARCHITECTURE str OF common_pulse_delay IS
 
-  CONSTANT c_pulse_delay_max_width : NATURAL := ceil_log2(g_pulse_delay_max);
+  CONSTANT c_pulse_delay_max_width : NATURAL := ceil_log2(g_pulse_delay_max+1);
 
-  SIGNAL pulse_delay_reg       : STD_LOGIC_VECTOR(ceil_log2(g_pulse_delay_max)-1 DOWNTO 0);
-  SIGNAL nxt_pulse_delay_reg   : STD_LOGIC_VECTOR(ceil_log2(g_pulse_delay_max)-1 DOWNTO 0);
+  SIGNAL pulse_delay_reg       : STD_LOGIC_VECTOR(c_pulse_delay_max_width-1 DOWNTO 0);
+  SIGNAL nxt_pulse_delay_reg   : STD_LOGIC_VECTOR(c_pulse_delay_max_width-1 DOWNTO 0);
 
   SIGNAL common_counter_cnt_en : STD_LOGIC;
   SIGNAL common_counter_count  : STD_LOGIC_VECTOR(c_pulse_delay_max_width-1 DOWNTO 0);
diff --git a/libraries/base/common/src/vhdl/mms_common_pulse_delay.vhd b/libraries/base/common/src/vhdl/mms_common_pulse_delay.vhd
index 831ca0fed0..e8b7c951e5 100644
--- a/libraries/base/common/src/vhdl/mms_common_pulse_delay.vhd
+++ b/libraries/base/common/src/vhdl/mms_common_pulse_delay.vhd
@@ -33,7 +33,8 @@ USE technology_lib.technology_select_pkg.ALL;
 
 ENTITY mms_common_pulse_delay IS
   GENERIC (
-    g_pulse_delay_max : NATURAL := 0 -- Maximum number of clk cycles that pulse can be delayed
+    g_pulse_delay_max : NATURAL := 0; -- Maximum number of clk cycles that pulse can be delayed
+    g_register_out    : BOOLEAN
    );
   PORT (
     pulse_clk        : IN  STD_LOGIC;
diff --git a/libraries/base/common/tb/vhdl/tb_common_pulse_delay.vhd b/libraries/base/common/tb/vhdl/tb_common_pulse_delay.vhd
index 57451d455a..aecf97add5 100644
--- a/libraries/base/common/tb/vhdl/tb_common_pulse_delay.vhd
+++ b/libraries/base/common/tb/vhdl/tb_common_pulse_delay.vhd
@@ -24,6 +24,10 @@
 -- Purpose:
 -- . Feed different pulse_delay control settings to common_pulse_delay,
 --   verify correct pulse_out
+-- Usage:
+-- . as 8
+-- . run -a
+-- . if no failure messages are printed, TB ran OK.
 
 LIBRARY IEEE, common_lib;
 USE IEEE.STD_LOGIC_1164.ALL;
@@ -35,18 +39,50 @@ END tb_common_pulse_delay;
 
 ARCHITECTURE tb OF tb_common_pulse_delay IS
 
-  CONSTANT c_clk_period        : TIME := 5 ns;
-  CONSTANT c_pulse_delay_max   : NATURAL := 10;
-  CONSTANT c_pulse_delay_max_w : NATURAL := ceil_log2(c_pulse_delay_max);
-
-  SIGNAL tb_end          : STD_LOGIC := '0';
-  SIGNAL clk             : STD_LOGIC := '1';
-  SIGNAL rst             : STD_LOGIC := '1';
-  SIGNAL pulse_in        : STD_LOGIC;
-  SIGNAL nxt_pulse_in    : STD_LOGIC;
-  SIGNAL pulse_delay     : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
-  SIGNAL nxt_pulse_delay : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
-  SIGNAL pulse_out       : STD_LOGIC;
+  -----------------------------------------------------------------------------
+  -- common_pulse_delay parameters
+  -----------------------------------------------------------------------------
+  CONSTANT c_pulse_delay_max   : NATURAL := 100;
+  CONSTANT c_pulse_delay_max_w : NATURAL := ceil_log2(c_pulse_delay_max+1);
+
+  -----------------------------------------------------------------------------
+  -- Clock & reset
+  -----------------------------------------------------------------------------
+  CONSTANT c_clk_period : TIME := 5 ns;
+
+  SIGNAL clk            : STD_LOGIC := '1';
+  SIGNAL rst            : STD_LOGIC := '1';
+
+  -----------------------------------------------------------------------------
+  -- Stimuli
+  -----------------------------------------------------------------------------
+  SIGNAL pulse_in    : STD_LOGIC;
+  SIGNAL first_pulse : STD_LOGIC;
+  SIGNAL pulse_delay : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
+
+  -----------------------------------------------------------------------------
+  -- Verification
+  ----------------------------------------------------------------------------
+  CONSTANT c_nof_pulses             : NATURAL := pow2(ceil_log2(c_pulse_delay_max))-1;
+  CONSTANT c_init_cycles            : NATURAL := 12; -- Number of clock cycles for init (startup after reset)
+  CONSTANT c_total_delay_cycles     : NATURAL := (c_nof_pulses*(c_nof_pulses+1))/2; --sum of functional delays 1..c_nof_pulses
+  CONSTANT c_total_reg_delay_cycles : NATURAL := c_nof_pulses; -- 1 extra delay cycles is introduced for every pulse due to register
+  CONSTANT c_total_cycles           : NATURAL := c_init_cycles+c_total_delay_cycles+c_total_reg_delay_cycles;
+
+  SIGNAL tb_end                     : STD_LOGIC := '0';
+  SIGNAL pulse_delay_reg            : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
+  SIGNAL pulse_out                  : STD_LOGIC;
+  SIGNAL pulse_count                : NATURAL;
+  SIGNAL pulse_delay_count          : NATURAL;
+
+  -----------------------------------------------------------------------------
+  -- Registers
+  -----------------------------------------------------------------------------
+  SIGNAL nxt_pulse_in          : STD_LOGIC;
+  SIGNAL nxt_pulse_delay       : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
+  SIGNAL nxt_pulse_delay_reg   : STD_LOGIC_VECTOR(c_pulse_delay_max_w-1 DOWNTO 0);
+  SIGNAL nxt_pulse_count       : NATURAL;
+  SIGNAL nxt_pulse_delay_count : NATURAL;
   
 BEGIN
 
@@ -60,8 +96,9 @@ BEGIN
   -- Stimuli
   -----------------------------------------------------------------------------
   -- Create the first pulse here, then feed pulse_out to pulse
-  nxt_pulse_in <= '1'; --FIXME
-
+  first_pulse <= '0', '1' AFTER 10*c_clk_period, '0' AFTER 11*c_clk_period;
+  nxt_pulse_in <= first_pulse or pulse_out;
+  -- Make next pulse delay 1 cycle longer
   nxt_pulse_delay <= INCR_UVEC(pulse_delay, 1) WHEN pulse_in='1' ELSE pulse_delay;
  
   -----------------------------------------------------------------------------
@@ -70,7 +107,7 @@ BEGIN
   u_common_pulse_delay : ENTITY work.common_pulse_delay
   GENERIC MAP (
     g_pulse_delay_max => c_pulse_delay_max,
-    g_register_out    => FALSE 
+    g_register_out    => TRUE 
   )
   PORT MAP (
     clk         => clk,
@@ -81,17 +118,50 @@ BEGIN
     pulse_out   => pulse_out
   );
 
-  -------------------------------------------------------------------------------
+  -----------------------------------------------------------------------------
+  -- Verification
+  -- . Check total number of output pulses
+  -- . Check input->output pulse delay
+  -----------------------------------------------------------------------------
+  tb_end <= '0', '1' AFTER c_total_cycles*c_clk_period;
+
+  -- Keep counts
+  nxt_pulse_count <= pulse_count+1 WHEN pulse_out='1' ELSE pulse_count; 
+  nxt_pulse_delay_count <= 0 WHEN pulse_in='1' ELSE pulse_delay_count+1;
+
+  -- Store the delay setting for comparison to actual pulse delay
+  nxt_pulse_delay_reg <= pulse_delay WHEN pulse_in='1' ELSE pulse_delay_reg;
+
+  -- Perform checks
+  p_verify: PROCESS(pulse_out, tb_end)
+  BEGIN
+    -- input/output pulse delay should match setting
+    IF pulse_out='1' AND pulse_delay_count/=TO_UINT(pulse_delay_reg) THEN
+      REPORT "I/O pulse delay does not match delay setting!" SEVERITY FAILURE;
+    END IF;
+    -- Total number of pulses should be the maximum allowed by common_pulse_delay's interal counter width
+    IF tb_end='1' AND pulse_count/=c_nof_pulses THEN
+      REPORT "Incorrect total number of pulses!" SEVERITY FAILURE;    
+    END IF;
+  END PROCESS;
+
+  -----------------------------------------------------------------------------
   -- Registers
-  -------------------------------------------------------------------------------
+  -----------------------------------------------------------------------------
   p_clk : PROCESS (rst, clk)
   BEGIN
     IF rst = '1' THEN
-      pulse_delay <= (OTHERS=>'0');
-      pulse_in    <= '0';
+      pulse_delay       <= (OTHERS=>'0');
+      pulse_delay_reg   <= (OTHERS=>'0');
+      pulse_in          <= '0';
+      pulse_count       <= 0;
+      pulse_delay_count <= 0;
     ELSIF rising_edge(clk) THEN
-      pulse_delay <= nxt_pulse_delay;
-      pulse_in    <= nxt_pulse_in;
+      pulse_delay       <= nxt_pulse_delay;
+      pulse_delay_reg   <= nxt_pulse_delay_reg;
+      pulse_in          <= nxt_pulse_in;
+      pulse_count       <= nxt_pulse_count;
+      pulse_delay_count <= nxt_pulse_delay_count;
     END IF;
   END PROCESS;
 
-- 
GitLab