Files
ZPU/devices/sysbus/timer/timer_controller.vhd
Philip Smart 210cb9d974 Tidying
2019-10-23 14:14:42 +01:00

132 lines
5.0 KiB
VHDL

-- 32bit prescaled Timer
--
-- Original Author unknown.
-- Updated for ZPU SoC use: Philip Smart, 2019.
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. 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.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``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 THE
-- ZPU PROJECT OR CONTRIBUTORS 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.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.ALL;
library work;
-- Timer controller module
entity timer_controller is
generic(
prescale : integer := 1; -- Prescale incoming clock
timers : integer := 0 -- This is a power of 2, so zero means 1 counter, 4 means 16 counters...
);
port (
clk : in std_logic;
reset : in std_logic; -- active low
reg_addr_in : in std_logic_vector(7 downto 0); -- from host CPU
reg_data_in : in std_logic_vector(31 downto 0);
reg_rw : in std_logic;
reg_req : in std_logic;
ticks : out std_logic_vector(2**timers-1 downto 0)
);
end entity;
architecture rtl of timer_controller is
constant prescale_adj : integer := prescale-1;
signal prescale_counter : unsigned(15 downto 0);
signal prescaled_tick : std_logic;
type timer_counters is array (2**timers-1 downto 0) of unsigned(31 downto 0);
signal timer_counter : timer_counters;
signal timer_limit : timer_counters;
signal timer_enabled : std_logic_vector(2**timers-1 downto 0);
signal timer_index : unsigned(7 downto 0);
begin
-- Prescaled tick
process(clk, reset)
begin
if reset='0' then
prescale_counter <=(others => '0');
elsif rising_edge(clk) then
prescaled_tick <='0';
prescale_counter <=prescale_counter-1;
if prescale_counter=X"00" then
prescaled_tick <='1';
prescale_counter <=to_unsigned(prescale_adj,16);
end if;
end if;
end process;
-- The timers proper;
process(clk,reset)
begin
if reset='0' then
for I in 0 to (2**timers-1) loop
timer_counter(I) <= (others => '0');
end loop;
elsif rising_edge(clk) then
ticks <= (others => '0');
if prescaled_tick='1' then
for I in 0 to (2**timers-1) loop
if timer_enabled(I)='1' then
timer_counter(I) <=timer_counter(I)-1;
if timer_counter(I)=X"00000000" then
timer_counter(I)<=timer_limit(I);
ticks(I) <='1';
end if;
end if;
end loop;
end if;
end if;
end process;
-- Handle CPU access to hardware registers
process(clk,reset)
begin
if reset='0' then
timer_enabled <= (others => '0');
elsif rising_edge(clk) then
if reg_req='1' and reg_rw='0' then -- Write access
case reg_addr_in is
when X"00" =>
timer_enabled <= reg_data_in(2**timers-1 downto 0);
when X"04" =>
timer_index <= unsigned(reg_data_in(7 downto 0));
when X"08" =>
timer_limit(to_integer(timer_index(timers downto 0)))<= unsigned(reg_data_in(31 downto 0));
when others =>
null;
end case;
end if;
end if;
end process;
end architecture;