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;