Line 284... |
Line 284... |
constant USEC_DLY : std_logic_vector :=
|
constant USEC_DLY : std_logic_vector :=
|
conv_std_logic_vector(USEC_VAL - 1, USEC_WDT);
|
conv_std_logic_vector(USEC_VAL - 1, USEC_WDT);
|
signal uSec_Cntr : std_logic_vector( USEC_WDT - 1 downto 0 );
|
signal uSec_Cntr : std_logic_vector( USEC_WDT - 1 downto 0 );
|
signal uSec_Tick : std_logic;
|
signal uSec_Tick : std_logic;
|
|
|
constant INT_VECTOR_0 : ADDRESS_TYPE := ISR_Start_Addr;
|
|
constant INT_VECTOR_1 : ADDRESS_TYPE := ISR_Start_Addr+2;
|
|
constant INT_VECTOR_2 : ADDRESS_TYPE := ISR_Start_Addr+4;
|
|
constant INT_VECTOR_3 : ADDRESS_TYPE := ISR_Start_Addr+6;
|
|
constant INT_VECTOR_4 : ADDRESS_TYPE := ISR_Start_Addr+8;
|
|
constant INT_VECTOR_5 : ADDRESS_TYPE := ISR_Start_Addr+10;
|
|
constant INT_VECTOR_6 : ADDRESS_TYPE := ISR_Start_Addr+12;
|
|
constant INT_VECTOR_7 : ADDRESS_TYPE := ISR_Start_Addr+14;
|
|
|
|
signal CPU_Next_State : CPU_STATES := IPF_C0;
|
signal CPU_Next_State : CPU_STATES := IPF_C0;
|
signal CPU_State : CPU_STATES := IPF_C0;
|
signal CPU_State : CPU_STATES := IPF_C0;
|
|
|
signal CPU_Halt_Req : std_logic := '0';
|
signal CPU_Halt_Req : std_logic := '0';
|
signal CPU_Halt_Ack : std_logic := '0';
|
signal CPU_Halt_Ack : std_logic := '0';
|
Line 327... |
Line 318... |
signal INT_Ctrl : INT_CTRL_TYPE;
|
signal INT_Ctrl : INT_CTRL_TYPE;
|
signal Ack_D, Ack_Q, Ack_Q1: std_logic := '0';
|
signal Ack_D, Ack_Q, Ack_Q1: std_logic := '0';
|
signal Int_Req, Int_Ack : std_logic := '0';
|
signal Int_Req, Int_Ack : std_logic := '0';
|
signal Set_Mask : std_logic := '0';
|
signal Set_Mask : std_logic := '0';
|
signal Int_Mask : DATA_TYPE := x"00";
|
signal Int_Mask : DATA_TYPE := x"00";
|
signal ISR_Addr : ADDRESS_TYPE := x"0000";
|
|
signal i_Ints : INTERRUPT_BUNDLE := x"00";
|
signal i_Ints : INTERRUPT_BUNDLE := x"00";
|
signal Pending : INTERRUPT_BUNDLE := x"00";
|
signal Pending : INTERRUPT_BUNDLE := x"00";
|
signal Wait_for_FSM : std_logic := '0';
|
signal Wait_for_FSM : std_logic := '0';
|
signal Wait_for_ISR : std_logic := '0';
|
signal Wait_for_ISR : std_logic := '0';
|
|
|
|
alias ISR_Addr_Base is ISR_Start_Addr(15 downto 4);
|
|
signal ISR_Addr_Offset : std_logic_vector(3 downto 0) := x"0";
|
|
|
|
constant INT_VECTOR_0 : std_logic_vector(3 downto 0) := x"0";
|
|
constant INT_VECTOR_1 : std_logic_vector(3 downto 0) := x"2";
|
|
constant INT_VECTOR_2 : std_logic_vector(3 downto 0) := x"4";
|
|
constant INT_VECTOR_3 : std_logic_vector(3 downto 0) := x"6";
|
|
constant INT_VECTOR_4 : std_logic_vector(3 downto 0) := x"8";
|
|
constant INT_VECTOR_5 : std_logic_vector(3 downto 0) := x"A";
|
|
constant INT_VECTOR_6 : std_logic_vector(3 downto 0) := x"C";
|
|
constant INT_VECTOR_7 : std_logic_vector(3 downto 0) := x"E";
|
|
|
signal IDX_Offset : ADDRESS_TYPE := x"0000";
|
signal IDX_Offset : ADDRESS_TYPE := x"0000";
|
|
|
signal IDX_Reg_l : integer := 0;
|
signal IDX_Reg_l : integer := 0;
|
signal IDX_Reg_h : integer := 0;
|
signal IDX_Reg_h : integer := 0;
|
|
|
Line 380... |
Line 382... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Address bus selection/generation logic
|
-- Address bus selection/generation logic
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
|
-- Address selection logic based on current CPU state. This is combinatorial,
|
|
-- as adding pipeline registration would add a clock cycle to every instr,
|
|
-- without really adding the Fmax to compensate.
|
|
Address_Logic: process(CPU_State, Operand1, Operand2, IDX_NoOffset_Calc,
|
|
IDX_Offset_Calc, ISR_Addr_Offset, Stack_Ptr, Program_Ctr )
|
|
begin
|
|
case( CPU_State )is
|
|
|
|
when LDA_C2 | STA_C2 =>
|
|
Open8_Bus.Address <= Operand2 & Operand1;
|
|
|
|
when LDX_C1 | STX_C1 =>
|
|
Open8_Bus.Address <= IDX_NoOffset_Calc;
|
|
|
|
when LDO_C2 | STO_C2 =>
|
|
Open8_Bus.Address <= IDX_Offset_Calc;
|
|
|
|
when ISR_C1 | ISR_C2 =>
|
|
Open8_Bus.Address <= ISR_Addr_Base & ISR_Addr_Offset;
|
|
|
|
when PSH_C1 | POP_C1 | ISR_C3 | JSR_C1 | JSR_C2 | RTS_C1 | RTS_C2 | RTS_C3 =>
|
|
Open8_Bus.Address <= Stack_Ptr;
|
|
|
|
when others =>
|
|
Open8_Bus.Address <= Program_Ctr;
|
|
|
|
end case;
|
|
end process;
|
|
|
-- The original model treated the offset to LDO/STO as a signed value
|
-- The original model treated the offset to LDO/STO as a signed value
|
-- allowing access to locations -128 to +127 from [Rn+1:Rn]. This isn't
|
-- allowing access to locations -128 to +127 from [Rn+1:Rn]. This isn't
|
-- always helpful, so the generic allows the CPU to use unsigned math
|
-- always helpful, so the generic allows the CPU to use unsigned math
|
-- for the offsets. This makes the range 0 to +255 instead.
|
-- for the offsets. This makes the range 0 to +255 instead.
|
|
|
Line 423... |
Line 454... |
IDX_Offset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) +
|
IDX_Offset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) +
|
IDX_Offset;
|
IDX_Offset;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Address selection logic based on current CPU state. This is combinatorial,
|
|
-- as adding pipeline registration would add a clock cycle to every instr,
|
|
-- without really adding the Fmax to compensate.
|
|
Address_Logic: process(CPU_State, Operand1, Operand2, IDX_NoOffset_Calc,
|
|
IDX_Offset_Calc, ISR_Addr, Stack_Ptr, Program_Ctr )
|
|
begin
|
|
case( CPU_State )is
|
|
|
|
when LDA_C2 | STA_C2 =>
|
|
Open8_Bus.Address <= Operand2 & Operand1;
|
|
|
|
when LDX_C1 | STX_C1 =>
|
|
Open8_Bus.Address <= IDX_NoOffset_Calc;
|
|
|
|
when LDO_C2 | STO_C2 =>
|
|
Open8_Bus.Address <= IDX_Offset_Calc;
|
|
|
|
when ISR_C1 | ISR_C2 =>
|
|
Open8_Bus.Address <= ISR_Addr;
|
|
|
|
when PSH_C1 | POP_C1 | ISR_C3 | JSR_C1 | JSR_C2 | RTS_C1 | RTS_C2 | RTS_C3 =>
|
|
Open8_Bus.Address <= Stack_Ptr;
|
|
|
|
when others =>
|
|
Open8_Bus.Address <= Program_Ctr;
|
|
|
|
end case;
|
|
end process;
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Combinatorial portion of CPU finite state machine
|
-- Combinatorial portion of CPU finite state machine
|
-- State Logic / Instruction Decoding & Execution
|
-- State Logic / Instruction Decoding & Execution
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Line 1049... |
Line 1051... |
if( Enable_NMI )then
|
if( Enable_NMI )then
|
Int_Mask <= Default_Interrupt_Mask(7 downto 1) & '1';
|
Int_Mask <= Default_Interrupt_Mask(7 downto 1) & '1';
|
else
|
else
|
Int_Mask <= Default_Interrupt_Mask;
|
Int_Mask <= Default_Interrupt_Mask;
|
end if;
|
end if;
|
ISR_Addr <= INT_VECTOR_0;
|
ISR_Addr_Offset <= INT_VECTOR_0;
|
|
|
for i in 0 to 7 loop
|
for i in 0 to 7 loop
|
Regfile(i) <= x"00";
|
Regfile(i) <= x"00";
|
end loop;
|
end loop;
|
Flags <= x"00";
|
Flags <= x"00";
|
Line 1212... |
Line 1214... |
Wait_for_ISR <= '0';
|
Wait_for_ISR <= '0';
|
end if;
|
end if;
|
|
|
if( Wait_for_FSM = '0' and Wait_for_ISR = '0' )then
|
if( Wait_for_FSM = '0' and Wait_for_ISR = '0' )then
|
if( Pending(0) = '1' )then
|
if( Pending(0) = '1' )then
|
ISR_Addr <= INT_VECTOR_0;
|
ISR_Addr_Offset <= INT_VECTOR_0;
|
Pending(0) <= '0';
|
Pending(0) <= '0';
|
elsif( Pending(1) = '1' )then
|
elsif( Pending(1) = '1' )then
|
ISR_Addr <= INT_VECTOR_1;
|
ISR_Addr_Offset <= INT_VECTOR_1;
|
Pending(1) <= '0';
|
Pending(1) <= '0';
|
elsif( Pending(2) = '1' )then
|
elsif( Pending(2) = '1' )then
|
ISR_Addr <= INT_VECTOR_2;
|
ISR_Addr_Offset <= INT_VECTOR_2;
|
Pending(2) <= '0';
|
Pending(2) <= '0';
|
elsif( Pending(3) = '1' )then
|
elsif( Pending(3) = '1' )then
|
ISR_Addr <= INT_VECTOR_3;
|
ISR_Addr_Offset <= INT_VECTOR_3;
|
Pending(3) <= '0';
|
Pending(3) <= '0';
|
elsif( Pending(4) = '1' )then
|
elsif( Pending(4) = '1' )then
|
ISR_Addr <= INT_VECTOR_4;
|
ISR_Addr_Offset <= INT_VECTOR_4;
|
Pending(4) <= '0';
|
Pending(4) <= '0';
|
elsif( Pending(5) = '1' )then
|
elsif( Pending(5) = '1' )then
|
ISR_Addr <= INT_VECTOR_5;
|
ISR_Addr_Offset <= INT_VECTOR_5;
|
Pending(5) <= '0';
|
Pending(5) <= '0';
|
elsif( Pending(6) = '1' )then
|
elsif( Pending(6) = '1' )then
|
ISR_Addr <= INT_VECTOR_6;
|
ISR_Addr_Offset <= INT_VECTOR_6;
|
Pending(6) <= '0';
|
Pending(6) <= '0';
|
elsif( Pending(7) = '1' )then
|
elsif( Pending(7) = '1' )then
|
ISR_Addr <= INT_VECTOR_7;
|
ISR_Addr_Offset <= INT_VECTOR_7;
|
Pending(7) <= '0';
|
Pending(7) <= '0';
|
end if;
|
end if;
|
Wait_for_FSM <= or_reduce(Pending);
|
Wait_for_FSM <= or_reduce(Pending);
|
end if;
|
end if;
|
|
|
Line 1252... |
Line 1254... |
Int_Req <= Wait_for_FSM and (not Int_Ack);
|
Int_Req <= Wait_for_FSM and (not Int_Ack);
|
|
|
-- Incr_ISR allows the CPU Core to advance the vector address to pop the
|
-- Incr_ISR allows the CPU Core to advance the vector address to pop the
|
-- lower half of the address.
|
-- lower half of the address.
|
if( INT_Ctrl.Incr_ISR = '1' )then
|
if( INT_Ctrl.Incr_ISR = '1' )then
|
ISR_Addr <= ISR_Addr + 1;
|
ISR_Addr_Offset <= ISR_Addr_Offset + 1;
|
end if;
|
end if;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- ALU (Arithmetic / Logic Unit)
|
-- ALU (Arithmetic / Logic Unit)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|