URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [VHDL/] [o8_interval_meas.vhd] - Rev 259
Compare with Previous | Blame | View Log
-- Copyright (c)2020 Jeremy Seth Henry -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are met: -- * Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- * Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution, -- where applicable (as part of a user interface, debugging port, etc.) -- -- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -- VHDL Units : o8_interval_meas -- Description: Provides an settable resolution counter for measuring -- : events -- Register Map: -- Offset Bitfield Description Read/Write -- 0x00 AAAAAAAA Captured Interval Byte 0 (RW*) -- 0x01 AAAAAAAA Captured Interval Byte 1 (RW*) -- -- Notes : Writing to either register will clear the timer -- -- Revision History -- Author Date Change ------------------ -------- --------------------------------------------------- -- Seth Henry 06/11/20 Design Start library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; use ieee.std_logic_misc.all; library work; use work.open8_pkg.all; entity o8_interval_meas is generic( Clock_Divide : integer := 12; Address : ADDRESS_TYPE ); port( Open8_Bus : in OPEN8_BUS_TYPE; Write_Qual : in std_logic := '1'; Rd_Data : out DATA_TYPE; Interrupt : out std_logic; Trigger_Reset : in std_logic := '0'; Trigger_Capture : in std_logic ); end entity; architecture behave of o8_interval_meas is alias Clock is Open8_Bus.Clock; alias Reset is Open8_Bus.Reset; constant User_Addr : std_logic_vector(15 downto 1) := Address(15 downto 1); alias Comp_Addr is Open8_Bus.Address(15 downto 1); signal Addr_Match : std_logic := '0'; alias Reg_Sel_d is Open8_Bus.Address(0); signal Reg_Sel_q : std_logic := '0'; signal Wr_En_d : std_logic := '0'; signal Wr_En_q : std_logic := '0'; signal Rd_En_d : std_logic := '0'; signal Rd_En_q : std_logic := '0'; signal Trig_Reset_SR : std_logic_vector(2 downto 0); signal Trig_Reset_RE : std_logic; signal Trig_Capture_SR : std_logic_vector(2 downto 0); signal Trig_Capture_RE : std_logic; constant DLY_VAL : integer := Clock_Divide; constant DLY_WDT : integer := ceil_log2(DLY_VAL - 1); constant DLY_INTV : std_logic_vector := conv_std_logic_vector( DLY_VAL - 1, DLY_WDT); signal Intv_Cntr : std_logic_vector( DLY_WDT - 1 downto 0 ); signal Intv_Tick : std_logic := '0'; signal Timer_Latch : std_logic_vector(15 downto 0) := x"0000"; alias Timer_Latch_B0 is Timer_Latch(7 downto 0); alias Timer_Latch_B1 is Timer_Latch(15 downto 8); signal Timer_Counter : std_logic_vector(15 downto 0) := x"0000"; begin Addr_Match <= '1' when Comp_Addr = User_Addr else '0'; Wr_En_d <= Addr_Match and Open8_Bus.Wr_En; Rd_En_d <= Addr_Match and Open8_Bus.Rd_En; io_reg: process( Clock, Reset ) begin if( Reset = Reset_Level )then Reg_Sel_q <= '0'; Wr_En_q <= '0'; Rd_En_q <= '0'; Rd_Data <= OPEN8_NULLBUS; Interrupt <= '0'; elsif( rising_edge( Clock ) )then Reg_Sel_q <= Reg_Sel_d; Wr_En_q <= Wr_En_d and Write_Qual; Rd_Data <= OPEN8_NULLBUS; Rd_En_q <= Rd_En_d; if( Rd_En_q = '1' and Reg_Sel_q = '0' )then Rd_Data <= Timer_Latch_B0; end if; if( Rd_En_q = '1' and Reg_Sel_q = '1' )then Rd_Data <= Timer_Latch_B1; end if; Interrupt <= Trig_Capture_RE; end if; end process; Capture_proc: process( Clock, Reset ) begin if( Reset = Reset_Level )then Trig_Reset_SR <= (others => '0'); Trig_Reset_RE <= '0'; Trig_Capture_SR <= (others => '0'); Trig_Capture_RE <= '0'; Intv_Cntr <= (others => '0'); Intv_Tick <= '0'; Timer_Counter <= (others => '0'); Timer_Latch <= (others => '0'); elsif( rising_edge(Clock) )then Trig_Reset_SR <= Trig_Reset_SR(1 downto 0) & Trigger_Reset; Trig_Reset_RE <= Trig_Reset_SR(1) and not Trig_Reset_SR(2); Trig_Capture_SR <= Trig_Capture_SR(1 downto 0) & Trigger_Capture; Trig_Capture_RE <= Trig_Capture_SR(1) and not Trig_Capture_SR(2); Intv_Cntr <= Intv_Cntr - 1; Intv_Tick <= '0'; if( Intv_Cntr = 0 )then Intv_Cntr <= DLY_INTV; Intv_Tick <= '1'; end if; Timer_Counter <= Timer_Counter + Intv_Tick; if( Trig_Reset_RE = '1' or Wr_En_q = '1' )then Timer_Counter <= (others => '0'); elsif( and_reduce(Timer_Counter) = '1' )then Timer_Counter <= Timer_Counter; end if; if( Wr_En_q = '1' )then Timer_Latch <= (others => '0'); elsif( Trig_Capture_RE = '1' )then Timer_Latch <= Timer_Counter; end if; end if; end process; end architecture;