?? mc8051_tmrctr.vhd
字號:
-- Description: Timer/Counter unit of the mc8051 microcontroller.
--
--
--
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
-----------------------------ENTITY DECLARATION--------------------------------
entity mc8051_tmrctr is
port (clk : in std_logic; --< system clock
reset : in std_logic; --< system reset
int0_i : in std_logic; --< interrupt 0
int1_i : in std_logic; --< interrupt 1
t0_i : in std_logic; --< external clock for
-- timer/counter0
t1_i : in std_logic; --< external clock for
-- timer/counter1
tmod_i : in std_logic_vector(7 downto 0); --< from SFR register
tcon_tr0_i : in std_logic; --< timer run 0
tcon_tr1_i : in std_logic; --< timer run 1
reload_i : in std_logic_vector(7 downto 0); --< to load counter
wt_en_i : in std_logic; --< indicates reload
wt_i : in std_logic_vector(1 downto 0); --< reload which reg.
th0_o : out std_logic_vector(7 downto 0); --< contents of th0
tl0_o : out std_logic_vector(7 downto 0); --< contents of tl0
th1_o : out std_logic_vector(7 downto 0); --< contents of th1
tl1_o : out std_logic_vector(7 downto 0); --< contents of tl1
tf0_o : out std_logic; --< interrupt flag 0
tf1_o : out std_logic); --< interrupt flag 1
end mc8051_tmrctr;
-------------------------------------------------------------------------------
architecture rtl of mc8051_tmrctr is
signal s_pre_count : unsigned(3 downto 0); -- these two signals provide
signal s_count_enable : std_logic; -- a clock enable signal which
-- masks out every twelfth ***
-- rising edge of clk
signal s_count0 : unsigned(15 downto 0); -- count for tmr/ctr0
signal s_countl0 : unsigned(7 downto 0); -- count register for tmr/ctr0
signal s_counth0 : unsigned(7 downto 0); -- count register for tmr/ctr0
signal s_count1 : unsigned(15 downto 0); -- count for tmr/ctr1
signal s_countl1 : unsigned(7 downto 0); -- count register for tmr/ctr1
signal s_counth1 : unsigned(7 downto 0); -- count register for tmr/ctr1
signal s_gate0 : std_logic; -- gate bit for tmr/ctr 0
signal s_gate1 : std_logic; -- gate bit for tmr/ctr 1
signal s_c_t0 : std_logic; -- tmr/ctr 0 is timer if 0
signal s_c_t1 : std_logic; -- tmr/ctr 1 is timer if 0
signal s_tmr_ctr0_en : std_logic; -- starts tmr/ctr 0 if 1
signal s_tmr_ctr1_en : std_logic; -- starts tmr/ctr 1 if 1
signal s_mode0 : unsigned(1 downto 0); -- mode of tmr/ctr 0
signal s_mode1 : unsigned(1 downto 0); -- mode of tmr/ctr 1
signal s_tf0 : std_logic; -- overflow flag of tmr/ctr 0
signal s_tf1 : std_logic; -- overflow flag of tmr/ctr 1
signal s_t0ff0 : std_logic; -- flipflop for edge dedection
signal s_t0ff1 : std_logic; -- flipflop for edge dedection
signal s_t0ff2 : std_logic; -- flipflop for edge dedection
signal s_t1ff0 : std_logic; -- flipflop for edge dedection
signal s_t1ff1 : std_logic; -- flipflop for edge dedection
signal s_t1ff2 : std_logic; -- flipflop for edge dedection
signal s_ext_edge0 : std_logic; -- 1 if external edge dedected
signal s_ext_edge1 : std_logic; -- 1 if external edge dedected
signal s_int0_sync : std_logic; -- synchronized int0 input ***
signal s_int1_sync : std_logic; -- synchronized int1 input ***
begin -- architecture rtl
-- The names of the following signals make the code more readable.
s_gate0 <= tmod_i(3);
s_c_t0 <= tmod_i(2);
s_mode0(1) <= tmod_i(1);
s_mode0(0) <= tmod_i(0);
s_gate1 <= tmod_i(7);
s_c_t1 <= tmod_i(6);
s_mode1(1) <= tmod_i(5);
s_mode1(0) <= tmod_i(4);
-- These two synchronized signals start the corresponding timer/counter if they are 1. -- ***
s_tmr_ctr0_en <= tcon_tr0_i and (not(s_gate0) or s_int0_sync); -- ***
s_tmr_ctr1_en <= tcon_tr1_i and (not(s_gate1) or s_int1_sync); -- ***
-- The outputs of this unit are the two timer overflow flags, which are read
-- by the control unit and the two 16 bit count registers to enable read
-- access.
tf0_o <= s_tf0;
tf1_o <= s_tf1;
th0_o <= std_logic_vector(s_count0(15 downto 8));
tl0_o <= std_logic_vector(s_count0(7 downto 0));
th1_o <= std_logic_vector(s_count1(15 downto 8));
tl1_o <= std_logic_vector(s_count1(7 downto 0));
-------------------------------------------------------------------------------
-- The two interrupt inputs are synchronized. ***
p_sync_inputs: process (clk, reset) -- ***
begin -- ***
if reset = '1' then -- ***
s_int0_sync <= '0'; -- ***
s_int1_sync <= '0'; -- ***
else -- ***
if clk'event and clk='1' then -- ***
s_int0_sync <= int0_i; -- ***
s_int1_sync <= int1_i; -- ***
end if; -- ***
end if; -- ***
end process p_sync_inputs; -- ***
-------------------------------------------------------------------------------
-- The register s_pre_count is driven with the system clock. So a
-- good enable signal (which is stable when clk has its rising edge) can be
-- derived to mask out every twelfth pulse of clk. ***
s_count_enable <= '1' when s_pre_count = conv_unsigned(11,4) else '0'; -- ***
p_divide_clk: process (clk, reset)
begin
if reset = '1' then
s_pre_count <= conv_unsigned(0,4);
else
if clk'event and clk='1' then
if (s_pre_count = conv_unsigned(11,4)) then -- ***
s_pre_count <= conv_unsigned(0,4); -- ***
else -- ***
s_pre_count <= s_pre_count + conv_unsigned(1,1); -- ***
end if;
end if;
end if;
end process p_divide_clk;
-------------------------------------------------------------------------------
-- The two flip flops are updated every second clock period.
-- If a falling edge
-- on the port t0_i is dedected the signal s_ext_edge0 is set to 1 and with
-- the next rising edge of clk the counter0 is incremented.
-- The same function is realised for counter1.
s_ext_edge0 <= '1' when (s_t0ff1 = '0' and s_t0ff2 = '1') else '0';
p_sample_t0: process (clk, reset)
begin
if reset = '1' then
s_t0ff0 <= '0';
s_t0ff1 <= '0';
s_t0ff2 <= '0';
else
if clk'event and clk = '1' then
if s_pre_count = conv_unsigned(6,3) then
if s_c_t0 = '1' then
s_t0ff0 <= t0_i;
s_t0ff1 <= s_t0ff0;
s_t0ff2 <= s_t0ff1;
end if;
end if;
end if;
end if;
end process p_sample_t0;
s_ext_edge1 <= '1' when (s_t1ff1 = '0' and s_t1ff2 = '1') else '0';
p_sample_t1: process (clk, reset)
begin
if reset = '1' then
s_t1ff0 <= '0';
s_t1ff1 <= '0';
s_t1ff2 <= '0';
else
if clk'event and clk = '1' then
if s_pre_count = conv_unsigned(6,3) then
if s_c_t1 = '1' then
s_t1ff0 <= t1_i;
s_t1ff1 <= s_t1ff0;
s_t1ff2 <= s_t1ff1;
end if;
end if;
end if;
end if;
end process p_sample_t1;
------------------------------------------------------------------------------
--+++++++++++++++++++++ TIMER / COUNTER 0 ++++++++++++++++++++++++++++++--
------------------------------------------------------------------------------
-- This is timer/counter0. It is built around the 16 bit count register
-- s_count0 and realises its four operating modes
------------------------------------------------------------------------------
s_count0(15 downto 8) <= s_counth0;
s_count0(7 downto 0) <= s_countl0;
s_count1(15 downto 8) <= s_counth1;
s_count1(7 downto 0) <= s_countl1;
p_tmr_ctr: process (clk, reset)
begin
if reset = '1' then -- perform asynchronous reset
s_countl0 <= conv_unsigned(0,8);
s_counth0 <= conv_unsigned(0,8);
s_countl1 <= conv_unsigned(0,8);
s_counth1 <= conv_unsigned(0,8);
s_tf1 <= '0';
s_tf0 <= '0';
else
if clk'event and clk = '1' then
-------------------------------------------------------------------------------
-- operating mode 0 (13 bit timer/counter)
-------------------------------------------------------------------------------
case s_mode0 is
when "00" =>
-- This section generates the timer/counter overflow flag0
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then
if s_count0 = conv_unsigned(65311,16) then -- ***
s_tf0 <= '1';
else
s_tf0 <= '0';
end if;
end if;
end if;
end if;
-- This section generates the low byte register of tmr/ctr0
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_countl0 = conv_unsigned(31,8) then -- ***
s_countl0 <= conv_unsigned(0,8);
else
s_countl0 <= s_countl0 + conv_unsigned(1,1);
end if;
else
if s_ext_edge0 = '1' then
if s_countl0 = conv_unsigned(31,8) then -- ***
s_countl0 <= conv_unsigned(0,8);
else
s_countl0 <= s_countl0 + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end if;
-- This section generates the high byte register of tmr/ctr0
if wt_i = "10" and wt_en_i = '1' then
s_counth0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_count0 = conv_unsigned(65311,16) then -- ***
s_counth0 <= conv_unsigned(0,8);
else
if s_countl0 = conv_unsigned(31,8) then -- ***
s_counth0 <= s_counth0 + conv_unsigned(1,1);
end if;
end if;
else
if s_ext_edge0 = '1' then
if s_count0 = conv_unsigned(65311,16) then -- ***
s_counth0 <= conv_unsigned(0,8);
else
if s_countl0 = conv_unsigned(31,8) then -- ***
s_counth0 <= s_counth0 + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end if;
end if;
-------------------------------------------------------------------------------
-- operating mode 1 (16 bit timer/counter)
-------------------------------------------------------------------------------
when "01" =>
-- This section generates the timer/counter overflow flag0
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' or (s_ext_edge0 = '1' and s_c_t0 = '1') then
if s_count0 = conv_unsigned(65535,16) then
s_tf0 <= '1';
else
s_tf0 <= '0';
end if;
end if;
end if;
end if;
-- This section generates the low byte register of tmr/ctr0
if wt_i = "00" and wt_en_i = '1' then
s_countl0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_count0 = conv_unsigned(65535,16) then
s_countl0 <= conv_unsigned(0,8);
else
s_countl0 <= s_countl0 + conv_unsigned(1,1);
end if;
else
if s_ext_edge0 = '1' then
if s_count0 = conv_unsigned(65535,16) then
s_countl0 <= conv_unsigned(0,8);
else
s_countl0 <= s_countl0 + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end if;
-- This section generates the high byte register of tmr/ctr0
if wt_i = "10" and wt_en_i = '1' then
s_counth0 <= unsigned(reload_i);
else
if s_tmr_ctr0_en = '1' then
if s_count_enable = '1' then
if s_c_t0 = '0' then
if s_count0 = conv_unsigned(65535,16) then
s_counth0 <= conv_unsigned(0,8);
else
if s_countl0 = conv_unsigned(255,8) then
s_counth0 <= s_counth0 + conv_unsigned(1,1);
end if;
end if;
else
if s_ext_edge0 = '1' then
if s_count0 = conv_unsigned(65535,16) then
s_counth0 <= conv_unsigned(0,8);
else
if s_countl0 = conv_unsigned(255,8) then
s_counth0 <= s_counth0 + conv_unsigned(1,1);
end if;
end if;
end if;
end if;
end if;
end if;
end if;
-------------------------------------------------------------------------------
-- operating mode 2 (8 bit timer/counter, autoreloaded from high byte register)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -