diff options
Diffstat (limited to 'hdl/state_machine.vhd')
| -rw-r--r-- | hdl/state_machine.vhd | 62 |
1 files changed, 27 insertions, 35 deletions
diff --git a/hdl/state_machine.vhd b/hdl/state_machine.vhd index 33d2f33..1ab862e 100644 --- a/hdl/state_machine.vhd +++ b/hdl/state_machine.vhd @@ -16,7 +16,6 @@ entity state_machine is we_mem : out std_logic := '0'; re_mem : out std_logic := '0'; we_w : out std_logic := '0'; - instr_ret : out std_logic := '0'; bit_select : out std_logic_vector(2 downto 0) := (others => '0'); data : out std_logic_vector(7 downto 0) := (others => '0'); pc : out std_logic_vector(12 downto 0); @@ -68,7 +67,6 @@ begin we_mem <= '0'; we_w <= '0'; we_status <= '0'; - instr_ret <= '0'; stack_push <= '0'; stack_pop <= '0'; gie_clear <= '0'; @@ -86,28 +84,28 @@ begin -- 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; + 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; + do_phantom_nop := false; + state <= MRead; - -- if we had a branch before, this cycle is a NOP. + -- if we had a branch before, this cycle is a NOP. 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; + state <= MRead; else - instr := instruction_decode(opcode); - is_phantom := false; + instr := instruction_decode(opcode); + is_phantom := false; is_skip_phantom := false; - state <= MRead; + state <= MRead; end if; -- set use_literal based on decoded instruction, holds through MWrite @@ -149,8 +147,8 @@ begin -- increment PC or change address, different for different instructions. if instr.op = GOTO then - pc_internal <= "00" & instr.k; - do_phantom_nop := true; + pc_internal <= "00" & instr.k; + do_phantom_nop := true; is_skip_phantom := false; elsif instr.op = CALL then @@ -160,16 +158,16 @@ begin stack_push <= '1'; -- go to the function we called - pc_internal <= "00" & instr.k; - do_phantom_nop := true; + pc_internal <= "00" & instr.k; + do_phantom_nop := true; is_skip_phantom := false; 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'; - do_phantom_nop := true; + pc_internal <= stack_dout; + stack_pop <= '1'; + do_phantom_nop := true; is_skip_phantom := false; if instr.op = RETFIE then gie_set <= '1'; @@ -202,8 +200,8 @@ begin end if; -- Write to PCL (addr 0x02): redirect PC, like a GOTO if instr.f = "0000010" then - pc_internal <= pclath & alu_result; - do_phantom_nop := true; + pc_internal <= pclath & alu_result; + do_phantom_nop := true; is_skip_phantom := false; end if; else @@ -225,23 +223,17 @@ begin -- DECFSZ/INCFSZ/BTFSS/BTFSC: skip next instruction if ALU signals skip if not is_phantom and - (instr.op = DECFSZ or instr.op = INCFSZ or instr.op = BTFSS or instr.op = BTFSC) and alu_skip = '1' then + (instr.op = DECFSZ or instr.op = INCFSZ or instr.op = BTFSS or instr.op = BTFSC) and alu_skip = '1' then do_phantom_nop := true; is_skip_phantom := true; end if; - if not is_phantom then + if not is_phantom and + instr.op /= GOTO and instr.op /= CALL and + instr.op /= RETUR and instr.op /= RETLW then we_status <= '1'; - -- branch instructions complete over 2 cycles; pulse instr_ret only - -- on the phantom NOP cycle (below), not here - if instr.op /= GOTO and instr.op /= CALL and - instr.op /= RETUR and instr.op /= RETLW then - instr_ret <= '1'; - end if; - elsif not is_skip_phantom then - -- branch phantom NOP: this is the true end of the 2-cycle instruction - instr_ret <= '1'; end if; + state <= IFetch; end case; |
