summaryrefslogtreecommitdiffstats
path: root/PIC/state_machine.vhd
diff options
context:
space:
mode:
authorVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
committerVaino Kauppila <vaino@vke.fi>2026-04-19 12:32:58 +0300
commiteb8643ddbef43547eb7bfe58789a3908926c7258 (patch)
treefadfba88a1c71b266b8c67df166a3a6ead6b30d1 /PIC/state_machine.vhd
parent129a1c975dbd0c042576010b1f6eb40d19fc5733 (diff)
downloadvhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.tar.gz
vhdl_pic-eb8643ddbef43547eb7bfe58789a3908926c7258.zip
refactor dir structure, add fib.c
Diffstat (limited to 'PIC/state_machine.vhd')
-rw-r--r--PIC/state_machine.vhd222
1 files changed, 0 insertions, 222 deletions
diff --git a/PIC/state_machine.vhd b/PIC/state_machine.vhd
deleted file mode 100644
index 24da581..0000000
--- a/PIC/state_machine.vhd
+++ /dev/null
@@ -1,222 +0,0 @@
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.numeric_std.all;
-use work.alu_types.all;
-
-use work.decoder.all;
-
-entity state_machine is
- port(
- clk : in std_logic;
- opcode : in std_logic_vector(13 downto 0);
-
- reset : in std_logic;
-
- op : out alu_op;
- 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);
- addr : out std_logic_vector(6 downto 0) := (others => '0');
-
- use_literal : out std_logic;
- we_status : out std_logic := '0';
-
- stack_push : out std_logic := '0';
- stack_pop : out std_logic := '0';
- stack_din : out std_logic_vector(12 downto 0) := (others => '0');
- stack_dout : in std_logic_vector(12 downto 0);
-
- alu_skip : in std_logic;
- alu_result : in std_logic_vector(7 downto 0)
- );
-
-
-end entity state_machine;
-
-architecture rtl of state_machine is
- type state_t is (IFetch, MRead, Execute, MWrite);
-
- signal pc_internal : std_logic_vector(12 downto 0) := (others => '0');
- signal state : state_t := IFetch;
- signal pclath : std_logic_vector(4 downto 0) := (others => '0');
-
-begin
- pc <= pc_internal;
-
- fsm : process(clk)
- variable instr : instruction_t;
-
- -- do we do a phantom nop after this instruction?
- variable do_phantom_nop : boolean := false;
- variable is_phantom : boolean := false;
- -- true when phantom came from DECFSZ/INCFSZ skip (must still increment PC)
- -- false when phantom came from GOTO/CALL/RETURN (PC already at target)
- variable is_skip_phantom : boolean := false;
- begin
-
- if rising_edge(clk) then
-
- re_mem <= '0';
- we_mem <= '0';
- we_w <= '0';
- we_status <= '0';
- instr_ret <= '0';
- stack_push <= '0';
- stack_pop <= '0';
-
- if reset = '1' then
- pc_internal <= (others => '0');
- pclath <= (others => '0');
- state <= IFetch;
- do_phantom_nop := false;
- else
-
- case state is
- when IFetch =>
-
- -- if we had a branch before, this cycle is a NOP.
- if 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
- else
- instr := instruction_decode(opcode);
- is_phantom := false;
- is_skip_phantom := false;
- end if;
-
- -- set use_literal based on decoded instruction, holds through MWrite
- if instr.class = LITERAL_OP then
- use_literal <= '1';
- else
- use_literal <= '0';
- end if;
-
- -- for literal operations
- data <= instr.k(7 downto 0);
-
- -- for memory-read/write operations
- addr <= instr.f;
-
- -- for bit-select operations
- bit_select <= instr.b;
-
- state <= Mread;
-
- when MRead =>
-
- -- read memory addressed by the opcode
- -- MOVWF, CLRF, CLRW, NOP are write-only.
- if instr.class = BIT_OP or
- (instr.class = BYTE_OP and
- instr.op /= MOVWF and instr.op /= CLRF and
- instr.op /= CLRW and instr.op /= NOP) then
- re_mem <= '1';
- end if;
-
- state <= Execute;
-
- when Execute =>
-
- op <= instr.op; -- move the decoded instruction to the ALU
-
- if not is_phantom then
-
- -- increment PC or change address, different for different instructions.
- if instr.op = GOTO then
-
- pc_internal <= "00" & instr.k;
- do_phantom_nop := true;
- is_skip_phantom := false;
-
- elsif instr.op = CALL then
-
- -- push PC+1 to the stack
- stack_din <= std_logic_vector(unsigned(pc_internal) + 1);
- stack_push <= '1';
-
- -- go to the function we called
- pc_internal <= "00" & instr.k;
- do_phantom_nop := true;
- is_skip_phantom := false;
-
- elsif instr.op = RETUR or instr.op = RETLW then
-
- -- pop the PC from stack.
- pc_internal <= stack_dout;
- stack_pop <= '1'; -- pop deferred to next cycle.
- do_phantom_nop := true;
- is_skip_phantom := false;
-
- else
- pc_internal <= std_logic_vector(unsigned(pc_internal) + 1);
- end if;
-
- elsif is_skip_phantom then
- -- skip phantom: PC was at the skipped instruction, step past it
- pc_internal <= std_logic_vector(unsigned(pc_internal) + 1);
- end if;
- -- branch phantom: PC already at target, no change needed
-
- state <= MWrite;
-
- when MWrite =>
-
- -- write to correct memory based on class (skip for phantom NOP)
- if not is_phantom then
- case instr.class is
- when BYTE_OP =>
- if instr.op /= NOP then
- if instr.d = '1' then
- we_mem <= '1';
- -- Write to PCLATH (addr 0x0A): latch upper PC bits
- if instr.f = "0001010" then
- pclath <= alu_result(4 downto 0);
- 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;
- is_skip_phantom := false;
- end if;
- else
- we_w <= '1';
- end if;
- end if;
- when BIT_OP =>
- -- NOT for the BTFSS or BTFSC instructions.
- if instr.op = BCF or instr.op = BSF then
- we_mem <= '1';
- end if;
- when LITERAL_OP =>
- if instr.op /= NOP and instr.op /= RETUR then
- we_w <= '1';
- end if;
- when others => null;
- end case;
- end if;
-
- -- 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
- do_phantom_nop := true;
- is_skip_phantom := true;
- end if;
-
- if not is_phantom then
- we_status <= '1';
- instr_ret <= '1';
- end if;
- state <= IFetch;
-
- end case;
- end if; -- reset
- end if;
- end process fsm;
-
-end architecture rtl;