From 805853b4bbd16600784caba88f254c33204b72f9 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Wed, 28 Jan 2015 12:53:56 +0000
Subject: [PATCH] Added common_led_controller.vhd with test bench.

---
 libraries/base/common/hdllib.cfg              |   2 +
 .../common/src/vhdl/common_led_controller.vhd | 120 +++++++++++++++
 .../tb/vhdl/tb_common_led_controller.vhd      | 143 ++++++++++++++++++
 3 files changed, 265 insertions(+)
 create mode 100644 libraries/base/common/src/vhdl/common_led_controller.vhd
 create mode 100644 libraries/base/common/tb/vhdl/tb_common_led_controller.vhd

diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg
index e39164c39e..7782f3706b 100644
--- a/libraries/base/common/hdllib.cfg
+++ b/libraries/base/common/hdllib.cfg
@@ -70,6 +70,7 @@ synth_files =
     $UNB/Firmware/modules/common/src/vhdl/common_counter.vhd
     $UNB/Firmware/modules/common/src/vhdl/common_init.vhd
     $UNB/Firmware/modules/common/src/vhdl/common_pulser.vhd
+    src/vhdl/common_led_controller.vhd
     src/vhdl/common_pulser_us_ms_s.vhd
     $UNB/Firmware/modules/common/src/vhdl/common_debounce.vhd
     $UNB/Firmware/modules/common/src/vhdl/common_frame_busy.vhd
@@ -182,6 +183,7 @@ test_bench_files =
     #$UNB/Firmware/modules/common/tb/vhdl/tb_common_iobuf_in.vhd
     $UNB/Firmware/modules/common/tb/vhdl/tb_common_init.vhd
     $UNB/Firmware/modules/common/tb/vhdl/tb_common_int2float.vhd
+    tb/vhdl/tb_common_led_controller.vhd
     $UNB/Firmware/modules/common/tb/vhdl/tb_common_mem_mux.vhd
     $UNB/Firmware/modules/common/tb/vhdl/tb_common_mult.vhd
     $UNB/Firmware/modules/common/tb/vhdl/tb_common_mult_add2.vhd
