Line 554... |
Line 554... |
signal IDX_Offset : ADDRESS_TYPE := x"0000";
|
signal IDX_Offset : ADDRESS_TYPE := x"0000";
|
|
|
signal IDX_Sel_l : std_logic_vector(2 downto 0) := "000";
|
signal IDX_Sel_l : std_logic_vector(2 downto 0) := "000";
|
signal IDX_Sel_h : std_logic_vector(2 downto 0) := "000";
|
signal IDX_Sel_h : std_logic_vector(2 downto 0) := "000";
|
|
|
signal IDX_Reg_l : integer := 0;
|
|
signal IDX_Reg_h : integer := 0;
|
|
|
|
signal IDX_NoOffset_Calc : ADDRESS_TYPE := x"0000";
|
signal IDX_NoOffset_Calc : ADDRESS_TYPE := x"0000";
|
signal IDX_Offset_Calc : ADDRESS_TYPE := x"0000";
|
signal IDX_Offset_Calc : ADDRESS_TYPE := x"0000";
|
|
|
begin
|
begin
|
|
|
Line 599... |
Line 596... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Address bus selection/generation logic
|
-- Address bus selection/generation logic
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
|
-- 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
|
|
-- always helpful, so the generic allows the CPU to use unsigned math
|
|
-- for the offsets. This makes the range 0 to +255 instead.
|
|
|
|
IDX_Offset_SX <= '0' when Unsigned_Index_Offsets else Operand1(7);
|
|
|
|
IDX_Offset(15 downto 8) <= (others => IDX_Offset_SX);
|
|
IDX_Offset(7 downto 0) <= Operand1;
|
|
|
|
-- Enable_Auto_Increment uses the LSB to determine whether or not to
|
|
-- do the auto-increment, so we need to lock the LSB for each operand
|
|
-- if it is enabled. This forces [ODD:EVEN] pairing.
|
|
|
|
IDX_Sel_l <= (SubOp(2 downto 1) & '0') when Enable_Auto_Increment else
|
|
SubOp;
|
|
|
|
IDX_Sel_h <= (SubOp(2 downto 1) & '1') when Enable_Auto_Increment else
|
|
SubOp_p1;
|
|
|
|
-- Pipeline registers for the indexed and indexed with offset addresses.
|
|
Idx_Addr_Calc_proc: process( Clock )
|
|
variable IDX_Reg_l, IDX_Reg_h : integer range 0 to 7 := 0;
|
|
begin
|
|
IDX_Reg_l := conv_integer(IDX_Sel_l);
|
|
IDX_Reg_h := conv_integer(IDX_Sel_h);
|
|
if( rising_edge(Clock))then
|
|
IDX_NoOffset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l));
|
|
IDX_Offset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) +
|
|
IDX_Offset;
|
|
end if;
|
|
end process;
|
|
|
-- Address selection logic based on current CPU state. This is combinatorial,
|
-- Address selection logic based on current CPU state. This is combinatorial,
|
-- as adding pipeline registration would add a clock cycle to every instr,
|
-- as adding pipeline registration would add a clock cycle to every instr,
|
-- without really adding the Fmax to compensate.
|
-- without really adding the Fmax to compensate.
|
Address_Logic: process(CPU_State, Operand1, Operand2, IDX_NoOffset_Calc,
|
Address_Logic: process(CPU_State, Operand1, Operand2, IDX_NoOffset_Calc,
|
IDX_Offset_Calc, ISR_Addr_Offset, Stack_Ptr,
|
IDX_Offset_Calc, ISR_Addr_Offset, Stack_Ptr,
|
Line 631... |
Line 661... |
Open8_Bus.Address <= Program_Ctr;
|
Open8_Bus.Address <= Program_Ctr;
|
|
|
end case;
|
end case;
|
end process;
|
end process;
|
|
|
-- 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
|
|
-- always helpful, so the generic allows the CPU to use unsigned math
|
|
-- for the offsets. This makes the range 0 to +255 instead.
|
|
|
|
IDX_Offset_SX <= '0' when Unsigned_Index_Offsets else Operand1(7);
|
|
|
|
IDX_Offset(15 downto 8) <= (others => IDX_Offset_SX);
|
|
IDX_Offset(7 downto 0) <= Operand1;
|
|
|
|
-- Enable_Auto_Increment uses the LSB to determine whether or not to
|
|
-- do the auto-increment, so we need to lock the LSB for each operand
|
|
-- if it is enabled. This forces [ODD:EVEN] pairing.
|
|
|
|
IDX_Sel_l <= (SubOp(2 downto 1) & '0') when Enable_Auto_Increment else
|
|
SubOp;
|
|
|
|
IDX_Sel_h <= (SubOp(2 downto 1) & '1') when Enable_Auto_Increment else
|
|
SubOp_p1;
|
|
|
|
IDX_Reg_l <= conv_integer(IDX_Sel_l);
|
|
IDX_Reg_h <= conv_integer(IDX_Sel_h);
|
|
|
|
-- Pipeline registers for the indexed and indexed with offset addresses.
|
|
Idx_Addr_Calc_proc: process( Clock, Reset )
|
|
variable Reg, Reg_1 : integer range 0 to 7 := 0;
|
|
begin
|
|
if( Reset = Reset_Level )then
|
|
IDX_NoOffset_Calc <= x"0000";
|
|
IDX_Offset_Calc <= x"0000";
|
|
elsif( rising_edge(Clock))then
|
|
IDX_NoOffset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l));
|
|
IDX_Offset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) +
|
|
IDX_Offset;
|
|
end if;
|
|
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 762... |
Line 755... |
|
|
when OP_STK =>
|
when OP_STK =>
|
case SubOp is
|
case SubOp is
|
when SOP_RSP =>
|
when SOP_RSP =>
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( not Allow_Stack_Address_Move )then
|
-- The behavior of RSP is controlled by the
|
-- The default behavior for this instruction is to simply
|
-- Allow_Stack_Address_Move generic. If it is TRUE, then RSP
|
-- repoint the SP to the HDL default
|
-- can read/write the SP arbitrarily based on R1:R0. Otherwise
|
SP_Ctrl.Oper <= SP_CLR;
|
-- it will use the default behavior of resetting it to the
|
end if;
|
-- HDL generic address.
|
if( Allow_Stack_Address_Move and
|
if( Allow_Stack_Address_Move )then
|
Flags(STACK_XFER_FLAG) = '1' )then
|
if( Flags(STACK_XFER_FLAG) = '1' )then
|
-- If RSP is set to allow SP moves, and the specified flag
|
-- If RSP is set to allow SP moves, and the specified flag
|
-- is true, then signal the stack pointer logic to load
|
-- is true, then signal the stack pointer logic to load
|
-- from R1:R0
|
-- from R1:R0
|
SP_Ctrl.Oper <= SP_SET;
|
SP_Ctrl.Oper <= SP_SET;
|
end if;
|
else -- Flags(STACK_XFER_FLAG = '0'
|
if( Allow_Stack_Address_Move and
|
|
Flags(STACK_XFER_FLAG) = '0')then
|
|
-- If RSP is set to allow SP moves, and the specified flag
|
-- If RSP is set to allow SP moves, and the specified flag
|
-- is false, then signal the ALU to copy the stack pointer
|
-- is false, then signal the ALU to copy the stack pointer
|
-- to R1:R0
|
-- to R1:R0
|
ALU_Ctrl.Oper <= ALU_RSP;
|
ALU_Ctrl.Oper <= ALU_RSP;
|
end if;
|
end if;
|
|
else
|
|
-- The default behavior for this instruction is to simply
|
|
-- repoint the SP to the HDL default
|
|
SP_Ctrl.Oper <= SP_CLR;
|
|
end if;
|
|
|
when SOP_RTS | SOP_RTI =>
|
when SOP_RTS | SOP_RTI =>
|
CPU_Next_State <= RTS_C1;
|
CPU_Next_State <= RTS_C1;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
SP_Ctrl.Oper <= SP_POP;
|
SP_Ctrl.Oper <= SP_POP;
|
Line 1100... |
Line 1096... |
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Reg <= SubOp_p1;
|
ALU_Ctrl.Reg <= SubOp_p1;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Basic Stack Manipulation (PSH, POP, RSP)
|
-- Basic Stack Manipulation (PSH, POP)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when PSH_C1 =>
|
when PSH_C1 =>
|
CPU_Next_State <= IPF_C1;
|
CPU_Next_State <= IPF_C1;
|
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
|
|