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

📄 cia6526.vhd

📁 FPGA64的VHDL源代码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
				tod_running <= '0';
			end if;
		end if;		
	end process;
	
	-- Control TOD output latch
	-- Reading the hours latches the output until
	-- the 10ths of seconds are read. While latched the
	-- clock continues to run in the bankground.
	process(clk)
	begin
		if rising_edge(clk) then
			if myRd = '1' then
				case addr is
				when X"8" => tod_latched <= '0';
				when X"B" => tod_latched <= '1';
				when others => null;
				end case;
			end if;
		end if;		
	end process;


-- -----------------------------------------------------------------------
-- Timer A and B
-- -----------------------------------------------------------------------
	process(clk)
		variable newTimerA : unsigned(15 downto 0);
		variable nextClkTimerA : std_logic;
		variable timerBInput : std_logic;
		variable newTimerB : unsigned(15 downto 0);
		variable nextClkTimerB : std_logic;
		variable new_cra_runmode : std_logic;
		variable new_crb_runmode : std_logic;
	begin		
		if rising_edge(clk) then
			loadTimerA <= '0';
			loadTimerB <= '0';
			new_cra_runmode := cra_runmode;
			new_crb_runmode := crb_runmode;
			
			if resetIrq then
				intr_timerA <= '0';
				intr_timerB <= '0';
			end if;

			if myWr = '1' then
				case addr is
				when X"4" =>
					talo <= di;
				when X"5" =>
					tahi <= di;
					if cra_start = '0' then
						loadTimerA <= '1';
					end if;
				when X"6" =>
					tblo <= di;
				when X"7" =>
					tbhi <= di;
					if crb_start = '0' then
						loadTimerB <= '1';
					end if;
				when X"E" =>
					if cra_start = '0' then
						-- Only set on rising edge
						timerAToggle <= timerAToggle or di(0);
					end if;
					cra_start <= di(0);
					new_cra_runmode := di(3);
				when X"F" =>
					if crb_start = '0' then
						-- Only set on rising edge
						timerBToggle <= timerBToggle or di(0);
					end if;
					crb_start <= di(0);
					new_crb_runmode := di(3);
				when others => null;
				end case;
			end if;
			
			if reset = '1' then
				new_cra_runmode := '0';
				new_crb_runmode := '0';
			end if;
			
			cra_runmode <= new_cra_runmode;
			crb_runmode <= new_crb_runmode;

			if enable = '1' then
				--
				-- process timer A
				--
				timerAPulse <= '0';
				newTimerA := timerA;
				
				-- CNT is not emulated so don't count when inmode = 1
				nextClkTimerA := cra_start and (not cra_inmode);
				if clkTimerA = '1' then
					newTimerA := newTimerA - 1;
				end if;
				if nextClkTimerA = '1'
				and newTimerA = 0 then
					intr_timerA <= '1';
					loadTimerA <= '1';
					timerAPulse <= '1';
					timerAToggle <= not timerAToggle;
					if (new_cra_runmode or cra_runmode) = '1' then
						cra_start <= '0';
					end if;
				end if;
				if forceTimerA = '1' then
					loadTimerA <= '1';
				end if;
				clkTimerA <= nextClkTimerA;
				timerA <= newTimerA;
					
				--
				-- process timer B
				--
				timerBPulse <= '0';
				newTimerB := timerB;

				if crb_inmode6 = '1' then
					-- count timerA underflows
					timerBInput := timerAPulse;
				elsif crb_inmode5 = '0' then
					-- count clock pulses
					timerBInput := '1'; 
				else
					-- CNT is not emulated so don't count
					timerBInput := '0';
				end if;
				nextClkTimerB := timerBInput and crb_start;
				if clkTimerB = '1' then
					newTimerB := newTimerB - 1;
				end if;				
				if nextClkTimerB = '1'
				and newTimerB = 0 then
					intr_timerB <= '1';
					loadTimerB <= '1';
					timerBPulse <= '1';
					timerBToggle <= not timerBToggle;
					if (new_crb_runmode or crb_runmode) = '1' then
						crb_start <= '0';
					end if;
				end if;
				if forceTimerB = '1' then
					loadTimerB <= '1';
				end if;
				clkTimerB <= nextClkTimerB;
				timerB <= newTimerB;
			end if;

			if loadTimerA = '1' then
				timerA <= tahi & talo;
				clkTimerA <= '0';
			end if;

			if loadTimerB = '1' then
				timerB <= tbhi & tblo;
				clkTimerB <= '0';
			end if;
		end if;
	end process;


