URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/open8_urisc/trunk/VHDL
- from Rev 186 to Rev 187
- ↔ Reverse comparison
Rev 186 → Rev 187
/Open8_pkg.vhd
76,6 → 76,7
port( |
Clock : in std_logic; |
Reset : in std_logic; |
CPU_Halt : in std_logic; |
Interrupts : in INTERRUPT_BUNDLE; |
Address : out ADDRESS_TYPE; |
Rd_Data : in DATA_TYPE; |
143,7 → 144,7
|
type CPU_STATES is ( |
-- Instruction fetch & Decode |
PIPE_FILL_0, PIPE_FILL_1, PIPE_FILL_2, INSTR_DECODE, |
IPF_C0, IPF_C1, IPF_C2, IDC_C0, |
-- Branching |
BRN_C1, DBNZ_C1, JMP_C1, JMP_C2, |
-- Loads |
156,11 → 157,10
-- Stack |
PSH_C1, POP_C1, POP_C2, POP_C3, POP_C4, |
-- Subroutines & Interrupts |
WAIT_FOR_INT, |
WAI_Cx, WAH_Cx, BRK_C1, |
ISR_C1, ISR_C2, ISR_C3, JSR_C1, JSR_C2, |
RTS_C1, RTS_C2, RTS_C3, RTS_C4, RTS_C5, RTI_C6, |
-- Debugging |
BRK_C1 ); |
RTS_C1, RTS_C2, RTS_C3, RTS_C4, RTS_C5, RTI_C6 |
); |
|
type CACHE_MODES is (CACHE_IDLE, CACHE_INSTR, CACHE_OPER1, CACHE_OPER2, |
CACHE_PREFETCH ); |
/o8_cpu.vhd
152,7 → 152,7
-- Seth Henry 09/20/11 Added BRK_Implements_WAI option, allowing the |
-- processor to wait for an interrupt instead of the |
-- 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) |
-- Seth Henry 02/03/12 Replaced complex interrupt controller with simpler, |
-- faster logic that simply does priority encoding. |
176,6 → 176,13
-- for GMSK. This allowed the .data field to be |
-- removed and Operand1 used in its place, which |
-- 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; |
use ieee.std_logic_1164.all; |
201,7 → 208,8
port( |
Clock : 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; |
Rd_Data : in DATA_TYPE; |
221,9 → 229,11
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 := PIPE_FILL_0; |
signal CPU_State : CPU_STATES := PIPE_FILL_0; |
signal CPU_Next_State : CPU_STATES := IPF_C0; |
signal CPU_State : CPU_STATES := IPF_C0; |
|
signal CPU_Halt_Req : std_logic; |
|
signal Cache_Ctrl : CACHE_MODES := CACHE_IDLE; |
|
signal Opcode : OPCODE_TYPE := (others => '0'); |
309,7 → 319,7
-- 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 ) |
variable Reg : integer range 0 to 7 := 0; |
begin |
338,21 → 348,21
------------------------------------------------------------------------------- |
-- Initial Instruction fetch & decode |
------------------------------------------------------------------------------- |
when PIPE_FILL_0 => |
CPU_Next_State <= PIPE_FILL_1; |
when IPF_C0 => |
CPU_Next_State <= IPF_C1; |
PC_Ctrl.Offset <= PC_NEXT; |
|
when PIPE_FILL_1 => |
CPU_Next_State <= PIPE_FILL_2; |
when IPF_C1 => |
CPU_Next_State <= IPF_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
|
when PIPE_FILL_2 => |
CPU_Next_State <= INSTR_DECODE; |
when IPF_C2 => |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
|
when INSTR_DECODE => |
CPU_Next_State <= INSTR_DECODE; |
when IDC_C0 => |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
|
case Opcode is |
384,9 → 394,12
|
when OP_INT => |
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 |
CPU_Next_State <= WAIT_FOR_INT; |
CPU_Next_State <= WAI_Cx; |
INT_Ctrl.Soft_Ints(Reg) <= '1'; |
end if; |
|
395,12 → 408,22
when SOP_RSP => |
PC_Ctrl.Offset <= PC_NEXT; |
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; |
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; |
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; |
end if; |
|
409,13 → 432,17
SP_Ctrl.Oper <= SP_POP; |
|
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 |
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; |
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; |
|
when SOP_JMP => |
470,7 → 497,6
Cache_Ctrl <= CACHE_OPER1; |
PC_Ctrl.Offset <= PC_NEXT; |
|
|
when OP_LDO => |
CPU_Next_State <= LDO_C1; |
Cache_Ctrl <= CACHE_OPER1; |
508,15 → 534,34
|
if( Int_Req = '1' )then |
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; |
-- 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; |
-- 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; |
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; |
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; |
|
------------------------------------------------------------------------------- |
524,21 → 569,21
------------------------------------------------------------------------------- |
|
when BRN_C1 => |
CPU_Next_State <= INSTR_DECODE; |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Flags(Reg) = Opcode(0) )then |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
Cache_Ctrl <= CACHE_IDLE; |
PC_Ctrl.Offset <= Operand1; |
end if; |
|
when DBNZ_C1 => |
CPU_Next_State <= INSTR_DECODE; |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Flags(PSR_Z) = '0' )then |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
Cache_Ctrl <= CACHE_IDLE; |
PC_Ctrl.Offset <= Operand1; |
end if; |
548,7 → 593,7
Cache_Ctrl <= CACHE_OPER2; |
|
when JMP_C2 => |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
PC_Ctrl.Oper <= PC_LOAD; |
|
------------------------------------------------------------------------------- |
572,7 → 617,7
PC_Ctrl.Offset <= PC_NEXT; |
|
when LDI_C1 => |
CPU_Next_State <= INSTR_DECODE; |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_LDI; |
603,7 → 648,7
PC_Ctrl.Offset <= PC_NEXT; |
|
when LDX_C4 => |
CPU_Next_State <= INSTR_DECODE; |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_LDI; |
623,12 → 668,12
PC_Ctrl.Offset <= PC_NEXT; |
|
when STA_C3 => |
CPU_Next_State <= PIPE_FILL_2; |
CPU_Next_State <= IPF_C2; |
Cache_Ctrl <= CACHE_PREFETCH; |
PC_Ctrl.Offset <= PC_NEXT; |
|
when STO_C1 => |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
Cache_Ctrl <= CACHE_PREFETCH; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Enable_Auto_Increment and SubOp(0) = '1' )then |
638,13 → 683,13
end if; |
|
when STO_C2 => |
CPU_Next_State <= PIPE_FILL_1; |
CPU_Next_State <= IPF_C1; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_UPP2; |
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1'; |
|
when STX_C1 => |
CPU_Next_State <= PIPE_FILL_1; |
CPU_Next_State <= IPF_C1; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Enable_Auto_Increment and SubOp(0) = '1' )then |
CPU_Next_State <= STX_C2; |
653,7 → 698,7
end if; |
|
when STX_C2 => |
CPU_Next_State <= PIPE_FILL_2; |
CPU_Next_State <= IPF_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_UPP2; |
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1'; |
667,12 → 712,12
-- 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 |
when MUL_C1 => |
CPU_Next_State <= PIPE_FILL_2; |
CPU_Next_State <= IPF_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_MUL; |
|
when UPP_C1 => |
CPU_Next_State <= PIPE_FILL_2; |
CPU_Next_State <= IPF_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_UPP2; |
ALU_Ctrl.Reg <= SubOp_p1; |
681,7 → 726,7
-- Basic Stack Manipulation (PSH, POP, RSP) |
------------------------------------------------------------------------------- |
when PSH_C1 => |
CPU_Next_State <= PIPE_FILL_1; |
CPU_Next_State <= IPF_C1; |
SP_Ctrl.Oper <= SP_PUSH; |
|
when POP_C1 => |
697,7 → 742,7
PC_Ctrl.Offset <= PC_NEXT; |
|
when POP_C4 => |
CPU_Next_State <= INSTR_DECODE; |
CPU_Next_State <= IDC_C0; |
Cache_Ctrl <= CACHE_INSTR; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_POP; |
706,11 → 751,12
------------------------------------------------------------------------------- |
-- 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; |
if( Int_Req = '1' )then |
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; |
-- Reset all of the sub-block controls to IDLE, to avoid unintended |
-- operation due to the current instruction |
717,6 → 763,16
DP_Ctrl.Src <= DATA_RD_MEM; |
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 => |
CPU_Next_State <= ISR_C2; |
INT_Ctrl.Incr_ISR <= '1'; |
743,7 → 799,7
DP_Ctrl.Reg <= PC_LSB; |
|
when JSR_C2 => |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
PC_Ctrl.Oper <= PC_LOAD; |
SP_Ctrl.Oper <= SP_PUSH; |
|
767,7 → 823,7
Cache_Ctrl <= CACHE_OPER2; |
|
when RTS_C5 => |
CPU_Next_State <= PIPE_FILL_0; |
CPU_Next_State <= IPF_C0; |
PC_Ctrl.Oper <= PC_LOAD; |
-- if this is an RTI, then we need to clear the I bit |
if( SubOp = SOP_RTI )then |
778,16 → 834,10
end if; |
|
when RTI_C6 => |
CPU_Next_State <= PIPE_FILL_1; |
CPU_Next_State <= IPF_C1; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_RFLG; |
|
------------------------------------------------------------------------------- |
-- Debugging (BRK) Performs a 5-clock NOP |
------------------------------------------------------------------------------- |
when BRK_C1 => |
CPU_Next_State <= PIPE_FILL_0; |
|
when others => |
null; |
end case; |
806,7 → 856,7
variable Temp : std_logic_vector(8 downto 0) := "000000000"; |
begin |
if( Reset = Reset_Level )then |
CPU_State <= PIPE_FILL_0; |
CPU_State <= IPF_C0; |
Opcode <= OP_INC; |
SubOp <= ACCUM; |
SubOp_p1 <= ACCUM; |
815,6 → 865,8
Instr_Prefetch <= '0'; |
Prefetch <= x"00"; |
|
CPU_Halt_Req <= '0'; |
|
Wr_Data <= (others => '0'); |
Wr_Enable <= '0'; |
Rd_Enable <= '1'; |
842,6 → 894,9
Flags <= x"00"; |
|
elsif( rising_edge(Clock) )then |
|
CPU_Halt_Req <= CPU_Halt; |
|
Wr_Enable <= '0'; |
Wr_Data <= x"00"; |
Rd_Enable <= '0'; |