OpenCores
URL https://opencores.org/ocsvn/tinyvliw8/tinyvliw8/trunk

Subversion Repositories tinyvliw8

[/] [tinyvliw8/] [trunk/] [src/] [vhdl/] [timer.vhd] - Rev 9

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--
-- Design:  tinyVLIW8 soft-core processor
-- Author:  Oliver Stecklina <stecklina@ihp-microelectronics.com>
-- Date:    27.05.2015 
-- File:    timer.vhd
--
-----------------------------------------------------------------
--
-- Description : 16-bit timer module. The timer provides two
--      internal timer modules.
--
-----------------------------------------------------------------
--
--    Copyright (C) 2015 IHP GmbH, Frankfurt (Oder), Germany
--
-- This code is free software. It is licensed under the EUPL, Version 1.1
-- or - as soon they will be approved by the European Commission - subsequent
-- versions of the EUPL (the "License").
-- You may redistribute this code and/or modify it under the terms of this
-- License.
-- You may not use this work except in compliance with the License.
-- You may obtain a copy of the License at:
--
-- http://joinup.ec.europa.eu/software/page/eupl/licence-eupl
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" basis,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-----------------------------------------------------------------
 
LIBRARY	IEEE;
 
USE IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
 
ENTITY timer IS
	PORT (
		clk       : in std_logic;
 
		addr      : in std_logic_vector(2 downto 0);	 -- register address
 
		writeEn_n : in  STD_LOGIC;	                   -- write enable, low active
		readEn_n  : in  STD_LOGIC;                    -- read enable, low active
 
		dataOut   : OUT std_logic_vector(7 downto 0); -- data bus for writing register
		dataIn    : IN std_logic_vector(7 downto 0);  -- data bus for reading register
 
		irq       : out std_logic;
		irq_ack   : in  std_logic;
 
		rst_n     : IN  STD_LOGIC                -- asynchr. reset, low active
	);
END timer;
 
ARCHITECTURE behav OF timer IS
 
component clock_divider
	generic (n: integer := 2);
	PORT (
		inclk     : in  std_logic;
		outclk    : out std_logic;
 
		div       : in std_logic_vector((n - 1) downto 0);
		en        : IN std_logic
	);
END component;
 
component gendelay
	generic (n: integer := 1);
	port (
		a_in	: in	std_logic;
		a_out	: out	std_logic
	);
end component;
 
--	signal clk_s      : std_logic;
	signal rst_n_s    : std_logic;
 
	signal cnt_reg    : std_logic_vector(15 downto 0);       -- state counter
	signal ifg_reg    : std_logic_vector(1 downto 0);
 
	signal ccr0       : std_logic_vector(15 downto 0);
	signal ccr1       : std_logic_vector(15 downto 0);
 
	-- | clr(7) | mode(6) | ie1(5) | ie0(4) | .. | div(2 .. 1) | en(0) |
	signal ctl_reg    : std_logic_vector(6 downto 0);
 
	signal irq_s      : std_logic;
	signal ifgEn_s    : std_logic;
	signal divclk_s   : std_logic;
 
	signal clrBit_s      : std_logic;
	signal clr_s      : std_logic;
 
  signal rst_tar_cnt : std_logic;
 
BEGIN
 
--	delay_i: gendelay
--		generic map (n => 2)
--		port map (
--			a_in	=> clrBit_s,
--			a_out	=> clr_s
--		);
  clr_s <= clrBit_s; 
	rst_n_s <= rst_n;
