Files
SharpMZ_MiSTer/common/i8253/counter0.vhd
2018-09-28 17:04:36 +01:00

146 lines
4.5 KiB
VHDL

---------------------------------------------------------------------------------------------------------
--
-- Name: counter0.vhd
-- Created: July 2018
-- Author(s): Nibbles Lab (C) 2005 - 2012, Refactored and ported for this emulation by Philip Smart
-- Description: Sharp MZ series i8253 PIT - Counter 0
-- This module emulates Counter 0 of the Intel i8253 Programmable Interval Timer.
--
-- Credits:
-- Copyright: (c) 2005-2012 Nibbles Lab, 2018 Philip Smart <philip.smart@net2net.org>
--
-- History: July 2018 - Initial module refactored and updated for this emulation.
--
---------------------------------------------------------------------------------------------------------
-- This source file 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 3 of the License, or
-- (at your option) any later version.
--
-- This source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity counter0 is
Port (
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
WRM : in std_logic;
WRD : in std_logic;
KCLK : in std_logic;
CLK : in std_logic;
GATE : in std_logic;
POUT : out std_logic
);
end counter0;
architecture Behavioral of counter0 is
--
-- counter
--
signal CREG : std_logic_vector(15 downto 0);
--
-- initialize
--
signal INIV : std_logic_vector(15 downto 0);
signal RL : std_logic_vector(1 downto 0);
signal PO : std_logic;
signal UL : std_logic;
signal NEWM : std_logic;
--
-- count control
--
signal CEN : std_logic;
signal GT : std_logic;
begin
-- Default for unused bus.
DO <= "00000000";
--
-- Counter access mode
--
process( KCLK, WRM ) begin
if( KCLK'event and KCLK='1' and WRM='0' ) then
RL<=DI(5 downto 4);
end if;
end process;
--
-- Counter initialize
--
process( KCLK, WRD, WRM ) begin
if( KCLK'event and KCLK='1' ) then
if( WRM='0' ) then
NEWM<='1';
UL<='0';
elsif( WRD='0' ) then
if( RL="01" ) then
INIV(7 downto 0)<=DI;
NEWM<='0';
elsif( RL="10" ) then
INIV(15 downto 8)<=DI;
NEWM<='0';
elsif( RL="11" ) then
if( UL='0' ) then
INIV(7 downto 0)<=DI;
UL<='1';
else
INIV(15 downto 8)<=DI;
UL<='0';
NEWM<='0';
end if;
end if;
end if;
end if;
end process;
--
-- Count enable
--
CEN<='1' when NEWM='0' and GATE='1' else '0';
--
-- Count (mode 3)
--
process( CLK, WRM, DI(3 downto 1) ) begin
if( CLK'event and CLK='1' ) then
GT<=GATE;
if( WRM='0' ) then
case DI(3 downto 1) is
when "000" => PO<='0';
when others => PO<='1';
end case;
elsif( (GT='0' and GATE='1') or CREG=2 ) then
CREG<=INIV;
PO<=not PO;
elsif( CEN='1' ) then
if( CREG(0)='1' ) then
if( PO='1' ) then
CREG<=CREG-3;
else
CREG<=CREG-1;
end if;
else
CREG<=CREG-2;
end if;
end if;
end if;
end process;
POUT<=PO;
end Behavioral;