summaryrefslogtreecommitdiffstats
path: root/hdl/state_machine.vhd
diff options
context:
space:
mode:
authorVäinö Kauppila <vaino@vke.fi>2026-04-20 18:21:28 +0300
committerVäinö Kauppila <vaino@vke.fi>2026-04-20 18:21:28 +0300
commit7af8820d2dbd441f95cb5c8bde74e4649878383c (patch)
tree46775e7fc08137d8d40a69d70be4e2d76265cc66 /hdl/state_machine.vhd
parentbada76e705a4219fe2da27bb59c32dbdd0601514 (diff)
downloadvhdl_pic-7af8820d2dbd441f95cb5c8bde74e4649878383c.tar.gz
vhdl_pic-7af8820d2dbd441f95cb5c8bde74e4649878383c.zip
prog rom generation using Amaranth
Diffstat (limited to 'hdl/state_machine.vhd')
-rw-r--r--hdl/state_machine.vhd62
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;