--	clk_s <= clk;
 
	clk_div_i : clock_divider
	generic map (n => 2)
	port map (
		inclk  => clk,
		outclk => divclk_s,
 
		div    => ctl_reg(2 downto 1),
		en     => ctl_reg(0)
	);
 
	clrBit_s <= '1' when dataIn(7) = '1' and readEn_n = '0' and addr = "000" and writeEn_n = '0' else
	            '0';
 
  rst_tar_cnt <='0' when rst_n_s='0' else
                '0' when clrBit_s='1' else
                '1';            
 
 
	tar_cnt : process (divclk_s, rst_tar_cnt)			-- state counter
		variable cnt: unsigned (15 downto 0);
	BEGIN
		--IF (rst_n_s = '0' or clr_s = '1') THEN
    IF (rst_tar_cnt='0') THEN
			 cnt := (others => '0');
		ELSE
			if (divclk_s'EVENT AND divclk_s = '1') THEN	-- rising SCKL edge				
				IF (ctl_reg(6) = '0' and cnt = cnt'high) or (ctl_reg(6) = '1' and cnt = unsigned(ccr0)) THEN
					cnt := (others => '0');
				ELSE
					cnt := cnt + 1;
				END IF;
			END if;
		END IF;
 
		cnt_reg <= std_logic_vector(cnt);
	END PROCESS;
 
	irq_en : process(rst_n_s, clk)
	begin
		IF (rst_n_s = '0') THEN
			 irq_s <= '0';
		ELSE
			if (clk'EVENT AND clk = '0') THEN	-- falling SCKL edge
				if (irq_ack = '1') then
					irq_s <= '0';
				else
					if ((ctl_reg(4) = '1' and cnt_reg = ccr0 and ifg_reg(0) = '0') or (ctl_reg(5) = '1' and cnt_reg = ccr1 and ifg_reg(1) = '0')) then
						irq_s <= '1';
					end if;
				end if;
			end if;
		end if;
	end process;
 
	ifgEn_s <=  irq_s or not(writeEn_n);
 
	ifg : process(rst_n_s, ifgEn_s)
	BEGIN
		IF (rst_n_s = '0') THEN
			 ifg_reg <= (others => '0');
		ELSE
			if (ifgEn_s'event and ifgEn_s = '1') then
				if (irq_s = '1') then
					if (ctl_reg(4) = '1' and cnt_reg = ccr0) then
						ifg_reg(0) <= '1';
					end if;
 
					if (ctl_reg(5) = '1' and cnt_reg = ccr1) then
						ifg_reg(1) <= '1';
					end if;
				else
					if (readEn_n = '0' and writeEn_n = '0' and addr = "001") then
						ifg_reg <= ifg_reg and not(dataIn(1 downto 0));
					end if;
				end if;
			end if;
		end if;
	end process;
 
	wr_reg : process(rst_n_s, readEn_n, writeEn_n)			-- state counter
	BEGIN
		IF (rst_n_s = '0') THEN
			 ctl_reg <= (others => '0');
 
			 ccr0    <= (others => '0');
			 ccr1    <= (others => '0');
		ELSE
			if (readEn_n = '0') then
				if (writeEn_n'event and writeEn_n = '0') then
					CASE addr IS
						when "000" => ctl_reg           <= dataIn(6 downto 0);
						when "100" => ccr0(7 downto 0)  <= dataIn;
						when "101" => ccr0(15 downto 8) <= dataIn;
						when "110" => ccr1(7 downto 0)  <= dataIn;
						when "111" => ccr1(15 downto 8) <= dataIn;
						WHEN others => null;
					END CASE;
				end if;
			end if;
		end if;
	END PROCESS;
 
 
	dataOut <= '0' & ctl_reg                   when rst_n_s = '1' and readEn_n = '0' and addr = "000" else
	           "000000" & ifg_reg(1 downto 0)  when rst_n_s = '1' and readEn_n = '0' and addr = "001" else
	           cnt_reg(7 downto 0)             when rst_n_s = '1' and readEn_n = '0' and addr = "010" else
	           cnt_reg(15 downto 8)            when rst_n_s = '1' and readEn_n = '0' and addr = "011" else
	           ccr0(7 downto 0)                when rst_n_s = '1' and readEn_n = '0' and addr = "100" else
	           ccr0(15 downto 8)               when rst_n_s = '1' and readEn_n = '0' and addr = "101" else
	           ccr1(7 downto 0)                when rst_n_s = '1' and readEn_n = '0' and addr = "110" else
	           ccr1(15 downto 8)               when rst_n_s = '1' and readEn_n = '0' and addr = "111" else
	           (others => '0');
 
	irq <= irq_s when rst_n_s = '1' else
	       '0';
 
END behav;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.