📄 timers.vhd
字号:
-----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- 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 2 of the License, or
-- (at your option) any later version.
--
-- See the file COPYING for the full details of the license.
-----------------------------------------------------------------------------
-- Entity: timers
-- File: timers.vhd
-- Author: Jiri Gaisler - ESA/ESTEC
-- Description: This unit implemets two general-pupose timers and one watchdog.
-- All three timers are 24-bit wide down-counters clocked by a
-- common 10-bit pre-scaler. The pre-scaler is clocked by the
-- system clock. All three timers share the same decrementer
-- which means that the minimum pre-scaler division is three.
-- On reset, the scaler and watchdog are set to 'all-ones',
-- the two GP-timers disabled, and the remaining registers are
-- 'unknown'.
------------------------------------------------------------------------------
-- Version control:
-- 11-10-1998: First implemetation
-- 26-09-1999: Release 1.0
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_signed."-";
use work.iface.all;
use work.macro.all;
entity timers is
port (
rst : in std_logic;
clk : in std_logic;
pbi : in pbus_in_type;
pbo : out pbus_out_type;
timo : out timers_out_type
);
end;
architecture rtl of timers is
type timer_control_type is record
enable : std_logic; -- enable counter
load : std_logic; -- load counter
restart : std_logic; -- restart counter
irq : std_logic; -- interrupt
end record;
type timregs is record
t0value : std_logic_vector(23 downto 0);
t0load : std_logic_vector(23 downto 0);
t0ctrl : timer_control_type;
t1value : std_logic_vector(23 downto 0);
t1load : std_logic_vector(23 downto 0);
t1ctrl : timer_control_type;
scalerval : std_logic_vector(9 downto 0);
scalerpre : std_logic_vector(9 downto 0);
wdog : std_logic_vector(23 downto 0);
wdogtout : std_logic;
end record;
signal tregs, tregsin : timregs;
signal tickin : std_logic;
signal tick : std_logic_vector(2 downto 0);
-- Main process
begin
timerop : process(rst, tregs, pbi, tick)
variable sval : std_logic_vector(9 downto 0);
variable rdata : std_logic_vector(31 downto 0);
variable res, addin : std_logic_vector(23 downto 0);
variable tv : timregs;
begin
tv := tregs; tv.t0ctrl.irq := '0'; tv.t1ctrl.irq := '0';
tv.t0ctrl.load := '0'; tv.t1ctrl.load := '0';
-- scaler operation
-- pragma translate_off
if not is_x(tregs.scalerval) then
-- pragma translate_on
sval := tregs.scalerval - 1; -- decrement scaler
-- pragma translate_off
end if;
-- pragma translate_on
tickin <= sval(9) and not tregs.scalerval(9);
if (rst = '0') or (sval(9) /= tregs.scalerval(9)) then
sval := tregs.scalerpre; -- reload if carry-out
end if;
tv.scalerval := sval;
-- timer operation
case tick is -- select which timer to operate on
when "001" =>
addin := tregs.t0value;
when "010" =>
addin := tregs.t1value;
when others =>
addin := tregs.wdog;
end case;
-- pragma translate_off
if not is_x(addin) then
-- pragma translate_on
res := addin - 1; -- decrement timer
-- pragma translate_off
end if;
-- pragma translate_on
-- update corresponding register and generate irq/wdrst
if (tick(0) and tregs.t0ctrl.enable) = '1' then
tv.t0value := res; tv.t0ctrl.irq := res(23) and not addin(23);
end if;
if (tick(1) and tregs.t1ctrl.enable) = '1' then
tv.t1value := res; tv.t1ctrl.irq := res(23) and not addin(23);
end if;
if tick(2) = '1' then
tv.wdogtout := res(23) and not addin(23);
if tv.wdogtout = '0' then
tv.wdog := res;
end if;
end if;
-- reload timer 0 if carry-out and restart
if ((tregs.t0ctrl.restart and tv.t0ctrl.irq) or tregs.t0ctrl.load) = '1' then
tv.t0value := tregs.t0load;
end if;
if tv.t0ctrl.irq = '1' then
tv.t0ctrl.enable := tregs.t0ctrl.restart;
end if;
-- reload timer 1 if carry-out and restart
if ((tregs.t1ctrl.restart and tv.t1ctrl.irq) or tregs.t1ctrl.load) = '1' then
tv.t1value := tregs.t1load;
end if;
if tv.t1ctrl.irq = '1' then
tv.t1ctrl.enable := tregs.t1ctrl.restart;
end if;
-- read/write registers
rdata := (others => '0');
if pbi.enable = '1' then
if pbi.read = '1' then
case pbi.address is
when "010000" => rdata(23 downto 0) := tregs.t0value;
when "010001" => rdata(23 downto 0) := tregs.t0load;
when "010010" =>
rdata(1 downto 0) := tregs.t0ctrl.restart & tregs.t0ctrl.enable;
when "010011" => rdata(23 downto 0) := tregs.wdog;
when "010100" => rdata(23 downto 0) := tregs.t1value;
when "010101" => rdata(23 downto 0) := tregs.t1load;
when "010110" =>
rdata(1 downto 0) := tregs.t1ctrl.restart & tregs.t1ctrl.enable;
when "011000" => rdata(9 downto 0) := tregs.scalerval;
when "011001" => rdata(9 downto 0) := tregs.scalerpre;
when others => null;
end case;
else
case pbi.address is
when "010000" => tv.t0value := pbi.data(23 downto 0);
when "010001" => tv.t0load := pbi.data(23 downto 0);
when "010010" => tv.t0ctrl.load := pbi.data(2);
tv.t0ctrl.restart := pbi.data(1);
tv.t0ctrl.enable := pbi.data(0);
when "010011" => tv.wdog := pbi.data(23 downto 0);
when "010100" => tv.t1value := pbi.data(23 downto 0);
when "010101" => tv.t1load := pbi.data(23 downto 0);
when "010110" => tv.t1ctrl.load := pbi.data(2);
tv.t1ctrl.restart := pbi.data(1);
tv.t1ctrl.enable := pbi.data(0);
when "011000" => tv.scalerval := pbi.data(9 downto 0);
when "011001" => tv.scalerpre := pbi.data(9 downto 0);
when others => null;
end case;
end if;
end if;
-- reset operation
if rst = '0' then
tv.t0ctrl.enable := '0';
tv.t1ctrl.enable := '0';
tv.wdog := (others => '1');
tv.wdogtout := '0';
end if;
tregsin <= tv; -- update registers
pbo.data <= rdata; -- drive data bus
end process;
-- Registers
regs : process(clk)
begin
if clk'event and (clk = '1') then
tregs <= tregsin;
tick(0) <= tickin; tick(1) <= tick(0); tick(2) <= tick(1);
end if;
end process;
-- Drive outputs
timo.tick <= tick(0);
timo.irq <= tregs.t1ctrl.irq & tregs.t0ctrl.irq;
timo.wdog <= not tregs.wdogtout;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -