aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Stirling <opensource@mikestirling.co.uk>2011-07-25 22:17:35 +0100
committerMike Stirling <opensource@mikestirling.co.uk>2011-07-25 22:17:35 +0100
commit3ea54eb8b11e87333ad809c7bbfd9537c2fc8250 (patch)
tree780d9588c327fddc5a56a257193b6718efa72ba4
parent9a5d41651b1e31f4cab5ee820f95a00c0a4baa67 (diff)
downloadfpga-bbc-3ea54eb8b11e87333ad809c7bbfd9537c2fc8250.tar.gz
fpga-bbc-3ea54eb8b11e87333ad809c7bbfd9537c2fc8250.tar.bz2
fpga-bbc-3ea54eb8b11e87333ad809c7bbfd9537c2fc8250.zip
Boots to "BBC Computer" message with dummy keyboard and interrupts disabled (something is keeping the interrupt permanently asserted). Need to add paged ROMs in Flash (no more room in the FPGA).
-rw-r--r--bbc_micro_de1.qsf1
-rw-r--r--bbc_micro_de1.vhd163
-rw-r--r--m6522.vhd1
-rw-r--r--m6522_tb.vhd323
4 files changed, 437 insertions, 51 deletions
diff --git a/bbc_micro_de1.qsf b/bbc_micro_de1.qsf
index d6578f0..4003236 100644
--- a/bbc_micro_de1.qsf
+++ b/bbc_micro_de1.qsf
@@ -512,4 +512,5 @@ set_global_assignment -name QIP_FILE pll32.qip
set_global_assignment -name VHDL_FILE bbc_micro_de1.vhd
set_global_assignment -name VHDL_FILE bbc_micro_de1_tb.vhd
set_global_assignment -name QIP_FILE ehbasic.qip
+set_global_assignment -name VHDL_FILE m6522_tb.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file
diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
index f48507f..0d29726 100644
--- a/bbc_micro_de1.vhd
+++ b/bbc_micro_de1.vhd
@@ -337,10 +337,16 @@ signal reset_n : std_logic;
-- Clock enable counter
-- CPU and video cycles are interleaved. The CPU runs at 2 MHz (every 16th
-- cycle) and the video subsystem is enabled on every odd cycle.
-signal clken_counter : unsigned(3 downto 0);
+signal clken_counter : unsigned(4 downto 0);
signal slomo_counter : unsigned(17 downto 0);
-signal cpu_clken : std_logic;
-signal vid_clken : std_logic;
+signal cpu_cycle : std_logic; -- Qualifies all 2 MHz cycles
+signal cpu_cycle_mask : std_logic; -- Set to mask CPU cycles until 1 MHz cycle is complete
+signal cpu_clken : std_logic; -- 2 MHz cycles in which the CPU is enabled
+-- IO cycles are out of phase with the CPU
+signal vid_clken : std_logic; -- 16 MHz video cycles
+signal mhz4_clken : std_logic; -- Used by 6522
+signal mhz2_clken : std_logic; -- Used for latching CPU address for clock stretch
+signal mhz1_clken : std_logic; -- 1 MHz bus and associated peripherals, 6522 phase 2
-- Testing
signal test_uart_do : std_logic_vector(7 downto 0);
@@ -376,6 +382,10 @@ signal crtc_lpstb : std_logic := '0';
signal crtc_ma : std_logic_vector(13 downto 0);
signal crtc_ra : std_logic_vector(4 downto 0);
+-- Decoded display address after address translation for hardware
+-- scrolling
+signal display_a : std_logic_vector(14 downto 0);
+
-- "VIDPROC" signals
signal vidproc_invert_n : std_logic;
signal r_in : std_logic;
@@ -430,10 +440,6 @@ signal user_via_pb_in : std_logic_vector(7 downto 0);
signal user_via_pb_out : std_logic_vector(7 downto 0);
signal user_via_pb_oe_n : std_logic_vector(7 downto 0);
--- Common VIA signals
-signal via_clken : std_logic;
-signal via_phase2 : std_logic;
-
-- IC32 latch on System VIA
signal ic32 : std_logic_vector(7 downto 0);
signal sound_enable_n : std_logic;
@@ -465,6 +471,8 @@ signal adlc_enable : std_logic; -- 0xFEA0-FEBF (Econet)
signal adc_enable : std_logic; -- 0xFEC0-FEDF
signal tube_enable : std_logic; -- 0xFEE0-FEFF
+signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral
+
begin
-------------------------
-- COMPONENT INSTANCES
@@ -555,13 +563,13 @@ begin
);
-- MOS ROM
--- mos : os12 port map (
--- cpu_a(13 downto 0),
--- clock,
--- mos_d );
- test_rom : ehbasic port map (
+ mos : os12 port map (
cpu_a(13 downto 0),
- clock, mos_d );
+ clock,
+ mos_d );
+-- test_rom : ehbasic port map (
+-- cpu_a(13 downto 0),
+-- clock, mos_d );
-- System VIA
system_via : m6522 port map (
@@ -589,9 +597,9 @@ begin
sys_via_pb_in,
sys_via_pb_out,
sys_via_pb_oe_n,
- via_phase2,
+ mhz1_clken,
reset_n,
- via_clken,
+ mhz4_clken,
clock
);
@@ -621,9 +629,9 @@ begin
user_via_pb_in,
user_via_pb_out,
user_via_pb_oe_n,
- via_phase2,
+ mhz1_clken,
reset_n,
- via_clken,
+ mhz4_clken,
clock
);
@@ -631,16 +639,20 @@ begin
pll_reset <= not SW(9);
reset_n <= not (pll_reset or not pll_locked);
- -- Clock enable generation
- -- CPU is on cycle 0 of 16 (2 MHz)
- -- Video is on all odd cycles
- cpu_clken <= '1' when clken_counter = 0 and (SW(8) = '1' or slomo_counter = 0) else '0';
- vid_clken <= clken_counter(0);
- -- FIXME: VIAs - this is wrong. They should actually run at 1MHz (so 4 MHz clken in this
- -- case) and the CPU should be stalled until the 1 MHz bus cycle is complete
- via_clken <= clken_counter(0) and clken_counter(1);
- via_phase2 <= clken_counter(3);
- process(clock,reset_n)
+ -- Clock enable generation - 32 MHz clock split into 32 cycles
+ -- CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses)
+ -- Video is on all odd cycles (16 MHz)
+ -- 1 MHz cycles are on cycle 31 (1 MHz)
+ vid_clken <= clken_counter(0); -- 1,3,5...
+ mhz4_clken <= clken_counter(0) and clken_counter(1) and clken_counter(2); -- 7/15/23/31
+ mhz2_clken <= mhz4_clken and clken_counter(3); -- 15/31
+ mhz1_clken <= mhz2_clken and clken_counter(4); -- 31
+ cpu_cycle <=
+ not (clken_counter(0) or clken_counter(1) or clken_counter(2) or clken_counter(3))
+ when (SW(8) = '1' or slomo_counter = 0) else '0'; -- 0/16
+ cpu_clken <= cpu_cycle and not cpu_cycle_mask;
+
+ clk_gen: process(clock,reset_n)
begin
if reset_n = '0' then
clken_counter <= (others => '0');
@@ -652,6 +664,24 @@ begin
end if;
end if;
end process;
+
+ cycle_stretch: process(clock,reset_n)
+ begin
+ if reset_n = '0' then
+ cpu_cycle_mask <= '0';
+ elsif rising_edge(clock) and mhz2_clken = '1' then
+ if mhz1_enable = '1' and cpu_cycle_mask = '0' then
+ -- Block CPU cycles until 1 MHz cycle has completed
+ cpu_cycle_mask <= '1';
+ end if;
+ if mhz1_clken = '1' then
+ -- CPU can run again
+ -- FIXME: This may not be correct in terms of CPU cycles, but it
+ -- should work
+ cpu_cycle_mask <= '0';
+ end if;
+ end if;
+ end process;
-- CPU configuration and fixed signals
cpu_mode <= "00"; -- 6502
@@ -675,6 +705,11 @@ begin
io_fred <= '1' when cpu_a(15 downto 8) = "11111100" else '0';
io_jim <= '1' when cpu_a(15 downto 8) = "11111101" else '0';
io_sheila <= '1' when cpu_a(15 downto 8) = "11111110" else '0';
+ -- The following IO regions are accessed at 1 MHz and hence will stall the
+ -- CPU accordingly
+ mhz1_enable <= io_fred or io_jim or
+ adc_enable or sys_via_enable or user_via_enable or
+ serproc_enable or acia_enable or crtc_enable;
-- SHEILA address demux
-- All the system peripherals are mapped into this page as follows:
@@ -750,7 +785,8 @@ begin
user_via_do when user_via_enable = '1' else
test_uart_do when io_fred = '1' else
SRAM_DQ(7 downto 0);
- cpu_irq_n <= sys_via_irq_n and user_via_irq_n;
+ --cpu_irq_n <= sys_via_irq_n; -- and user_via_irq_n;
+ cpu_irq_n <= '1';
-- SRAM bus
SRAM_UB_N <= '1';
@@ -783,21 +819,58 @@ begin
else
-- Fetch data from previous display cycle
SRAM_WE_N <= '1';
- SRAM_ADDR <= "000" & crtc_ma(11 downto 0) & crtc_ra(2 downto 0);
+ SRAM_ADDR <= "000" & display_a;
end if;
end if;
end process;
+ -- Address translation logic for calculation of display address
+ process(crtc_ma,crtc_ra,disp_addr_offs)
+ variable aa : unsigned(3 downto 0);
+ begin
+ if crtc_ma(12) = '0' then
+ -- No adjustment
+ aa := unsigned(crtc_ma(11 downto 8));
+ else
+ -- Address adjusted according to screen mode to compensate for
+ -- wrap at 0x8000.
+ case disp_addr_offs is
+ when "00" =>
+ -- Mode 3 - restart at 0x4000
+ aa := unsigned(crtc_ma(11 downto 8)) + 8;
+ when "01" =>
+ -- Mode 6 - restart at 0x6000
+ aa := unsigned(crtc_ma(11 downto 8)) + 12;
+ when "10" =>
+ -- Mode 0,1,2 - restart at 0x3000
+ aa := unsigned(crtc_ma(11 downto 8)) + 6;
+ when "11" =>
+ -- Mode 4,5 - restart at 0x5800
+ aa := unsigned(crtc_ma(11 downto 8)) + 11;
+ when others =>
+ null;
+ end case;
+ end if;
+
+ if crtc_ma(13) = '0' then
+ -- HI RES
+ display_a <= std_logic_vector(aa(3 downto 0)) & crtc_ma(7 downto 0) & crtc_ra(2 downto 0);
+ else
+ -- TTX VDU
+ display_a <= std_logic(aa(3)) & "1111" & crtc_ma(9 downto 0);
+ end if;
+ end process;
+
-- VIDPROC
vidproc_invert_n <= '1';
r_in <= '0';
g_in <= '0';
b_in <= '0';
- GPIO_0(0) <= crtc_clken;
- GPIO_0(1) <= crtc_hsync;
- GPIO_0(2) <= crtc_vsync;
- GPIO_0(3) <= not (crtc_hsync xor crtc_vsync);
+ GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
+ GPIO_0(1) <= cpu_clken;
+ GPIO_0(2) <= cpu_cycle_mask;
+ GPIO_0(3) <= mhz1_enable;
-- CRTC drives video out (CSYNC on HSYNC output, VSYNC high)
VGA_HS <= not (crtc_hsync xor crtc_vsync);
@@ -808,10 +881,12 @@ begin
-- Connections to System VIA
sys_via_ca1_in <= crtc_vsync;
- sys_via_cb1_in <= crtc_lpstb;
+ sys_via_ca2_in <= '0'; -- Keyboard interrupt
+ sys_via_cb1_in <= '0'; -- /EOC
+ sys_via_cb2_in <= crtc_lpstb;
-- Connections to User VIA (user port is output on green LEDs)
- --LEDG <= user_via_pb_out;
+ LEDG <= user_via_pb_out;
-- IC32 latch
sound_enable_n <= ic32(0);
@@ -834,8 +909,6 @@ begin
end if;
end process;
- LEDG <= ic32;
-
-- Keyboard LEDs
LEDR(0) <= not caps_lock_led_n;
LEDR(1) <= not shift_lock_led_n;
@@ -855,22 +928,12 @@ begin
when 7 => sys_via_pa_in(7) <= SW(2);
when 8 => sys_via_pa_in(7) <= SW(1);
when 9 => sys_via_pa_in(7) <= SW(0);
- when others => sys_via_pa_in(7) <= '1';
+ when others => sys_via_pa_in(7) <= '0';
end case;
else
- sys_via_pa_in(7) <= '1';
+ -- 'W' output of keyboard IC2 is inverse data, so 0 is no key pressed
+ sys_via_pa_in(7) <= '0';
end if;
end process;
-
--- process(clock,reset_n)
--- begin
--- if reset_n = '0' then
--- LEDG <= "00000000";
--- elsif rising_edge(clock) then
--- if cpu_a(15 downto 0) = "0000001010001111" and cpu_r_nw = '0' then
--- LEDG <= cpu_do;
--- end if;
--- end if;
--- end process;
end architecture;
diff --git a/m6522.vhd b/m6522.vhd
index cb3e827..f0b974a 100644
--- a/m6522.vhd
+++ b/m6522.vhd
@@ -191,7 +191,6 @@ architecture RTL of M6522 is
signal final_irq : std_logic;
begin
-
p_phase : process
begin
-- internal clock phase
diff --git a/m6522_tb.vhd b/m6522_tb.vhd
new file mode 100644
index 0000000..7c4b1fa
--- /dev/null
+++ b/m6522_tb.vhd
@@ -0,0 +1,323 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+entity m6522_tb is
+end entity;
+
+architecture tb of m6522_tb is
+
+component M6522 is
+ port (
+
+ I_RS : in std_logic_vector(3 downto 0);
+ I_DATA : in std_logic_vector(7 downto 0);
+ O_DATA : out std_logic_vector(7 downto 0);
+ O_DATA_OE_L : out std_logic;
+
+ I_RW_L : in std_logic;
+ I_CS1 : in std_logic;
+ I_CS2_L : in std_logic;
+
+ O_IRQ_L : out std_logic; -- note, not open drain
+ -- port a
+ I_CA1 : in std_logic;
+ I_CA2 : in std_logic;
+ O_CA2 : out std_logic;
+ O_CA2_OE_L : out std_logic;
+
+ I_PA : in std_logic_vector(7 downto 0);
+ O_PA : out std_logic_vector(7 downto 0);
+ O_PA_OE_L : out std_logic_vector(7 downto 0);
+
+ -- port b
+ I_CB1 : in std_logic;
+ O_CB1 : out std_logic;
+ O_CB1_OE_L : out std_logic;
+
+ I_CB2 : in std_logic;
+ O_CB2 : out std_logic;
+ O_CB2_OE_L : out std_logic;
+
+ I_PB : in std_logic_vector(7 downto 0);
+ O_PB : out std_logic_vector(7 downto 0);
+ O_PB_OE_L : out std_logic_vector(7 downto 0);
+
+ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+ RESET_L : in std_logic;
+ ENA_4 : in std_logic; -- clk enable
+ CLK : in std_logic
+ );
+end component;
+
+signal rs : std_logic_vector(3 downto 0) := "0000";
+signal di : std_logic_vector(7 downto 0) := "00000000";
+signal do : std_logic_vector(7 downto 0);
+signal n_d_oe : std_logic;
+signal r_nw : std_logic := '1';
+signal cs1 : std_logic := '0';
+signal n_cs2 : std_logic := '0';
+signal n_irq : std_logic;
+signal ca1_in : std_logic := '0';
+signal ca2_in : std_logic := '0';
+signal ca2_out : std_logic;
+signal n_ca2_oe : std_logic;
+signal pa_in : std_logic_vector(7 downto 0) := "00000000";
+signal pa_out : std_logic_vector(7 downto 0);
+signal n_pa_oe : std_logic_vector(7 downto 0);
+signal cb1_in : std_logic := '0';
+signal cb1_out : std_logic;
+signal n_cb1_oe : std_logic;
+signal cb2_in : std_logic := '0';
+signal cb2_out : std_logic;
+signal n_cb2_oe : std_logic;
+signal pb_in : std_logic_vector(7 downto 0) := "00000000";
+signal pb_out : std_logic_vector(7 downto 0);
+signal n_pb_oe : std_logic_vector(7 downto 0);
+
+signal phase2 : std_logic := '0';
+signal n_reset : std_logic := '0';
+signal clken : std_logic := '0';
+signal clock : std_logic := '0';
+
+begin
+
+ uut: m6522 port map (
+ rs, di, do, n_d_oe,
+ r_nw, cs1, n_cs2, n_irq,
+ ca1_in, ca2_in, ca2_out, n_ca2_oe,
+ pa_in, pa_out, n_pa_oe,
+ cb1_in, cb1_out, n_cb1_oe,
+ cb2_in, cb2_out, n_cb2_oe,
+ pb_in, pb_out, n_pb_oe,
+ phase2, n_reset, clken, clock
+ );
+
+ clock <= not clock after 125 ns; -- 4x 1 MHz
+ phase2 <= not phase2 after 500 ns;
+ clken <= '1'; -- all cycles enabled
+
+ process
+ begin
+ wait for 1 us;
+ -- Release reset
+ n_reset <= '1';
+ end process;
+
+ process
+
+ procedure reg_write(
+ a : in std_logic_vector(3 downto 0);
+ d : in std_logic_vector(7 downto 0)) is
+ begin
+ wait until falling_edge(phase2);
+ rs <= a;
+ di <= d;
+ cs1 <= '1';
+ r_nw <= '0';
+ wait until falling_edge(phase2);
+ cs1 <= '0';
+ r_nw <= '1';
+ end procedure;
+
+ procedure reg_read(
+ a : in std_logic_vector(3 downto 0)) is
+ begin
+ wait until falling_edge(phase2);
+ rs <= a;
+ cs1 <= '1';
+ r_nw <= '1';
+ wait until falling_edge(phase2);
+ cs1 <= '0';
+ end procedure;
+
+ begin
+ wait for 2 us;
+
+ -- Set port A and B to output
+ reg_write("0010","11111111");
+ reg_write("0011","11111111");
+
+ -- Write to port B
+ reg_write("0000","10101010");
+ -- Write to port B
+ reg_write("0000","01010101");
+ -- Write to port A (no handshake)
+ reg_write("1111","10101010");
+ -- Write to port A (with handshake)
+ reg_write("0001","01010101");
+
+ -- Set port A and B to input
+ reg_write("0010","00000000");
+ reg_write("0011","00000000");
+
+ -- Apply input stimuli and read from ports
+ pa_in <= "10101010";
+ pb_in <= "01010101";
+ reg_read("0000");
+ reg_read("0001");
+
+ -- Test CA1 interrupt
+ ca1_in <= '0';
+ reg_write("1100","00000001"); -- PCR - interrupt on rising edge
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","10000010"); -- Enable CA1 interrupt
+ ca1_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0001"); -- Should clear interrupt
+ wait for 2 us;
+ reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+ ca1_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_write("1101","00000010"); -- Should clear interrupt
+ wait for 2 us;
+ reg_write("1110","00000010"); -- Disable CA1 interrupt
+
+ -- Test CB1 interrupt
+ cb1_in <= '0';
+ reg_write("1100","00010000"); -- PCR - interrupt on rising edge
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","10010000"); -- Enable CB1 interrupt
+ cb1_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0000"); -- Should clear interrupt
+ wait for 2 us;
+ reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+ cb1_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_write("1101","00010000"); -- Should clear interrupt
+ wait for 2 us;
+ reg_write("1110","00010000"); -- Disable CA1 interrupt
+
+ -- Test CA2 interrupt modes
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","10000001"); -- Enable CA2 interrupt
+ -- mode 2 (+ve edge, clear on read/write)
+ reg_write("1100","00000100"); -- PCR
+ ca2_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("1111"); -- Should not clear interrupt
+ reg_read("0001"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 0 (-ve edge, clear on read/write)
+ reg_write("1100","00000000"); -- PCR
+ ca2_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("1111"); -- Should not clear interrupt
+ reg_read("0001"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 3 (+ve edge, don't clear on read/write)
+ reg_write("1100","00000110");
+ ca2_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("1111"); -- Should not clear interrupt
+ reg_read("0001"); -- Should not clear interrupt
+ reg_write("1101","00000001"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 1 (-ve edge, don't clear on read/write)
+ reg_write("1100","00000010");
+ ca2_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("1111"); -- Should not clear interrupt
+ reg_read("0001"); -- Should not clear interrupt
+ reg_write("1101","00000001"); -- Should clear interrupt
+ wait for 2 us;
+
+ -- Test CA2 output modes
+ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+ reg_write("1100","00001000");
+ -- mode 5 (set low for 1 cycle on read/write ORA)
+ reg_write("1100","00001010");
+ -- mode 6 (held low)
+ reg_write("1100","00001100");
+ -- mode 7 (held high)
+ reg_write("1100","00001110");
+
+ -- Test CB2 interrupt modes
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","10001000"); -- Enable CB2 interrupt
+ -- mode 2 (+ve edge, clear on read/write)
+ reg_write("1100","01000000"); -- PCR
+ cb2_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0000"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 0 (-ve edge, clear on read/write)
+ reg_write("1100","00000000"); -- PCR
+ cb2_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0000"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 3 (+ve edge, don't clear on read/write)
+ reg_write("1100","01100000");
+ cb2_in <= '1'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0000"); -- Should not clear interrupt
+ reg_write("1101","00001000"); -- Should clear interrupt
+ wait for 2 us;
+ -- mode 1 (-ve edge, don't clear on read/write)
+ reg_write("1100","00100000");
+ cb2_in <= '0'; -- Trigger event
+ wait for 2 us;
+ reg_read("1101");
+ reg_read("0000"); -- Should not clear interrupt
+ reg_write("1101","00001000"); -- Should clear interrupt
+ wait for 2 us;
+
+ -- Test CB2 output modes
+ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+ reg_write("1100","10000000");
+ -- mode 5 (set low for 1 cycle on read/write ORA)
+ reg_write("1100","10100000");
+ -- mode 6 (held low)
+ reg_write("1100","11000000");
+ -- mode 7 (held high)
+ reg_write("1100","11100000");
+
+ -- Timer 1 timeout
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","11000000"); -- Enable timer 1 interrupt
+ -- Count to 16
+ reg_write("0100","00010000");
+ reg_write("0101","00000000");
+ wait for 50 us;
+ -- Count to 16
+ reg_write("0100","00010000");
+ reg_write("0101","00000000"); -- Should clear interrupt
+ wait for 50 us;
+ reg_read("0100"); -- Should clear interrupt
+
+ -- Timer 2 timeout
+ reg_write("1101","01111111"); -- Clear interrupts
+ reg_write("1110","01111111"); -- Disable all interrupts
+ reg_write("1110","10100000"); -- Enable timer 2 interrupt
+ -- Count to 16
+ reg_write("1000","00010000");
+ reg_write("1001","00000000");
+ wait for 50 us;
+ -- Count to 16
+ reg_write("1000","00010000");
+ reg_write("1001","00000000"); -- Should clear interrupt
+ wait for 50 us;
+ reg_read("1000"); -- Should clear interrupt
+
+ wait;
+ end process;
+
+end architecture;