Line 67... |
Line 67... |
-- : respectively. DBNZ decrements the specified register, and will
|
-- : respectively. DBNZ decrements the specified register, and will
|
-- : branch if the result is non-zero (Zero flag is not set). MUL
|
-- : branch if the result is non-zero (Zero flag is not set). MUL
|
-- : places the result of R0 * Rn into R1:R0, and executes in two
|
-- : places the result of R0 * Rn into R1:R0, and executes in two
|
-- : cycles. (R1:R0 = R0 * Rn)
|
-- : cycles. (R1:R0 = R0 * Rn)
|
-- :
|
-- :
|
|
-- : BRK_Implements_WAI modifies the BRK instruction such that it
|
|
-- : triggers the wait for interrupt state, but without triggering
|
|
-- : a soft interrupt in lieu of its normal behavior, which is to
|
|
-- : insert several dead clock cycles - essentially a long NOP
|
-- Revision History
|
-- Revision History
|
-- Author Date Change
|
-- Author Date Change
|
------------------ -------- ---------------------------------------------------
|
------------------ -------- ---------------------------------------------------
|
-- Seth Henry 07/19/06 Design Start
|
-- Seth Henry 07/19/06 Design Start
|
-- Seth Henry 01/18/11 Fixed BTT instruction to match V8
|
-- Seth Henry 01/18/11 Fixed BTT instruction to match V8
|
Line 81... |
Line 85... |
-- 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
|
|
-- the bus entirely (Rd_Enable is low)
|
|
|
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 201... |
Line 207... |
type SP_CTRL_TYPE is record
|
type SP_CTRL_TYPE is record
|
Oper : SP_MODES;
|
Oper : SP_MODES;
|
Addr : ADDRESS_TYPE;
|
Addr : ADDRESS_TYPE;
|
end record;
|
end record;
|
|
|
type DP_MODES is ( DATA_IDLE, DATA_REG, DATA_FLAG, DATA_PC );
|
type DP_MODES is ( DATA_BUS_IDLE, DATA_RD_MEM,
|
|
DATA_WR_REG, DATA_WR_FLAG, DATA_WR_PC );
|
|
|
type DATA_CTRL_TYPE is record
|
type DATA_CTRL_TYPE is record
|
Src : DP_MODES;
|
Src : DP_MODES;
|
Reg : SUBOP_TYPE;
|
Reg : SUBOP_TYPE;
|
end record;
|
end record;
|
Line 352... |
Line 359... |
--
|
--
|
SP_Ctrl.Oper <= SP_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
--
|
--
|
Address <= Program_Ctr;
|
Address <= Program_Ctr;
|
--
|
--
|
DP_Ctrl.Src <= DATA_IDLE;
|
DP_Ctrl.Src <= DATA_RD_MEM;
|
DP_Ctrl.Reg <= ACCUM;
|
DP_Ctrl.Reg <= ACCUM;
|
--
|
--
|
INT_Ctrl.Mask_Set <= '0';
|
INT_Ctrl.Mask_Set <= '0';
|
INT_Ctrl.Soft_Ints <= x"00";
|
INT_Ctrl.Soft_Ints <= x"00";
|
INT_Ctrl.Incr_ISR <= '0';
|
INT_Ctrl.Incr_ISR <= '0';
|
Line 394... |
Line 401... |
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.Oper <= PC_REV1;
|
DP_Ctrl.Src <= DATA_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;
|
Line 417... |
Line 424... |
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.Oper <= PC_INCR;
|
|
-- 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;
|
|
|
Line 461... |
Line 469... |
ALU_Ctrl.Data<= Int_Mask;
|
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_PC;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Reg <= ACCUM+1;
|
DP_Ctrl.Reg <= ACCUM+1;
|
|
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
|
|
Line 529... |
Line 537... |
|
|
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.Oper <= PC_REV2;
|
DP_Ctrl.Src <= DATA_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.Oper <= PC_REV2;
|
DP_Ctrl.Src <= DATA_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.Oper <= PC_INCR;
|
ALU_Ctrl.Oper <= Opcode;
|
ALU_Ctrl.Oper <= Opcode;
|
Line 646... |
Line 654... |
-- Data Storage - Store to memory (STA, STO, STX)
|
-- Data Storage - Store to memory (STA, STO, STX)
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
when STA_C1 =>
|
when STA_C1 =>
|
CPU_Next_State <= STA_C2;
|
CPU_Next_State <= STA_C2;
|
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
DP_Ctrl.Src <= DATA_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;
|
Address <= Operand2 & Operand1;
|
Address <= Operand2 & Operand1;
|
Line 762... |
Line 770... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- 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
|
|
DP_Ctrl.Src <= DATA_BUS_IDLE;
|
CPU_Next_State <= WAIT_FOR_INT;
|
CPU_Next_State <= WAIT_FOR_INT;
|
|
|
when ISR_C1 =>
|
when ISR_C1 =>
|
CPU_Next_State <= ISR_C2;
|
CPU_Next_State <= ISR_C2;
|
Address <= ISR_Addr;
|
Address <= ISR_Addr;
|
INT_Ctrl.Incr_ISR <= '1';
|
INT_Ctrl.Incr_ISR <= '1';
|
|
|
when ISR_C2 =>
|
when ISR_C2 =>
|
CPU_Next_State <= ISR_C3;
|
CPU_Next_State <= ISR_C3;
|
Address <= ISR_Addr;
|
Address <= ISR_Addr;
|
DP_Ctrl.Src <= DATA_FLAG;
|
DP_Ctrl.Src <= DATA_WR_FLAG;
|
|
|
when ISR_C3 =>
|
when ISR_C3 =>
|
CPU_Next_State <= JSR_C1;
|
CPU_Next_State <= JSR_C1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Cache_Ctrl <= CACHE_OPER1;
|
Address <= Stack_Ptr;
|
Address <= Stack_Ptr;
|
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
DP_Ctrl.Src <= DATA_PC;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Reg <= ACCUM+1;
|
DP_Ctrl.Reg <= ACCUM+1;
|
ALU_Ctrl.Oper <= ALU_STP;
|
ALU_Ctrl.Oper <= ALU_STP;
|
ALU_Ctrl.Reg <= INT_FLAG;
|
ALU_Ctrl.Reg <= INT_FLAG;
|
Ack_D <= '1';
|
Ack_D <= '1';
|
|
|
when JSR_C1 =>
|
when JSR_C1 =>
|
CPU_Next_State <= JSR_C2;
|
CPU_Next_State <= JSR_C2;
|
Cache_Ctrl <= CACHE_OPER2;
|
Cache_Ctrl <= CACHE_OPER2;
|
Address <= Stack_Ptr;
|
Address <= Stack_Ptr;
|
SP_Ctrl.Oper <= SP_PUSH;
|
SP_Ctrl.Oper <= SP_PUSH;
|
DP_Ctrl.Src <= DATA_PC;
|
DP_Ctrl.Src <= DATA_WR_PC;
|
DP_Ctrl.Reg <= ACCUM;
|
DP_Ctrl.Reg <= ACCUM;
|
|
|
when JSR_C2 =>
|
when JSR_C2 =>
|
CPU_Next_State <= PIPE_FILL_0;
|
CPU_Next_State <= PIPE_FILL_0;
|
Address <= Stack_Ptr;
|
Address <= Stack_Ptr;
|
Line 859... |
Line 868... |
-- 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;
|
Cache_Ctrl <= CACHE_IDLE;
|
Cache_Ctrl <= CACHE_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
SP_Ctrl.Oper <= SP_IDLE;
|
DP_Ctrl.Src <= DATA_IDLE; -- JSH 7/20
|
DP_Ctrl.Src <= DATA_RD_MEM; -- JSH 7/20
|
INT_Ctrl.Soft_Ints <= (others => '0'); -- JSH 7/22
|
INT_Ctrl.Soft_Ints <= (others => '0'); -- JSH 7/22
|
-- 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.Oper <= PC_INCR;
|
PC_Ctrl.Offset <= x"FF";
|
PC_Ctrl.Offset <= x"FF";
|
CPU_Next_State <= ISR_C1;
|
CPU_Next_State <= ISR_C1;
|
Line 930... |
Line 939... |
end loop;
|
end loop;
|
Flags <= x"00";
|
Flags <= x"00";
|
|
|
elsif( rising_edge(Clock) )then
|
elsif( rising_edge(Clock) )then
|
Wr_Enable <= '0';
|
Wr_Enable <= '0';
|
|
Wr_Data <= x"00";
|
Rd_Enable <= '0';
|
Rd_Enable <= '0';
|
|
|
if( Halt = '0' )then
|
if( Halt = '0' )then
|
Rd_Enable <= '1';
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Instruction/Operand caching for pipelined memory access
|
-- Instruction/Operand caching for pipelined memory access
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
CPU_State <= CPU_Next_State;
|
CPU_State <= CPU_Next_State;
|
case Cache_Ctrl is
|
case Cache_Ctrl is
|
Line 994... |
Line 1003... |
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- (Write) Data Path
|
-- (Write) Data Path
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
case DP_Ctrl.Src is
|
case DP_Ctrl.Src is
|
when DATA_IDLE =>
|
when DATA_BUS_IDLE =>
|
null;
|
null;
|
|
|
when DATA_REG =>
|
when DATA_RD_MEM =>
|
|
Rd_Enable <= '1';
|
|
|
|
when DATA_WR_REG =>
|
Wr_Enable <= '1';
|
Wr_Enable <= '1';
|
Rd_Enable <= '0';
|
|
Wr_Data <= Regfile(conv_integer(DP_Ctrl.Reg));
|
Wr_Data <= Regfile(conv_integer(DP_Ctrl.Reg));
|
|
|
when DATA_FLAG =>
|
when DATA_WR_FLAG =>
|
Wr_Enable <= '1';
|
Wr_Enable <= '1';
|
Rd_Enable <= '0';
|
|
Wr_Data <= Flags;
|
Wr_Data <= Flags;
|
|
|
when DATA_PC =>
|
when DATA_WR_PC =>
|
Wr_Enable <= '1';
|
Wr_Enable <= '1';
|
Rd_Enable <= '0';
|
|
Wr_Data <= Program_Ctr(15 downto 8);
|
Wr_Data <= Program_Ctr(15 downto 8);
|
if( DP_Ctrl.Reg = ACCUM )then
|
if( DP_Ctrl.Reg = ACCUM )then
|
Wr_Data <= Program_Ctr(7 downto 0);
|
Wr_Data <= Program_Ctr(7 downto 0);
|
end if;
|
end if;
|
|
|