📄 timer_counter.vhd
字号:
TimerCounter0Cnt:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
TCNT0 <= (others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if(adr=TCNT0_Address and iowe='1' and cp2en='1') then -- Write to TCNT0
TCNT0 <= dbus_in;
elsif(tmr_cp2en='1') then
case PWM0 is
when '0' => -- Non-PWM mode
if(CTC0='1' and TCNT0=OCR0) then -- Clear T/C on compare match
TCNT0 <= (others => '0');
elsif(TCNT0_En='1') then
TCNT0 <= TCNT0 + 1; -- Increment TCNT0
end if;
when '1' => -- PWM mode
if(TCNT0_En='1') then
case Cnt0Dir is
when '0' => -- Counts up
if(TCNT0=x"FF") then
TCNT0<=x"FE";
else
TCNT0 <= TCNT0 + 1; -- Increment TCNT0 (0 to FF)
end if;
when '1' => -- Counts down
if(TCNT0=x"00") then
TCNT0 <= x"01";
else
TCNT0 <= TCNT0 - 1; -- Decrement TCNT0 (FF to 0)
end if;
when others => null;
end case;
end if;
when others => null;
end case;
end if;
end if;
end process;
Cnt0DirectionControl:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
Cnt0Dir <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if(tmr_cp2en='1') then -- Clock enable
if(TCNT0_En='1') then
if (PWM0='1') then
case Cnt0Dir is
when '0' =>
if(TCNT0=x"FF") then
Cnt0Dir <= '1';
end if;
when '1' =>
if(TCNT0=x"00") then
Cnt0Dir <= '0';
end if;
when others => null;
end case;
end if;
end if;
end if;
end if;
end process;
TCnt0OutputControl:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
OC0_PWM0_Int <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if(tmr_cp2en='1') then -- Clock enable
if(TCNT0_En='1') then
case PWM0 is
when '0' => -- Non PWM Mode
if(TCNT0=OCR0 and TCNT0CmpBl='0') then
if(COM01='0' and COM00='1') then -- Toggle
OC0_PWM0_Int <= not OC0_PWM0_Int;
end if;
end if;
when '1' => -- PWM Mode
case TCCR0(5 downto 4) is -- -> COM01&COM00
when "10" => -- Non-inverted PWM
if(TCNT0=x"FF") then -- Update OCR0
if (OCR0_Tmp=x"00") then
OC0_PWM0_Int <= '0'; -- Clear
elsif (OCR0_Tmp=x"FF") then
OC0_PWM0_Int <= '1'; -- Set
end if;
elsif(TCNT0=OCR0 and OCR0/=x"00") then
if(Cnt0Dir='0') then -- Up-counting
OC0_PWM0_Int <= '0'; -- Clear
else -- Down-counting
OC0_PWM0_Int <= '1'; -- Set
end if;
end if;
when "11" => -- Inverted PWM
if(TCNT0=x"FF") then -- Update OCR0
if (OCR0_Tmp=x"00") then
OC0_PWM0_Int <= '1'; -- Set
elsif (OCR0_Tmp=x"FF") then
OC0_PWM0_Int <= '0'; -- Clear
end if;
elsif(TCNT0=OCR0 and OCR0/=x"00") then
if(Cnt0Dir='0') then -- Up-counting
OC0_PWM0_Int <= '1'; -- Set
else -- Down-counting
OC0_PWM0_Int <= '0'; -- Clear
end if;
end if;
when others => null;
end case;
when others => null;
end case;
end if;
end if;
end if;
end process;
OC0_PWM0 <= OC0_PWM0_Int;
TCnt0_TIFR_Bits:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
TOV0 <= '0';
OCF0 <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
-- TOV0
if(stopped_mode='1' and tmr_running='0' and cp2en='1') then -- !!!Special mode!!!
if(adr=TIFR_Address and iowe='1') then
TOV0 <= dbus_in(0); -- !!!
end if;
else
case TOV0 is
when '0' =>
if (tmr_cp2en='1' and TCNT0_En='1') then
if (PWM0='0') then -- Non PWM Mode
if (TCNT0=x"FF") then
TOV0 <= '1';
end if;
else -- PWM Mode
if(TCNT0=x"00") then
TOV0 <= '1';
end if;
end if;
end if;
when '1' =>
if((TC0OvfIRQ_Ack='1' or (adr=TIFR_Address and iowe='1' and dbus_in(0)='1')) and cp2en='1') then -- Clear TOV0 flag
TOV0 <= '0';
end if;
when others => null;
end case;
end if;
-- OCF0
if(stopped_mode='1' and tmr_running='0' and cp2en='1') then -- !!!Special mode!!!
if(adr=TIFR_Address and iowe='1') then
OCF0 <= dbus_in(1); -- !!!
end if;
else
case OCF0 is
when '0' =>
if (tmr_cp2en='1' and TCNT0_En='1') then
if (TCNT0=OCR0 and TCNT0CmpBl='0') then
OCF0 <= '1';
end if;
end if;
when '1' =>
if((TC0CmpIRQ_Ack='1' or (adr=TIFR_Address and iowe='1' and dbus_in(1)='1')) and cp2en='1') then -- Clear OCF2 flag
OCF0 <= '0';
end if;
when others => null;
end case;
end if;
end if;
end process;
TCCR0(7) <= '0';
TCCR0_Reg:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
TCCR0(6 downto 0) <= (others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if (cp2en='1') then -- Clock Enable
if (adr=TCCR0_Address and iowe='1') then
TCCR0(6 downto 0) <= dbus_in(6 downto 0);
end if;
end if;
end if;
end process;
OCR0_Write:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
OCR0 <= (others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
case PWM0 is
when '0' => -- Non-PWM mode
if (adr=OCR0_Address and iowe='1' and cp2en='1') then -- Load data from the data bus
OCR0 <= dbus_in;
end if;
when '1' => -- PWM mode
if(TCNT0=x"FF" and tmr_cp2en='1' and TCNT0_En='1') then -- Load data from the temporary register
OCR0 <= OCR0_Tmp;
end if;
when others => null;
end case;
end if;
end process;
OCR0_Tmp_Write:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
OCR0_Tmp <= (others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if (cp2en='1') then
if (adr=OCR0_Address and iowe='1') then -- Load data from the data bus
OCR0_Tmp <= dbus_in;
end if;
end if;
end if;
end process;
--
TCNT0WriteControl:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
TCNT0WrFl <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if (cp2en='1') then
case TCNT0WrFl is
when '0' =>
if (adr=TCNT0_Address and iowe='1' and TCNT0_En='0') then -- Load data from the data bus
TCNT0WrFl <= '1';
end if;
when '1' =>
if(TCNT0_En='0') then
TCNT0WrFl <= '0';
end if;
when others => null;
end case;
end if;
end if;
end process;
-- Operations on compare match(OCF0 and Toggling) disabled for TCNT0
TCNT0CmpBl <= '1' when (TCNT0WrFl='1' or (adr=TCNT0_Address and iowe='1')) else
'0';
-- -------------------------------------------------------------------------------------------
-- Timer/Counter 2
-- -------------------------------------------------------------------------------------------
TimerCounter2Cnt:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
TCNT2 <= (others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if(adr=TCNT2_Address and iowe='1' and cp2en='1') then -- Write to TCNT2
TCNT2 <= dbus_in;
elsif(tmr_cp2en='1') then
case PWM2 is
when '0' => -- Non-PWM mode
if(CTC2='1' and TCNT2=OCR2) then -- Clear T/C on compare match
TCNT2 <= (others => '0');
elsif(TCNT2_En='1') then
TCNT2 <= TCNT2 + 1; -- Increment TCNT2
end if;
when '1' => -- PWM mode
if(TCNT2_En='1') then
case Cnt2Dir is
when '0' => -- Counts up
if(TCNT2=x"FF") then
TCNT2 <= x"FE";
else
TCNT2 <= TCNT2 + 1; -- Increment TCNT2 (0 to FF)
end if;
when '1' => -- Counts down
if(TCNT2=x"00") then
TCNT2 <= x"01";
else
TCNT2 <= TCNT2 - 1; -- Decrement TCNT0 (FF to 0)
end if;
when others => null;
end case;
end if;
when others => null;
end case;
end if;
end if;
end process;
Cnt2DirectionControl:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
Cnt2Dir <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if(tmr_cp2en='1') then -- Clock enable
if(TCNT2_En='1') then
if (PWM2='1') then
case Cnt2Dir is
when '0' =>
if(TCNT2=x"FF") then
Cnt2Dir <= '1';
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -