⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timers.vhd

📁 一个航天航空用的Sparc处理器(配美国欧洲宇航局用的R_tems嵌入式操作系统)的VHDL源代码
💻 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 + -