From 46e1210381106707c2df7f07c56023eb6b760763 Mon Sep 17 00:00:00 2001 From: Väinö Kauppila Date: Sun, 19 Apr 2026 19:02:42 +0300 Subject: BSRAM progmem. fix Makefile memory command that does not work. add interrupts, bank 1, timer0. Timer0 not tested. --- hdl/state_machine.vhd | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'hdl/state_machine.vhd') diff --git a/hdl/state_machine.vhd b/hdl/state_machine.vhd index 5b1c623..1fb5291 100644 --- a/hdl/state_machine.vhd +++ b/hdl/state_machine.vhd @@ -31,7 +31,11 @@ entity state_machine is stack_dout : in std_logic_vector(12 downto 0); alu_skip : in std_logic; - alu_result : in std_logic_vector(7 downto 0) + alu_result : in std_logic_vector(7 downto 0); + + irq_pending : in std_logic; + gie_clear : out std_logic := '0'; + gie_set : out std_logic := '0' ); @@ -67,6 +71,8 @@ begin instr_ret <= '0'; stack_push <= '0'; stack_pop <= '0'; + gie_clear <= '0'; + gie_set <= '0'; if reset = '1' then pc_internal <= (others => '0'); @@ -78,16 +84,30 @@ begin case state is when IFetch => + -- Hardware interrupt: push PC, jump to vector, clear GIE + if irq_pending = '1' and not do_phantom_nop then + stack_din <= pc_internal; + stack_push <= '1'; + pc_internal <= "0000000000100"; -- 0x0004 + gie_clear <= '1'; + instr := instruction_decode((others => '0')); + is_phantom := true; + is_skip_phantom := false; + do_phantom_nop := false; + state <= MRead; + -- if we had a branch before, this cycle is a NOP. - if do_phantom_nop then + elsif do_phantom_nop then instr := instruction_decode((others => '0')); do_phantom_nop := false; is_phantom := true; -- is_skip_phantom carries over from whoever set do_phantom_nop + state <= MRead; else instr := instruction_decode(opcode); is_phantom := false; is_skip_phantom := false; + state <= MRead; end if; -- set use_literal based on decoded instruction, holds through MWrite @@ -106,7 +126,6 @@ begin -- for bit-select operations bit_select <= instr.b; - state <= Mread; when MRead => @@ -145,13 +164,16 @@ begin do_phantom_nop := true; is_skip_phantom := false; - elsif instr.op = RETUR or instr.op = RETLW then + elsif instr.op = RETUR or instr.op = RETLW or instr.op = RETFIE then -- pop the PC from stack. pc_internal <= stack_dout; - stack_pop <= '1'; -- pop deferred to next cycle. + stack_pop <= '1'; do_phantom_nop := true; is_skip_phantom := false; + if instr.op = RETFIE then + gie_set <= '1'; + end if; else pc_internal <= std_logic_vector(unsigned(pc_internal) + 1); -- cgit v1.3