diff --git a/libraries/base/common/src/vhdl/common_led_controller.vhd b/libraries/base/common/src/vhdl/common_led_controller.vhd
new file mode 100644
index 0000000000..73b7e063fb
--- /dev/null
+++ b/libraries/base/common/src/vhdl/common_led_controller.vhd
@@ -0,0 +1,120 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+-- Purpose: Provide visual activity information via a LED.
+-- Description:
+--   ctrl_on = '0' : then led = ctrl_input, so completely driven by external control
+--   ctrl_on = '1' : then led = '1' but pulses '0' for g_nof_ms each time that a ctrl_evt clk pulse occurs
+-- Remark:
+--   The p_state machine ensures that after g_nof_ms off the led also stays on for at least g_nof_ms, to
+--   avoid that a too fast ctrl_evt rate would cause the led too stay off. Hence the led can only accurately
+--   visualize a certain ctrl_evt rate, faster events will get lost.
+
+ENTITY common_led_controller IS
+  GENERIC (
+    g_nof_ms      : NATURAL := 100     -- force LED off for g_nof_ms and then on for at least g_nof_ms
+  );
+  PORT (
+    rst               : IN  STD_LOGIC;
+    clk               : IN  STD_LOGIC;
+    pulse_ms          : IN  STD_LOGIC;         -- pulses every ms
+    -- led control
+    ctrl_on           : IN  STD_LOGIC := '0';
+    ctrl_evt          : IN  STD_LOGIC := '0';  -- when ctrl_on='1' then the led output is on and pulses off for g_nof_ms when a ctrl_evt='1' event pulse occurs
+    ctrl_input        : IN  STD_LOGIC := '0';  -- when ctrl_on='0' then use ctrl_input to control the led output
+    -- led output
+    led               : OUT STD_LOGIC
+  );
+END common_led_controller;
+
+
+ARCHITECTURE rtl OF common_led_controller IS
+
+  TYPE t_state IS (s_idle, s_off, s_on);
+
+  SIGNAL state      : t_state;
+  SIGNAL nxt_state  : t_state;
+  
+  SIGNAL cnt        : NATURAL RANGE 0 TO g_nof_ms;
+  SIGNAL nxt_cnt    : NATURAL;
+  
+  SIGNAL nxt_led    : STD_LOGIC;
+  
+BEGIN
+
+  p_clk : PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      cnt   <= 0;
+      state <= s_idle;
+      led   <= '0';
+    ELSIF rising_edge(clk) THEN
+      cnt   <= nxt_cnt;
+      state <= nxt_state;
+      led   <= nxt_led;
+    END IF;
+  END PROCESS;
+  
+  p_state : PROCESS(state, ctrl_on, ctrl_evt, ctrl_input, pulse_ms, cnt)
+  BEGIN
+    IF ctrl_on='0' THEN
+      -- Default behaviour when ctrl_on = '0'
+      nxt_cnt   <= 0;
+      nxt_state <= s_idle;
+      nxt_led   <= ctrl_input;
+    ELSE
+      -- Pulse led off briefly on event when ctrl_on = '1'
+      nxt_cnt   <= cnt;
+      nxt_state <= state;
+      nxt_led   <= '1';
+      CASE state IS
+        WHEN s_idle =>
+          nxt_cnt <= 0;
+          IF ctrl_evt='1' THEN
+            nxt_state <= s_off;
+          END IF;
+        WHEN s_off =>
+          nxt_led <= '0';
+          IF pulse_ms='1' THEN
+            nxt_cnt <= cnt+1;
+            IF cnt=g_nof_ms THEN
+              nxt_cnt <= 0;
+              nxt_state <= s_on;
+            END IF;
+          END IF;
+        WHEN OTHERS =>  -- s_on
+          IF pulse_ms='1' THEN
+            nxt_cnt <= cnt+1;
+            IF cnt=g_nof_ms THEN
+              nxt_cnt <= 0;
+              nxt_state <= s_idle;
+            END IF;
+          END IF;
+      END CASE;
+    END IF;
+  END PROCESS;
+  
+END rtl;
diff --git a/libraries/base/common/tb/vhdl/tb_common_led_controller.vhd b/libraries/base/common/tb/vhdl/tb_common_led_controller.vhd
new file mode 100644
index 0000000000..9bd3098b35
--- /dev/null
+++ b/libraries/base/common/tb/vhdl/tb_common_led_controller.vhd
@@ -0,0 +1,143 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Test bench for common_led_controller
+-- Description:
+--   When ctrl_on='0' then toggle_ms drives the LED
+--   When ctrl+on='1' then the LED is on and it pulses off when a ctrl_evt occurs
+--                    too fast ctrl_evt get lost in a single pulse off.
+--   The tb is self-stopping, but not self-checking. The verification needs to be
+--   done manually in the wave window.
+-- Usage:
+--   > as 3
+--   > run -a
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE work.common_pkg.ALL;
+
+ENTITY tb_common_led_controller IS
+END tb_common_led_controller;
+
+ARCHITECTURE tb OF tb_common_led_controller IS
+
+  CONSTANT c_pulse_us      : NATURAL := 10;
+  CONSTANT c_1000          : NATURAL := 10;  -- use eg 10 instead of 1000 to speed up simulation
+  CONSTANT c_led_nof_ms    : NATURAL := 3;
+  CONSTANT c_on_nof_ms     : NATURAL := 50;
+  CONSTANT c_off_nof_ms    : NATURAL := 100;
+  CONSTANT c_nof_repeat    : NATURAL := 2;
+  
+  CONSTANT clk_period   : TIME := 1000 ns / c_pulse_us;
+  
+  SIGNAL tb_end         : STD_LOGIC := '0';
+  SIGNAL rst            : STD_LOGIC;
+  SIGNAL clk            : STD_LOGIC := '0';  
+  SIGNAL pulse_ms       : STD_LOGIC;
+  SIGNAL toggle_ms      : STD_LOGIC;
+  
+  SIGNAL ctrl_on        : STD_LOGIC;
+  SIGNAL ctrl_evt       : STD_LOGIC;
+  SIGNAL dbg_evt        : NATURAL;
+  
+  SIGNAL LED            : STD_LOGIC;
+  
+BEGIN
+  
+  clk <= NOT clk OR tb_end AFTER clk_period/2;
+  rst <= '1', '0' AFTER clk_period*7;
+  
+  p_stimuli : PROCESS
+    VARIABLE v_evt : POSITIVE;
+  BEGIN
+    FOR R IN 0 TO c_nof_repeat-1 LOOP
+      -- ctrl_on='0' => ctrl_input = toggle_ms drives the LED
+      ctrl_on  <= '0';
+      ctrl_evt <= '0';
+      FOR I IN 0 TO c_on_nof_ms-1 LOOP
+        WAIT UNTIL pulse_ms='1';
+      END LOOP;
+      
+      -- ctrl_on='1' => LED on and ctrl_evt pulses the LED off
+      ctrl_on  <= '1';
+      ctrl_evt <= '0';
+      FOR I IN 0 TO c_on_nof_ms-1 LOOP
+        WAIT UNTIL pulse_ms='1';
+      END LOOP;
+      
+      -- ctrl_on='1' => LED on and ctrl_evt pulses the LED off
+      v_evt := 1;
+      FOR I IN 0 TO c_off_nof_ms-1 LOOP
+        IF I=v_evt THEN
+          ctrl_evt <= '1';
+          WAIT UNTIL rising_edge(clk);
+          ctrl_evt <= '0';
+          v_evt := v_evt+I;
+        END IF;
+        dbg_evt <= v_evt;
+        WAIT UNTIL pulse_ms='1';
+      END LOOP;
+    END LOOP;
+      
+    tb_end <= '1';
+    WAIT FOR 1 us;
+    WAIT;
+  END PROCESS;
+  
+  u_common_pulser_us_ms_s : ENTITY work.common_pulser_us_ms_s
+  GENERIC MAP (
+    g_pulse_us   => c_pulse_us,  -- nof clk cycles to get us period
+    g_pulse_ms   => c_1000,      -- nof pulse_us pulses to get ms period
+    g_pulse_s    => c_1000       -- nof pulse_ms pulses to get s period
+  )
+  PORT MAP (
+    rst          => rst,
+    clk          => clk,
+    pulse_ms     => pulse_ms     -- pulses after every g_pulse_us*g_pulse_ms clock cycles
+  );
+  
+  u_common_toggle_ms : ENTITY work.common_toggle
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    in_dat      => pulse_ms,
+    out_dat     => toggle_ms
+  );
+
+  
+  u_common_led_controller : ENTITY work.common_led_controller
+  GENERIC MAP (
+    g_nof_ms      => c_led_nof_ms
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => clk,
+    pulse_ms          => pulse_ms,
+    -- led control
+    ctrl_on           => ctrl_on,
+    ctrl_evt          => ctrl_evt,
+    ctrl_input        => toggle_ms,
+    -- led output
+    led               => LED
+  );
+  
+END tb;
-- 
GitLab