Line 150... |
Line 150... |
-- Seth Henry 07/27/11 Optimized logic for timing, merged blocks into
|
-- Seth Henry 07/27/11 Optimized logic for timing, merged blocks into
|
-- single entity.
|
-- single entity.
|
-- Seth Henry 09/20/11 Added BRK_Implements_WAI option, allowing the
|
-- Seth Henry 09/20/11 Added BRK_Implements_WAI option, allowing the
|
-- processor to wait for an interrupt instead of the
|
-- processor to wait for an interrupt instead of the
|
-- normal BRK behavior.
|
-- normal BRK behavior.
|
-- Seth Henry 12/20/11 Modified core to allow WAIT_FOR_INT state to idle
|
-- Seth Henry 12/20/11 Modified core to allow WAI_Cx state to idle
|
-- the bus entirely (Rd_Enable is low)
|
-- the bus entirely (Rd_Enable is low)
|
-- Seth Henry 02/03/12 Replaced complex interrupt controller with simpler,
|
-- Seth Henry 02/03/12 Replaced complex interrupt controller with simpler,
|
-- faster logic that simply does priority encoding.
|
-- faster logic that simply does priority encoding.
|
-- Seth Henry 08/06/13 Removed HALT functionality
|
-- Seth Henry 08/06/13 Removed HALT functionality
|
-- Seth Henry 10/29/15 Fixed inverted carry logic in CMP and SBC instrs
|
-- Seth Henry 10/29/15 Fixed inverted carry logic in CMP and SBC instrs
|
Line 174... |
Line 174... |
-- original modes as fixed offset values.
|
-- original modes as fixed offset values.
|
-- Modified the ALU section with a new ALU operation
|
-- Modified the ALU section with a new ALU operation
|
-- for GMSK. This allowed the .data field to be
|
-- for GMSK. This allowed the .data field to be
|
-- removed and Operand1 used in its place, which
|
-- removed and Operand1 used in its place, which
|
-- simplified the logic a great deal.
|
-- simplified the logic a great deal.
|
|
-- Seth Henry 03/16/20 Added CPU_Halt input back, only now as an input to
|
|
-- the instruction decode state, where it acts as a
|
|
-- modified form of the BRK instruction that holds
|
|
-- state until CPU_Halt is deasserted. This has a
|
|
-- much smaller impact on Fmax/complexity than the
|
|
-- original clock enable, but imposes a mild impact
|
|
-- due to the need to reset the instruction pipeline
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_arith.all;
|
Line 199... |
Line 206... |
Default_Interrupt_Mask : DATA_TYPE := x"FF"; -- Enable all Ints
|
Default_Interrupt_Mask : DATA_TYPE := x"FF"; -- Enable all Ints
|
Reset_Level : std_logic := '0' ); -- Active reset level
|
Reset_Level : std_logic := '0' ); -- Active reset level
|
port(
|
port(
|
Clock : in std_logic;
|
Clock : in std_logic;
|
Reset : in std_logic;
|
Reset : in std_logic;
|
Interrupts : in INTERRUPT_BUNDLE;
|
CPU_Halt : in std_logic := '0';
|
|
Interrupts : in INTERRUPT_BUNDLE := x"00";
|
--
|
--
|
Address : out ADDRESS_TYPE;
|
Address : out ADDRESS_TYPE;
|
Rd_Data : in DATA_TYPE;
|
Rd_Data : in DATA_TYPE;
|
Rd_Enable : out std_logic;
|
Rd_Enable : out std_logic;
|
Wr_Data : out DATA_TYPE;
|
Wr_Data : out DATA_TYPE;
|
Line 219... |
Line 227... |
constant INT_VECTOR_4 : ADDRESS_TYPE := ISR_Start_Addr+8;
|
constant INT_VECTOR_4 : ADDRESS_TYPE := ISR_Start_Addr+8;
|
constant INT_VECTOR_5 : ADDRESS_TYPE := ISR_Start_Addr+10;
|
constant INT_VECTOR_5 : ADDRESS_TYPE := ISR_Start_Addr+10;
|
constant INT_VECTOR_6 : ADDRESS_TYPE := ISR_Start_Addr+12;
|
constant INT_VECTOR_6 : ADDRESS_TYPE := ISR_Start_Addr+12;
|
constant INT_VECTOR_7 : ADDRESS_TYPE := ISR_Start_Addr+14;
|
constant INT_VECTOR_7 : ADDRESS_TYPE := ISR_Start_Addr+14;
|
|
|
signal CPU_Next_State : CPU_STATES := PIPE_FILL_0;
|
signal CPU_Next_State : CPU_STATES := IPF_C0;
|
signal CPU_State : CPU_STATES := PIPE_FILL_0;
|
signal CPU_State : CPU_STATES := IPF_C0;
|
|
|
|
signal CPU_Halt_Req : std_logic;
|
|
|
signal Cache_Ctrl : CACHE_MODES := CACHE_IDLE;
|
signal Cache_Ctrl : CACHE_MODES := CACHE_IDLE;
|
|
|
signal Opcode : OPCODE_TYPE := (others => '0');
|
signal Opcode : OPCODE_TYPE := (others => '0');
|
signal SubOp, SubOp_p1 : SUBOP_TYPE := (others => '0');
|
signal SubOp, SubOp_p1 : SUBOP_TYPE := (others => '0');
|
Line 307... |
Line 317... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Combinatorial portion of CPU finite state machine
|
-- Combinatorial portion of CPU finite state machine
|
-- State Logic / Instruction Decoding & Execution
|
-- State Logic / Instruction Decoding & Execution
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
State_Logic: process(CPU_State, Flags, Int_Mask, Opcode,
|
State_Logic: process(CPU_State, Flags, Int_Mask, CPU_Halt_Req, Opcode,
|
SubOp , SubOp_p1, Operand1, Operand2, Int_Req )
|
SubOp , SubOp_p1, Operand1, Operand2, Int_Req )
|
variable Reg : integer range 0 to 7 := 0;
|
variable Reg : integer range 0 to 7 := 0;
|
begin
|
begin
|
CPU_Next_State <= CPU_State;
|
CPU_Next_State <= CPU_State;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
Line 336... |
Line 346... |
|
|
case CPU_State is
|
case CPU_State is
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Initial Instruction fetch & decode
|
-- Initial Instruction fetch & decode
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when PIPE_FILL_0 =>
|
when IPF_C0 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= IPF_C1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when PIPE_FILL_1 =>
|
when IPF_C1 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= IPF_C2;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when PIPE_FILL_2 =>
|
when IPF_C2 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when INSTR_DECODE =>
|
when IDC_C0 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
|
|
case Opcode is
|
case Opcode is
|
when OP_PSH =>
|
when OP_PSH =>
|
CPU_Next_State <= PSH_C1;
|
CPU_Next_State <= PSH_C1;
|
Line 382... |
Line 392... |
ALU_Ctrl.Oper <= ALU_DEC;
|
ALU_Ctrl.Oper <= ALU_DEC;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
when OP_INT =>
|
when OP_INT =>
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
-- Make sure the requested interrupt is actually enabled first
|
-- Make sure the requested interrupt is actually enabled first.
|
|
-- Also, unlike CPU_Halt, the INT instruction is actually being
|
|
-- executed, so go ahead and increment the program counter before
|
|
-- pausing so the CPU restarts on the next instruction.
|
if( Int_Mask(Reg) = '1' )then
|
if( Int_Mask(Reg) = '1' )then
|
CPU_Next_State <= WAIT_FOR_INT;
|
CPU_Next_State <= WAI_Cx;
|
INT_Ctrl.Soft_Ints(Reg) <= '1';
|
INT_Ctrl.Soft_Ints(Reg) <= '1';
|
end if;
|
end if;
|
|
|
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
|
if( not Allow_Stack_Address_Move )then
|
|
-- The default behavior for this instruction is to simply
|
|
-- repoint the SP to the HDL default
|
SP_Ctrl.Oper <= SP_CLR;
|
SP_Ctrl.Oper <= SP_CLR;
|
end if;
|
end if;
|
if( Allow_Stack_Address_Move and Flags(Stack_Xfer_Flag) = '1' )then
|
if( Allow_Stack_Address_Move and
|
|
Flags(Stack_Xfer_Flag) = '1' )then
|
|
-- If RSP is set to allow SP moves, and the specified flag
|
|
-- is true, then signal the stack pointer logic to load
|
|
-- from R1:R0
|
SP_Ctrl.Oper <= SP_SET;
|
SP_Ctrl.Oper <= SP_SET;
|
end if;
|
end if;
|
if( Allow_Stack_Address_Move and Flags(Stack_Xfer_Flag) = '0')then
|
if( Allow_Stack_Address_Move and
|
|
Flags(Stack_Xfer_Flag) = '0')then
|
|
-- If RSP is set to allow SP moves, and the specified flag
|
|
-- is false, then signal the ALU to copy the stack pointer
|
|
-- to R1:R0
|
ALU_Ctrl.Oper <= ALU_RSP;
|
ALU_Ctrl.Oper <= ALU_RSP;
|
end if;
|
end if;
|
|
|
when SOP_RTS | SOP_RTI =>
|
when SOP_RTS | SOP_RTI =>
|
CPU_Next_State <= RTS_C1;
|
CPU_Next_State <= RTS_C1;
|
SP_Ctrl.Oper <= SP_POP;
|
SP_Ctrl.Oper <= SP_POP;
|
|
|
when SOP_BRK =>
|
when SOP_BRK =>
|
CPU_Next_State <= BRK_C1;
|
|
PC_Ctrl.Offset <= PC_REV2;
|
|
-- If Break implements Wait for Interrupt, replace the normal
|
|
-- flow with a modified version of the INT instruction
|
|
if( BRK_Implements_WAI )then
|
if( BRK_Implements_WAI )then
|
CPU_Next_State <= WAIT_FOR_INT;
|
-- If BRK_Implements_WAI, then jump to the WAI_Cx and
|
|
-- increment the PC similar to an ISR flow.
|
|
CPU_Next_State <= WAI_Cx;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
else
|
|
-- If Break is implemented normally, back the PC up by
|
|
-- 2 and return through IPF_C0 in order to execute a 5
|
|
-- clock cycle delay
|
|
CPU_Next_State <= BRK_C1;
|
|
PC_Ctrl.Offset <= PC_REV2;
|
end if;
|
end if;
|
|
|
when SOP_JMP =>
|
when SOP_JMP =>
|
CPU_Next_State <= JMP_C1;
|
CPU_Next_State <= JMP_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Line 468... |
Line 495... |
when OP_LDI =>
|
when OP_LDI =>
|
CPU_Next_State <= LDI_C1;
|
CPU_Next_State <= LDI_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
|
|
when OP_LDO =>
|
when OP_LDO =>
|
CPU_Next_State <= LDO_C1;
|
CPU_Next_State <= LDO_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Offset <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
|
|
Line 506... |
Line 532... |
|
|
end case;
|
end case;
|
|
|
if( Int_Req = '1' )then
|
if( Int_Req = '1' )then
|
CPU_Next_State <= ISR_C1;
|
CPU_Next_State <= ISR_C1;
|
|
end if;
|
|
|
|
if( CPU_Halt_Req = '1' )then
|
|
CPU_Next_State <= WAH_Cx;
|
|
end if;
|
|
|
|
-- If either of these override conditions are true, the decoder needs
|
|
-- to undo everything it just setup, since even "single-cycle"
|
|
-- instructions will be executed again upon return.
|
|
if( Int_Req = '1' or CPU_Halt_Req = '1' )then
|
|
-- In either case, we want to skip loading the cache, as the cache
|
|
-- will be invalid by the time we get back.
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
-- Rewind the PC by 3 to compensate for the pipeline registers
|
-- Rewind the PC by 3 to put the PC back to the current instruction,
|
|
-- compensating for the pipeline registers.
|
PC_Ctrl.Offset <= PC_REV3;
|
PC_Ctrl.Offset <= PC_REV3;
|
-- Reset all of the sub-block controls to IDLE, to avoid unintended
|
-- Reset all of the sub-block controls to IDLE, to avoid unintended
|
-- operation due to the current instruction
|
-- operation due to the current instruction.
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
|
-- Interrupt logic outside of the state machine needs this to be set
|
|
-- to DATA_RD_MEM, while CPU_Halt considers this a "don't care".
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
INT_Ctrl.Soft_Ints <= (others => '0');
|
-- If an INT/SMSK instruction was going to be executed, it will get
|
|
-- executed again when normal processing resumes, so axe their
|
|
-- requests for now.
|
|
INT_Ctrl.Mask_Set <= '0';
|
|
INT_Ctrl.Soft_Ints(Reg) <= '0';
|
end if;
|
end if;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Program Control (BR0_C1, BR1_C1, DBNZ_C1, JMP )
|
-- Program Control (BR0_C1, BR1_C1, DBNZ_C1, JMP )
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
when BRN_C1 =>
|
when BRN_C1 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Flags(Reg) = Opcode(0) )then
|
if( Flags(Reg) = Opcode(0) )then
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
PC_Ctrl.Offset <= Operand1;
|
PC_Ctrl.Offset <= Operand1;
|
end if;
|
end if;
|
|
|
when DBNZ_C1 =>
|
when DBNZ_C1 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Flags(PSR_Z) = '0' )then
|
if( Flags(PSR_Z) = '0' )then
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
PC_Ctrl.Offset <= Operand1;
|
PC_Ctrl.Offset <= Operand1;
|
end if;
|
end if;
|
|
|
when JMP_C1 =>
|
when JMP_C1 =>
|
CPU_Next_State <= JMP_C2;
|
CPU_Next_State <= JMP_C2;
|
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
|
|
when JMP_C2 =>
|
when JMP_C2 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Data Storage - Load from memory (LDA, LDI, LDO, LDX)
|
-- Data Storage - Load from memory (LDA, LDI, LDO, LDX)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
Line 570... |
Line 615... |
CPU_Next_State <= LDI_C1;
|
CPU_Next_State <= LDI_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDI_C1 =>
|
when LDI_C1 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
Line 601... |
Line 646... |
CPU_Next_State <= LDX_C4;
|
CPU_Next_State <= LDX_C4;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDX_C4 =>
|
when LDX_C4 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Reg <= ACCUM;
|
ALU_Ctrl.Reg <= ACCUM;
|
|
|
Line 621... |
Line 666... |
when STA_C2 =>
|
when STA_C2 =>
|
CPU_Next_State <= STA_C3;
|
CPU_Next_State <= STA_C3;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when STA_C3 =>
|
when STA_C3 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= IPF_C2;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when STO_C1 =>
|
when STO_C1 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
CPU_Next_State <= STO_C2;
|
CPU_Next_State <= STO_C2;
|
ALU_Ctrl.Oper <= ALU_UPP;
|
ALU_Ctrl.Oper <= ALU_UPP;
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
end if;
|
end if;
|
|
|
when STO_C2 =>
|
when STO_C2 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= IPF_C1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1';
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1';
|
|
|
when STX_C1 =>
|
when STX_C1 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= IPF_C1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
CPU_Next_State <= STX_C2;
|
CPU_Next_State <= STX_C2;
|
ALU_Ctrl.Oper <= ALU_UPP;
|
ALU_Ctrl.Oper <= ALU_UPP;
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
end if;
|
end if;
|
|
|
when STX_C2 =>
|
when STX_C2 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= IPF_C2;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Oper <= ALU_UPP2;
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1';
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1';
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
Line 665... |
Line 710... |
-- Because we have to backup the pipeline by 1 to refetch the 2nd
|
-- Because we have to backup the pipeline by 1 to refetch the 2nd
|
-- instruction/first operand, we have to return through PF2. Also, we
|
-- instruction/first operand, we have to return through PF2. Also, we
|
-- need to tell the ALU to store the results to R1:R0 here. Note that
|
-- need to tell the ALU to store the results to R1:R0 here. Note that
|
-- there is no ALU_Ctrl.Reg, as this is implied in the ALU instruction
|
-- there is no ALU_Ctrl.Reg, as this is implied in the ALU instruction
|
when MUL_C1 =>
|
when MUL_C1 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= IPF_C2;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_MUL;
|
ALU_Ctrl.Oper <= ALU_MUL;
|
|
|
when UPP_C1 =>
|
when UPP_C1 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= IPF_C2;
|
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, RSP)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when PSH_C1 =>
|
when PSH_C1 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= IPF_C1;
|
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
|
|
when POP_C1 =>
|
when POP_C1 =>
|
CPU_Next_State <= POP_C2;
|
CPU_Next_State <= POP_C2;
|
|
|
Line 695... |
Line 740... |
CPU_Next_State <= POP_C4;
|
CPU_Next_State <= POP_C4;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when POP_C4 =>
|
when POP_C4 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= IDC_C0;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_POP;
|
ALU_Ctrl.Oper <= ALU_POP;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Subroutines & Interrupts (RTS, JSR)
|
-- Subroutines & Interrupts (RTS, JSR)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when WAIT_FOR_INT => -- For soft interrupts only, halt the Program_Ctr
|
when WAI_Cx => -- For soft interrupts only, halt the Program_Ctr
|
DP_Ctrl.Src <= DATA_BUS_IDLE;
|
DP_Ctrl.Src <= DATA_BUS_IDLE;
|
if( Int_Req = '1' )then
|
if( Int_Req = '1' )then
|
CPU_Next_State <= ISR_C1;
|
CPU_Next_State <= ISR_C1;
|
-- Rewind the PC by 3 to compensate for the pipeline registers
|
-- Rewind the PC by 3 to put the PC back to would have been the next
|
|
-- instruction, compensating for the pipeline registers.
|
PC_Ctrl.Offset <= PC_REV3;
|
PC_Ctrl.Offset <= PC_REV3;
|
-- Reset all of the sub-block controls to IDLE, to avoid unintended
|
-- Reset all of the sub-block controls to IDLE, to avoid unintended
|
-- operation due to the current instruction
|
-- operation due to the current instruction
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
end if;
|
end if;
|
|
|
|
when WAH_Cx => -- Holds until CPU_Halt_Req is deasserted.
|
|
DP_Ctrl.Src <= DATA_BUS_IDLE;
|
|
if( CPU_Halt_Req = '0' )then
|
|
CPU_Next_State <= IPF_C0;
|
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
|
end if;
|
|
|
|
when BRK_C1 => -- Debugging (BRK) Performs a 5-clock NOP.
|
|
CPU_Next_State <= IPF_C0;
|
|
|
when ISR_C1 =>
|
when ISR_C1 =>
|
CPU_Next_State <= ISR_C2;
|
CPU_Next_State <= ISR_C2;
|
INT_Ctrl.Incr_ISR <= '1';
|
INT_Ctrl.Incr_ISR <= '1';
|
|
|
when ISR_C2 =>
|
when ISR_C2 =>
|
Line 741... |
Line 797... |
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Reg <= PC_LSB;
|
DP_Ctrl.Reg <= PC_LSB;
|
|
|
when JSR_C2 =>
|
when JSR_C2 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
|
|
when RTS_C1 =>
|
when RTS_C1 =>
|
CPU_Next_State <= RTS_C2;
|
CPU_Next_State <= RTS_C2;
|
Line 765... |
Line 821... |
when RTS_C4 =>
|
when RTS_C4 =>
|
CPU_Next_State <= RTS_C5;
|
CPU_Next_State <= RTS_C5;
|
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
|
|
when RTS_C5 =>
|
when RTS_C5 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= IPF_C0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
-- if this is an RTI, then we need to clear the I bit
|
-- if this is an RTI, then we need to clear the I bit
|
if( SubOp = SOP_RTI )then
|
if( SubOp = SOP_RTI )then
|
CPU_Next_State <= RTI_C6;
|
CPU_Next_State <= RTI_C6;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
ALU_Ctrl.Oper <= ALU_CLP;
|
ALU_Ctrl.Oper <= ALU_CLP;
|
ALU_Ctrl.Reg <= conv_std_logic_vector(PSR_I,3);
|
ALU_Ctrl.Reg <= conv_std_logic_vector(PSR_I,3);
|
end if;
|
end if;
|
|
|
when RTI_C6 =>
|
when RTI_C6 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= IPF_C1;
|
PC_Ctrl.Offset <= PC_NEXT;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_RFLG;
|
ALU_Ctrl.Oper <= ALU_RFLG;
|
|
|
-------------------------------------------------------------------------------
|
|
-- Debugging (BRK) Performs a 5-clock NOP
|
|
-------------------------------------------------------------------------------
|
|
when BRK_C1 =>
|
|
CPU_Next_State <= PIPE_FILL_0;
|
|
|
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
end process;
|
end process;
|
Line 804... |
Line 854... |
variable Index : integer range 0 to 7 := 0;
|
variable Index : integer range 0 to 7 := 0;
|
variable Sum : std_logic_vector(8 downto 0) := "000000000";
|
variable Sum : std_logic_vector(8 downto 0) := "000000000";
|
variable Temp : std_logic_vector(8 downto 0) := "000000000";
|
variable Temp : std_logic_vector(8 downto 0) := "000000000";
|
begin
|
begin
|
if( Reset = Reset_Level )then
|
if( Reset = Reset_Level )then
|
CPU_State <= PIPE_FILL_0;
|
CPU_State <= IPF_C0;
|
Opcode <= OP_INC;
|
Opcode <= OP_INC;
|
SubOp <= ACCUM;
|
SubOp <= ACCUM;
|
SubOp_p1 <= ACCUM;
|
SubOp_p1 <= ACCUM;
|
Operand1 <= x"00";
|
Operand1 <= x"00";
|
Operand2 <= x"00";
|
Operand2 <= x"00";
|
Instr_Prefetch <= '0';
|
Instr_Prefetch <= '0';
|
Prefetch <= x"00";
|
Prefetch <= x"00";
|
|
|
|
CPU_Halt_Req <= '0';
|
|
|
Wr_Data <= (others => '0');
|
Wr_Data <= (others => '0');
|
Wr_Enable <= '0';
|
Wr_Enable <= '0';
|
Rd_Enable <= '1';
|
Rd_Enable <= '1';
|
|
|
Program_Ctr <= Program_Start_Addr;
|
Program_Ctr <= Program_Start_Addr;
|
Line 840... |
Line 892... |
Regfile(i) <= (others => '0');
|
Regfile(i) <= (others => '0');
|
end loop;
|
end loop;
|
Flags <= x"00";
|
Flags <= x"00";
|
|
|
elsif( rising_edge(Clock) )then
|
elsif( rising_edge(Clock) )then
|
|
|
|
CPU_Halt_Req <= CPU_Halt;
|
|
|
Wr_Enable <= '0';
|
Wr_Enable <= '0';
|
Wr_Data <= x"00";
|
Wr_Data <= x"00";
|
Rd_Enable <= '0';
|
Rd_Enable <= '0';
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|