-- -----------------------------------------------------------------------
-- Interrupts
-- -----------------------------------------------------------------------
	resetIrq <= ((myRd = '1') and (addr = X"D")) or (reset = '1');
	irq_n <= not(ir);
	intr_serial <= '0';

	process(clk)
	begin
		if rising_edge(clk) then
			if enable = '1' then
				ir <= ir
				or (intr_timerA and mask_timerA)
				or (intr_timerB and mask_timerB)
				or (intr_serial and mask_serial)
				or (intr_flagn and mask_flagn);
			end if;

			if myWr = '1' then
				case addr is
				when X"D" =>
					if di(7) ='0' then
						mask_timerA <= mask_timerA and (not di(0));
						mask_timerB <= mask_timerB and (not di(1));
						mask_serial <= mask_serial and (not di(3));
						mask_flagn <= mask_flagn and (not di(4));
					else
						mask_timerA <= mask_timerA or di(0);
						mask_timerB <= mask_timerB or di(1);
						mask_serial <= mask_serial or di(3);
						mask_flagn <= mask_flagn or di(4);
					end if;
				when others =>
					null;
				end case;
			end if;

			if resetIrq then
				ir <= '0';
			end if;

			if reset = '1' then
				mask_timerA <= '0';
				mask_timerB <= '0';
				mask_serial <= '0';
				mask_flagn <= '0';
			end if;
		end if;
	end process;




-- -----------------------------------------------------------------------
-- FLAG_N input
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			prevFlag_n <= flag_n;
			if (flag_n = '0') and (prevFlag_n = '1') then
				intr_flagn <= '1';
			end if;
			if resetIrq then
				intr_flagn <= '0';
			end if;
		end if;
	end process;


-- -----------------------------------------------------------------------
-- Write registers
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
--			resetIrq <= '0';
			if enable = '1' then
				forceTimerA <= '0';
				forceTimerB <= '0';
--				cra_runmode_reg <= cra_runmode;
--				crb_runmode_reg <= crb_runmode;
			end if;
			if myWr = '1' then
				case addr is
				when X"E" =>
					cra_pbon <= di(1);
					cra_outmode <= di(2);
--					cra_runmode <= di(3);
					forceTimerA <= di(4);
					cra_inmode <= di(5);
					cra_spmode <= di(6);
					cra_todin <= di(7);
				when X"F" =>
					crb_pbon <= di(1);
					crb_outmode <= di(2);
--					crb_runmode <= di(3);
					forceTimerB <= di(4);
					crb_inmode5 <= di(5);
					crb_inmode6 <= di(6);
					crb_alarm <= di(7);
				when others => null;
				end case;
			end if;
			if reset = '1' then
				cra_pbon <= '0';
				cra_outmode <= '0';
--				cra_runmode <= '0';
				cra_inmode <= '0';
				cra_spmode <= '0';
				cra_todin <= '0';
				crb_pbon <= '0';
				crb_outmode <= '0';
--				crb_runmode <= '0';
				crb_inmode5 <= '0';
				crb_inmode6 <= '0';
				crb_alarm <= '0';
			end if;
		end if;
	end process;


-- -----------------------------------------------------------------------
-- Read registers
-- -----------------------------------------------------------------------
	process(clk)
	begin
		if rising_edge(clk) then
			case addr is
			when X"0" => do <= ppai;
			when X"1" => do <= ppbi;
			when X"2" => do <= DDRA;
			when X"3" => do <= DDRB;
			when X"4" => do <= timera(7 downto 0);
			when X"5" => do <= timera(15 downto 8);
			when X"6" => do <= timerb(7 downto 0);
			when X"7" => do <= timerb(15 downto 8);
			when X"8" => do <= "0000" & tod_latch_10ths;
			when X"9" => do <= "0" & tod_latch_secs;
			when X"A" => do <= "0" & tod_latch_mins;
			when X"B" => do <= tod_latch_pm & "00" & tod_latch_hrs;
			when X"C" => do <= (others => '0');
			when X"D" => do <= ir & "00" & intr_flagn & intr_serial & "0" & intr_timerB & intr_timerA;
			when X"E" => do <= cra_todin & cra_spmode & cra_inmode & '0' & cra_runmode & cra_outmode & cra_pbon & cra_start;
			when X"F" => do <= crb_alarm & crb_inmode6 & crb_inmode5 & '0' & crb_runmode & crb_outmode & crb_pbon & crb_start;
			when others => do <= (others => '-');
			end case;
		end if;
	end process;
end Behavioral;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -