Line 1... |
Line 1... |
-- Copyright (c)2006, 2011, 2012, 2013, 2015, 2019 Jeremy Seth Henry
|
-- Copyright (c)2006, 2011, 2012, 2013, 2015, 2019, 2020 Jeremy Seth Henry
|
-- All rights reserved.
|
-- All rights reserved.
|
--
|
--
|
-- Redistribution and use in source and binary forms, with or without
|
-- Redistribution and use in source and binary forms, with or without
|
-- modification, are permitted provided that the following conditions are met:
|
-- modification, are permitted provided that the following conditions are met:
|
-- * Redistributions of source code must retain the above copyright
|
-- * Redistributions of source code must retain the above copyright
|
Line 164... |
Line 164... |
-- Seth Henry 03/11/20 Split the address logic from the main state machine
|
-- Seth Henry 03/11/20 Split the address logic from the main state machine
|
-- in order to simplify things and eliminate
|
-- in order to simplify things and eliminate
|
-- redundancies. Came across and fixed a problem with
|
-- redundancies. Came across and fixed a problem with
|
-- the STO instruction when Enable_Auto_Increment is
|
-- the STO instruction when Enable_Auto_Increment is
|
-- NOT set.
|
-- NOT set.
|
-- Seth Henry 03/11/20 Renamed core to "o8_cpu" to fit theme settled on
|
-- Seth Henry 03/12/20 Rationalized the naming of the CPU flags to match
|
-- over multiple projects.
|
-- the assembler names. Also fixed an issue where
|
|
-- the I bit wasn't being cleared after interrupts.
|
|
-- Simplified the program counter logic to only use
|
|
-- the offset for increments, redefining the
|
|
-- original modes as fixed offset values.
|
|
-- Modified the ALU section with a new ALU operation
|
|
-- for GMSK. This allowed the .data field to be
|
|
-- removed and Operand1 used in its place, which
|
|
-- simplified the logic a great deal.
|
|
|
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 182... |
Line 190... |
generic(
|
generic(
|
Program_Start_Addr : ADDRESS_TYPE := x"0000"; -- Initial PC location
|
Program_Start_Addr : ADDRESS_TYPE := x"0000"; -- Initial PC location
|
ISR_Start_Addr : ADDRESS_TYPE := x"FFF0"; -- Bottom of ISR vec's
|
ISR_Start_Addr : ADDRESS_TYPE := x"FFF0"; -- Bottom of ISR vec's
|
Stack_Start_Addr : ADDRESS_TYPE := x"03FF"; -- Top of Stack
|
Stack_Start_Addr : ADDRESS_TYPE := x"03FF"; -- Top of Stack
|
Allow_Stack_Address_Move : boolean := false; -- Use Normal v8 RSP
|
Allow_Stack_Address_Move : boolean := false; -- Use Normal v8 RSP
|
Stack_Xfer_Flag : integer := FL_GP1; -- If enabled, use GP1 to control RSP
|
Stack_Xfer_Flag : integer := PSR_GP4; -- If enabled, use GP4 to control RSP
|
Enable_Auto_Increment : boolean := false; -- Modify indexed instr
|
Enable_Auto_Increment : boolean := false; -- Modify indexed instr
|
BRK_Implements_WAI : boolean := false; -- BRK -> Wait for Int
|
BRK_Implements_WAI : boolean := false; -- BRK -> Wait for Int
|
Enable_NMI : boolean := true; -- Force INTR0 enabled
|
Enable_NMI : boolean := true; -- Force INTR0 enabled
|
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
|
Line 211... |
Line 219... |
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 Halt : std_logic;
|
|
|
|
signal CPU_Next_State : CPU_STATES := PIPE_FILL_0;
|
signal CPU_Next_State : CPU_STATES := PIPE_FILL_0;
|
signal CPU_State : CPU_STATES := PIPE_FILL_0;
|
signal CPU_State : CPU_STATES := PIPE_FILL_0;
|
|
|
signal Cache_Ctrl : CACHE_MODES := CACHE_IDLE;
|
signal Cache_Ctrl : CACHE_MODES := CACHE_IDLE;
|
|
|
Line 250... |
Line 256... |
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';
|
|
|
begin
|
begin
|
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Address bus selection/generation logic
|
-- Address bus selection/generation logic
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Address_Logic: process(CPU_State, Regfile, SubOp, SubOp_p1, Operand1, Operand2,
|
Address_Logic: process(CPU_State, Regfile, SubOp, SubOp_p1, Operand1,
|
Program_Ctr, Stack_Ptr, ISR_Addr )
|
Operand2, Program_Ctr, Stack_Ptr, ISR_Addr )
|
variable Reg, Reg_1 : integer range 0 to 7 := 0;
|
variable Reg, Reg_1 : integer range 0 to 7 := 0;
|
variable Offset_SX : ADDRESS_TYPE;
|
variable Offset_SX : ADDRESS_TYPE;
|
begin
|
begin
|
|
|
if( Enable_Auto_Increment )then
|
if( Enable_Auto_Increment )then
|
Line 307... |
Line 314... |
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;
|
--
|
--
|
PC_Ctrl.Oper <= PC_IDLE;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= x"03";
|
PC_Ctrl.Offset <= PC_IDLE;
|
PC_Ctrl.Addr <= x"0000";
|
|
--
|
--
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Reg <= ACCUM;
|
ALU_Ctrl.Reg <= ACCUM;
|
ALU_Ctrl.Data <= x"00";
|
|
--
|
--
|
SP_Ctrl.Oper <= SP_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
--
|
--
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Reg <= ACCUM;
|
DP_Ctrl.Reg <= ACCUM;
|
Line 333... |
Line 338... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Initial Instruction fetch & decode
|
-- Initial Instruction fetch & decode
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when PIPE_FILL_0 =>
|
when PIPE_FILL_0 =>
|
CPU_Next_State <= PIPE_FILL_1;
|
CPU_Next_State <= PIPE_FILL_1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when PIPE_FILL_1 =>
|
when PIPE_FILL_1 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= PIPE_FILL_2;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when PIPE_FILL_2 =>
|
when PIPE_FILL_2 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when INSTR_DECODE =>
|
when INSTR_DECODE =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
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;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV1;
|
PC_Ctrl.Offset <= PC_REV1;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Reg <= SubOp;
|
DP_Ctrl.Reg <= SubOp;
|
|
|
when OP_POP =>
|
when OP_POP =>
|
CPU_Next_State <= POP_C1;
|
CPU_Next_State <= POP_C1;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
SP_Ctrl.Oper <= SP_POP;
|
SP_Ctrl.Oper <= SP_POP;
|
|
|
when OP_BR0 | OP_BR1 =>
|
when OP_BR0 | OP_BR1 =>
|
CPU_Next_State <= BRN_C1;
|
CPU_Next_State <= BRN_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
|
|
when OP_DBNZ =>
|
when OP_DBNZ =>
|
CPU_Next_State <= DBNZ_C1;
|
CPU_Next_State <= DBNZ_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
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.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
-- Make sure the requested interrupt is actually enabled first
|
-- Make sure the requested interrupt is actually enabled first
|
if( Int_Mask(Reg) = '1' )then
|
if( Int_Mask(Reg) = '1' )then
|
CPU_Next_State <= WAIT_FOR_INT;
|
CPU_Next_State <= WAIT_FOR_INT;
|
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.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( not Allow_Stack_Address_Move )then
|
if( not Allow_Stack_Address_Move )then
|
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
|
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
|
ALU_Ctrl.Oper <= ALU_TSX;
|
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;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
SP_Ctrl.Oper <= SP_POP;
|
SP_Ctrl.Oper <= SP_POP;
|
|
|
when SOP_BRK =>
|
when SOP_BRK =>
|
CPU_Next_State <= BRK_C1;
|
CPU_Next_State <= BRK_C1;
|
PC_Ctrl.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
-- If Break implements Wait for Interrupt, replace the normal
|
-- If Break implements Wait for Interrupt, replace the normal
|
-- flow with a modified version of the INT instruction
|
-- 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;
|
CPU_Next_State <= WAIT_FOR_INT;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
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;
|
|
|
when SOP_SMSK =>
|
when SOP_SMSK =>
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
INT_Ctrl.Mask_Set <= '1';
|
INT_Ctrl.Mask_Set <= '1';
|
|
|
when SOP_GMSK =>
|
when SOP_GMSK =>
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper<= ALU_LDI;
|
ALU_Ctrl.Oper <= ALU_GMSK;
|
ALU_Ctrl.Reg <= ACCUM;
|
|
ALU_Ctrl.Data<= Int_Mask;
|
|
|
|
when SOP_JSR =>
|
when SOP_JSR =>
|
CPU_Next_State <= JSR_C1;
|
CPU_Next_State <= JSR_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
Line 442... |
Line 446... |
-- to the ALU writing the result to registers. As a result, this
|
-- to the ALU writing the result to registers. As a result, this
|
-- state needs to idle the ALU initially, and back the PC up by 1
|
-- state needs to idle the ALU initially, and back the PC up by 1
|
-- We can get away with only 1 extra clock by pre-fetching the
|
-- We can get away with only 1 extra clock by pre-fetching the
|
-- next instruction, though.
|
-- next instruction, though.
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV1;
|
PC_Ctrl.Offset <= PC_REV1;
|
-- Note that both the multiply process AND ALU process need the
|
-- Note that both the multiply process AND ALU process need the
|
-- source register for Rn (R1:R0 = R0 * Rn). Assert ALU_Ctrl.reg
|
-- source register for Rn (R1:R0 = R0 * Rn). Assert ALU_Ctrl.reg
|
-- now, but hold off on the ALU command until the next state.
|
-- now, but hold off on the ALU command until the next state.
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Oper <= ALU_IDLE;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
when OP_UPP =>
|
when OP_UPP =>
|
CPU_Next_State <= UPP_C1;
|
CPU_Next_State <= UPP_C1;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV1;
|
PC_Ctrl.Offset <= PC_REV1;
|
ALU_Ctrl.Oper <= Opcode;
|
ALU_Ctrl.Oper <= Opcode;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
when OP_LDA =>
|
when OP_LDA =>
|
CPU_Next_State <= LDA_C1;
|
CPU_Next_State <= LDA_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
|
|
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.Oper <= PC_INCR;
|
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.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
|
|
when OP_LDX =>
|
when OP_LDX =>
|
CPU_Next_State <= LDX_C1;
|
CPU_Next_State <= LDX_C1;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
|
|
when OP_STA =>
|
when OP_STA =>
|
CPU_Next_State <= STA_C1;
|
CPU_Next_State <= STA_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
|
|
when OP_STO =>
|
when OP_STO =>
|
CPU_Next_State <= STO_C1;
|
CPU_Next_State <= STO_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Reg <= ACCUM;
|
DP_Ctrl.Reg <= ACCUM;
|
|
|
when OP_STX =>
|
when OP_STX =>
|
CPU_Next_State <= STX_C1;
|
CPU_Next_State <= STX_C1;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_REV2;
|
PC_Ctrl.Offset <= PC_REV2;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Reg <= ACCUM;
|
DP_Ctrl.Reg <= ACCUM;
|
|
|
when others =>
|
when others =>
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= Opcode;
|
ALU_Ctrl.Oper <= Opcode;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
|
|
end case;
|
end case;
|
|
|
Line 507... |
Line 512... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
when BRN_C1 =>
|
when BRN_C1 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
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 <= PIPE_FILL_0;
|
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 <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Flags(FL_ZERO) = '0' )then
|
if( Flags(PSR_Z) = '0' )then
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= PIPE_FILL_0;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
PC_Ctrl.Offset <= Operand1;
|
PC_Ctrl.Offset <= Operand1;
|
end if;
|
end if;
|
|
|
Line 531... |
Line 536... |
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
|
|
when JMP_C2 =>
|
when JMP_C2 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= PIPE_FILL_0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Addr <= Operand2 & Operand1;
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Data Storage - Load from memory (LDA, LDI, LDO, LDX)
|
-- Data Storage - Load from memory (LDA, LDI, LDO, LDX)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
Line 546... |
Line 550... |
when LDA_C2 =>
|
when LDA_C2 =>
|
CPU_Next_State <= LDA_C3;
|
CPU_Next_State <= LDA_C3;
|
|
|
when LDA_C3 =>
|
when LDA_C3 =>
|
CPU_Next_State <= LDA_C4;
|
CPU_Next_State <= LDA_C4;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDA_C4 =>
|
when LDA_C4 =>
|
CPU_Next_State <= LDI_C1;
|
CPU_Next_State <= LDI_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDI_C1 =>
|
when LDI_C1 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Data <= Operand1;
|
|
|
|
when LDO_C1 =>
|
when LDO_C1 =>
|
CPU_Next_State <= LDX_C2;
|
CPU_Next_State <= LDX_C2;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
if( Enable_Auto_Increment and SubOp(0) = '1' )then
|
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;
|
|
|
Line 578... |
Line 581... |
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
|
end if;
|
end if;
|
|
|
when LDX_C2 =>
|
when LDX_C2 =>
|
CPU_Next_State <= LDX_C3;
|
CPU_Next_State <= LDX_C3;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDX_C3 =>
|
when LDX_C3 =>
|
CPU_Next_State <= LDX_C4;
|
CPU_Next_State <= LDX_C4;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when LDX_C4 =>
|
when LDX_C4 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Oper <= ALU_LDI;
|
ALU_Ctrl.Reg <= ACCUM;
|
ALU_Ctrl.Reg <= ACCUM;
|
ALU_Ctrl.Data <= Operand1;
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Data Storage - Store to memory (STA, STO, STX)
|
-- Data Storage - Store to memory (STA, STO, STX)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when STA_C1 =>
|
when STA_C1 =>
|
Line 604... |
Line 606... |
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Src <= DATA_WR_REG;
|
DP_Ctrl.Reg <= SubOp;
|
DP_Ctrl.Reg <= SubOp;
|
|
|
when STA_C2 =>
|
when STA_C2 =>
|
CPU_Next_State <= STA_C3;
|
CPU_Next_State <= STA_C3;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when STA_C3 =>
|
when STA_C3 =>
|
CPU_Next_State <= PIPE_FILL_2;
|
CPU_Next_State <= PIPE_FILL_2;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when STO_C1 =>
|
when STO_C1 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= PIPE_FILL_0;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
Cache_Ctrl <= CACHE_PREFETCH;
|
PC_Ctrl.Oper <= PC_INCR;
|
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 <= PIPE_FILL_1;
|
PC_Ctrl.Oper <= PC_INCR;
|
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 <= PIPE_FILL_1;
|
PC_Ctrl.Oper <= PC_INCR;
|
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 <= PIPE_FILL_2;
|
PC_Ctrl.Oper <= PC_INCR;
|
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';
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Multi-Cycle Math Operations (UPP, MUL)
|
-- Multi-Cycle Math Operations (UPP, MUL)
|
Line 652... |
Line 654... |
-- 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 <= PIPE_FILL_2;
|
PC_Ctrl.Oper <= PC_INCR;
|
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 <= PIPE_FILL_2;
|
PC_Ctrl.Oper <= PC_INCR;
|
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)
|
Line 673... |
Line 675... |
when POP_C1 =>
|
when POP_C1 =>
|
CPU_Next_State <= POP_C2;
|
CPU_Next_State <= POP_C2;
|
|
|
when POP_C2 =>
|
when POP_C2 =>
|
CPU_Next_State <= POP_C3;
|
CPU_Next_State <= POP_C3;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when POP_C3 =>
|
when POP_C3 =>
|
CPU_Next_State <= POP_C4;
|
CPU_Next_State <= POP_C4;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
|
|
when POP_C4 =>
|
when POP_C4 =>
|
CPU_Next_State <= INSTR_DECODE;
|
CPU_Next_State <= INSTR_DECODE;
|
Cache_Ctrl <= CACHE_INSTR;
|
Cache_Ctrl <= CACHE_INSTR;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_POP;
|
ALU_Ctrl.Oper <= ALU_POP;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Reg <= SubOp;
|
ALU_Ctrl.Data <= Operand1;
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Subroutines & Interrupts (RTS, JSR)
|
-- Subroutines & Interrupts (RTS, JSR)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when WAIT_FOR_INT => -- For soft interrupts only, halt the Program_Ctr
|
when WAIT_FOR_INT => -- For soft interrupts only, halt the Program_Ctr
|
Line 707... |
Line 708... |
|
|
when ISR_C3 =>
|
when ISR_C3 =>
|
CPU_Next_State <= JSR_C1;
|
CPU_Next_State <= JSR_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
ALU_Ctrl.Oper <= ALU_STP;
|
ALU_Ctrl.Oper <= ALU_STP;
|
ALU_Ctrl.Reg <= INT_FLAG;
|
ALU_Ctrl.Reg <= conv_std_logic_vector(PSR_I,3);
|
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_MSB;
|
DP_Ctrl.Reg <= PC_MSB;
|
Ack_D <= '1';
|
Ack_D <= '1';
|
|
|
Line 723... |
Line 724... |
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 <= PIPE_FILL_0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Addr <= Operand2 & Operand1;
|
|
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;
|
SP_Ctrl.Oper <= SP_POP;
|
SP_Ctrl.Oper <= SP_POP;
|
Line 748... |
Line 748... |
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
|
|
when RTS_C5 =>
|
when RTS_C5 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= PIPE_FILL_0;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Oper <= PC_LOAD;
|
PC_Ctrl.Addr <= Operand2 & Operand1;
|
-- 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.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 <= PIPE_FILL_1;
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_NEXT;
|
ALU_Ctrl.Oper <= ALU_RFLG;
|
ALU_Ctrl.Oper <= ALU_RFLG;
|
ALU_Ctrl.Data <= Operand1;
|
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Debugging (BRK) Performs a 5-clock NOP
|
-- Debugging (BRK) Performs a 5-clock NOP
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when BRK_C1 =>
|
when BRK_C1 =>
|
Line 777... |
Line 778... |
if( Int_Req = '1' )then
|
if( Int_Req = '1' )then
|
if( CPU_State = INSTR_DECODE or CPU_State = WAIT_FOR_INT )then
|
if( CPU_State = INSTR_DECODE or CPU_State = WAIT_FOR_INT )then
|
CPU_Next_State <= ISR_C1;
|
CPU_Next_State <= ISR_C1;
|
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 compensate for the pipeline registers
|
PC_Ctrl.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= PC_REV3;
|
PC_Ctrl.Offset <= x"FF";
|
|
-- 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;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
Line 880... |
Line 880... |
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
Offset_SX(15 downto 8) := (others => PC_Ctrl.Offset(7));
|
Offset_SX(15 downto 8) := (others => PC_Ctrl.Offset(7));
|
Offset_SX(7 downto 0) := PC_Ctrl.Offset;
|
Offset_SX(7 downto 0) := PC_Ctrl.Offset;
|
|
|
case PC_Ctrl.Oper is
|
case PC_Ctrl.Oper is
|
when PC_IDLE =>
|
|
null;
|
|
|
|
when PC_REV1 =>
|
|
Program_Ctr <= Program_Ctr - 1;
|
|
|
|
when PC_REV2 =>
|
|
Program_Ctr <= Program_Ctr - 2;
|
|
|
|
when PC_INCR =>
|
when PC_INCR =>
|
Program_Ctr <= Program_Ctr + Offset_SX - 2;
|
Program_Ctr <= Program_Ctr + Offset_SX - 2;
|
|
|
when PC_LOAD =>
|
when PC_LOAD =>
|
Program_Ctr <= PC_Ctrl.Addr;
|
Program_Ctr <= Operand2 & Operand1;
|
|
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
Line 975... |
Line 966... |
|
|
if( Wait_for_FSM = '0' )then
|
if( Wait_for_FSM = '0' )then
|
if( Pending(0) = '1' )then
|
if( Pending(0) = '1' )then
|
ISR_Addr <= INT_VECTOR_0;
|
ISR_Addr <= INT_VECTOR_0;
|
Pending(0) <= '0';
|
Pending(0) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(1) = '1' )then
|
elsif( Pending(1) = '1' )then
|
ISR_Addr <= INT_VECTOR_1;
|
ISR_Addr <= INT_VECTOR_1;
|
Pending(1) <= '0';
|
Pending(1) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(2) = '1' )then
|
elsif( Pending(2) = '1' )then
|
ISR_Addr <= INT_VECTOR_2;
|
ISR_Addr <= INT_VECTOR_2;
|
Pending(2) <= '0';
|
Pending(2) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(3) = '1' )then
|
elsif( Pending(3) = '1' )then
|
ISR_Addr <= INT_VECTOR_3;
|
ISR_Addr <= INT_VECTOR_3;
|
Pending(3) <= '0';
|
Pending(3) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(4) = '1' )then
|
elsif( Pending(4) = '1' )then
|
ISR_Addr <= INT_VECTOR_4;
|
ISR_Addr <= INT_VECTOR_4;
|
Pending(4) <= '0';
|
Pending(4) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(5) = '1' )then
|
elsif( Pending(5) = '1' )then
|
ISR_Addr <= INT_VECTOR_5;
|
ISR_Addr <= INT_VECTOR_5;
|
Pending(5) <= '0';
|
Pending(5) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(6) = '1' )then
|
elsif( Pending(6) = '1' )then
|
ISR_Addr <= INT_VECTOR_6;
|
ISR_Addr <= INT_VECTOR_6;
|
Pending(6) <= '0';
|
Pending(6) <= '0';
|
Wait_for_FSM <= '1';
|
|
elsif( Pending(7) = '1' )then
|
elsif( Pending(7) = '1' )then
|
ISR_Addr <= INT_VECTOR_7;
|
ISR_Addr <= INT_VECTOR_7;
|
Pending(7) <= '0';
|
Pending(7) <= '0';
|
Wait_for_FSM <= '1';
|
|
end if;
|
end if;
|
|
Wait_for_FSM <= or_reduce(Pending);
|
end if;
|
end if;
|
|
|
-- Reset the Wait_for_FSM flag on Int_Ack
|
-- Reset the Wait_for_FSM flag on Int_Ack
|
Ack_Q <= Ack_D;
|
Ack_Q <= Ack_D;
|
Ack_Q1 <= Ack_Q;
|
Ack_Q1 <= Ack_Q;
|
Line 1034... |
Line 1018... |
|
|
case ALU_Ctrl.Oper is
|
case ALU_Ctrl.Oper is
|
when ALU_INC => -- Rn = Rn + 1 : Flags N,C,Z
|
when ALU_INC => -- Rn = Rn + 1 : Flags N,C,Z
|
Sum := ("0" & x"01") +
|
Sum := ("0" & x"01") +
|
("0" & Regfile(Index));
|
("0" & Regfile(Index));
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
Regfile(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_UPP => -- Rn = Rn + 1
|
when ALU_UPP => -- Rn = Rn + 1
|
Sum := ("0" & x"01") +
|
Sum := ("0" & x"01") +
|
("0" & Regfile(Index));
|
("0" & Regfile(Index));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Regfile(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_UPP2 => -- Rn = Rn + C
|
when ALU_UPP2 => -- Rn = Rn + C
|
Sum := ("0" & x"00") +
|
Sum := ("0" & x"00") +
|
("0" & Regfile(Index)) +
|
("0" & Regfile(Index)) +
|
Flags(FL_CARRY);
|
Flags(PSR_C);
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Regfile(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_ADC => -- R0 = R0 + Rn + C : Flags N,C,Z
|
when ALU_ADC => -- R0 = R0 + Rn + C : Flags N,C,Z
|
Sum := ("0" & Regfile(0)) +
|
Sum := ("0" & Regfile(0)) +
|
("0" & Regfile(Index)) +
|
("0" & Regfile(Index)) +
|
Flags(FL_CARRY);
|
Flags(PSR_C);
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
Regfile(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
|
|
when ALU_TX0 => -- R0 = Rn : Flags N,Z
|
when ALU_TX0 => -- R0 = Rn : Flags N,Z
|
Temp := "0" & Regfile(Index);
|
Temp := "0" & Regfile(Index);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_OR => -- R0 = R0 | Rn : Flags N,Z
|
when ALU_OR => -- R0 = R0 | Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) or Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) or Regfile(Index);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_AND => -- R0 = R0 & Rn : Flags N,Z
|
when ALU_AND => -- R0 = R0 & Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) and Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) and Regfile(Index);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_XOR => -- R0 = R0 ^ Rn : Flags N,Z
|
when ALU_XOR => -- R0 = R0 ^ Rn : Flags N,Z
|
Temp(7 downto 0) := Regfile(0) xor Regfile(Index);
|
Temp(7 downto 0) := Regfile(0) xor Regfile(Index);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(0) <= Temp(7 downto 0);
|
Regfile(0) <= Temp(7 downto 0);
|
|
|
when ALU_ROL => -- Rn = Rn<<1,C : Flags N,C,Z
|
when ALU_ROL => -- Rn = Rn<<1,C : Flags N,C,Z
|
Temp := Regfile(Index) & Flags(FL_CARRY);
|
Temp := Regfile(Index) & Flags(PSR_C);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_CARRY) <= Temp(8);
|
Flags(PSR_C) <= Temp(8);
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_ROR => -- Rn = C,Rn>>1 : Flags N,C,Z
|
when ALU_ROR => -- Rn = C,Rn>>1 : Flags N,C,Z
|
Temp := Regfile(Index)(0) & Flags(FL_CARRY) &
|
Temp := Regfile(Index)(0) & Flags(PSR_C) &
|
Regfile(Index)(7 downto 1);
|
Regfile(Index)(7 downto 1);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_CARRY) <= Temp(8);
|
Flags(PSR_C) <= Temp(8);
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_DEC => -- Rn = Rn - 1 : Flags N,C,Z
|
when ALU_DEC => -- Rn = Rn - 1 : Flags N,C,Z
|
Sum := ("0" & Regfile(Index)) +
|
Sum := ("0" & Regfile(Index)) +
|
("0" & x"FF");
|
("0" & x"FF");
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
Regfile(Index) <= Sum(7 downto 0);
|
Regfile(Index) <= Sum(7 downto 0);
|
|
|
when ALU_SBC => -- Rn = R0 - Rn - C : Flags N,C,Z
|
when ALU_SBC => -- Rn = R0 - Rn - C : Flags N,C,Z
|
Sum := ("0" & Regfile(0)) +
|
Sum := ("0" & Regfile(0)) +
|
("1" & (not Regfile(Index))) +
|
("1" & (not Regfile(Index))) +
|
Flags(FL_CARRY);
|
Flags(PSR_C);
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
Regfile(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
|
|
when ALU_ADD => -- R0 = R0 + Rn : Flags N,C,Z
|
when ALU_ADD => -- R0 = R0 + Rn : Flags N,C,Z
|
Sum := ("0" & Regfile(0)) +
|
Sum := ("0" & Regfile(0)) +
|
("0" & Regfile(Index));
|
("0" & Regfile(Index));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Regfile(0) <= Sum(7 downto 0);
|
Regfile(0) <= Sum(7 downto 0);
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
|
|
when ALU_STP => -- Sets bit(n) in the Flags register
|
when ALU_STP => -- Sets bit(n) in the Flags register
|
Flags(Index) <= '1';
|
Flags(Index) <= '1';
|
|
|
when ALU_BTT => -- Z = !R0(N), N = R0(7)
|
when ALU_BTT => -- Z = !R0(N), N = R0(7)
|
Flags(FL_ZERO) <= not Regfile(0)(Index);
|
Flags(PSR_Z) <= not Regfile(0)(Index);
|
Flags(FL_NEG) <= Regfile(0)(7);
|
Flags(PSR_N) <= Regfile(0)(7);
|
|
|
when ALU_CLP => -- Clears bit(n) in the Flags register
|
when ALU_CLP => -- Clears bit(n) in the Flags register
|
Flags(Index) <= '0';
|
Flags(Index) <= '0';
|
|
|
when ALU_T0X => -- Rn = R0 : Flags N,Z
|
when ALU_T0X => -- Rn = R0 : Flags N,Z
|
Temp := "0" & Regfile(0);
|
Temp := "0" & Regfile(0);
|
Flags(FL_ZERO) <= nor_reduce(Temp(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Temp(7 downto 0));
|
Flags(FL_NEG) <= Temp(7);
|
Flags(PSR_N) <= Temp(7);
|
Regfile(Index) <= Temp(7 downto 0);
|
Regfile(Index) <= Temp(7 downto 0);
|
|
|
when ALU_CMP => -- Sets Flags on R0 - Rn : Flags N,C,Z
|
when ALU_CMP => -- Sets Flags on R0 - Rn : Flags N,C,Z
|
Sum := ("0" & Regfile(0)) +
|
Sum := ("0" & Regfile(0)) +
|
("1" & (not Regfile(Index))) +
|
("1" & (not Regfile(Index))) +
|
'1';
|
'1';
|
Flags(FL_ZERO) <= nor_reduce(Sum(7 downto 0));
|
Flags(PSR_Z) <= nor_reduce(Sum(7 downto 0));
|
Flags(FL_CARRY) <= Sum(8);
|
Flags(PSR_C) <= Sum(8);
|
Flags(FL_NEG) <= Sum(7);
|
Flags(PSR_N) <= Sum(7);
|
|
|
when ALU_MUL => -- Stage 1 of 2 {R1:R0} = R0 * Rn : Flags Z
|
when ALU_MUL => -- Stage 1 of 2 {R1:R0} = R0 * Rn : Flags Z
|
Regfile(0) <= Mult(7 downto 0);
|
Regfile(0) <= Mult(7 downto 0);
|
Regfile(1) <= Mult(15 downto 8);
|
Regfile(1) <= Mult(15 downto 8);
|
Flags(FL_ZERO) <= nor_reduce(Mult);
|
Flags(PSR_Z) <= nor_reduce(Mult);
|
|
|
when ALU_LDI => -- Rn <= Data : Flags N,Z
|
when ALU_LDI => -- Rn <= Data : Flags N,Z
|
Flags(FL_ZERO) <= nor_reduce(ALU_Ctrl.Data);
|
Flags(PSR_Z) <= nor_reduce(Operand1);
|
Flags(FL_NEG) <= ALU_Ctrl.Data(7);
|
Flags(PSR_N) <= Operand1(7);
|
Regfile(Index) <= ALU_Ctrl.Data;
|
Regfile(Index) <= Operand1;
|
|
|
when ALU_POP => -- Rn <= Data
|
when ALU_POP => -- Rn <= Data
|
Regfile(Index) <= ALU_Ctrl.Data;
|
Regfile(Index) <= Operand1;
|
|
|
when ALU_RFLG =>
|
when ALU_RFLG =>
|
Flags <= ALU_Ctrl.Data;
|
Flags <= Operand1;
|
|
|
when ALU_TSX =>
|
when ALU_RSP =>
|
Regfile(0) <= Stack_Ptr(7 downto 0);
|
Regfile(0) <= Stack_Ptr(7 downto 0);
|
Regfile(1) <= Stack_Ptr(15 downto 8);
|
Regfile(1) <= Stack_Ptr(15 downto 8);
|
|
|
|
when ALU_GMSK =>
|
|
Flags(PSR_Z) <= nor_reduce(Int_Mask);
|
|
Regfile(0) <= Int_Mask;
|
|
|
when others =>
|
when others =>
|
null;
|
null;
|
end case;
|
end case;
|
|
|
end if;
|
end if;
|
Line 1187... |
Line 1175... |
|
|
Multiplier_proc: process( Clock )
|
Multiplier_proc: process( Clock )
|
begin
|
begin
|
if( rising_edge(Clock) )then
|
if( rising_edge(Clock) )then
|
Mult <= Regfile(0) *
|
Mult <= Regfile(0) *
|
Regfile(conv_integer(ALU_Ctrl.Reg));
|
|
end if;
|
|
end process;
|
|
|
|
end architecture;
|
|
|
|
No newline at end of file
|
No newline at end of file
|