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
/
- from Rev 259 to Rev 260
- ↔ Reverse comparison
Rev 259 → Rev 260
/open8_urisc/trunk/VHDL/o8_cpu.vhd
70,6 → 70,20
-- : non-maskable interrupt at the highest priority. To remain |
-- : true to the original core, this should be set false. |
-- : |
-- : Sequential_Interrupts, when set, prevents interrupt service |
-- : routines from being interrupted by postponing an later |
-- : interrupts until the I bit is cleared (usually with an RTI, |
-- : but a CLP PSR_I will also work). This is potentially |
-- : dangerous, as it means a lower-priority ISR can "hog" the CPU |
-- : by failing to return. However, it can also prevent the |
-- : condition of an ISR interrupting itself until it causes a |
-- : memory fault. (For example, an interrupt source that whose |
-- : period is shorter than the ISR service time) Note that this |
-- : setting alters the way the pending logic works, so it affects |
-- : all interrupts, including the NMI. If this is set, special |
-- : care should be taken to make sure ISRs are short and always |
-- : execute an RTI at the end. |
-- : |
-- : RTI_Ignores_GP_Flags alters the set of flag bits restored |
-- : after an interrupt. By default, all of the flag bits are put |
-- : back to their original state. If this flag is set true, only |
88,7 → 102,7
-- : when done; |
-- : |
-- : Unsigned_Index_Offsets alters the way offsets are added to |
-- : [Rn+1:Rn] during LDO/STO instructions. The original, defeault |
-- : [Rn+1:Rn] during LDO/STO instructions. The original, default |
-- : behavior treats these offsets as signed values, allowing |
-- : instructions to offset by -128 to +127 from [Rn+1:Rn]. |
-- : Setting this generic to TRUE will switch to unsigned offsets, |
593,7 → 607,7
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 |
-- 2 and return through IPF_C0 in order to execute a 3 |
-- clock cycle delay |
CPU_Next_State <= BRK_C1; |
PC_Ctrl.Offset <= PC_REV2; |
930,8 → 944,6
-- 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 |
DP_Ctrl.Src <= DATA_RD_MEM; |
end if; |
|
1030,6 → 1042,10
begin |
if( Reset = Reset_Level )then |
CPU_State <= IPF_C0; |
|
CPU_Halt_Req <= '0'; |
Halt_Ack <= '0'; |
|
Opcode <= OP_INC; |
SubOp <= ACCUM; |
SubOp_p1 <= ACCUM; |
1038,9 → 1054,6
Instr_Prefetch <= '0'; |
Prefetch <= x"00"; |
|
CPU_Halt_Req <= '0'; |
Halt_Ack <= '0'; |
|
Open8_Bus.Wr_En <= '0'; |
Open8_Bus.Wr_Data <= OPEN8_NULLBUS; |
Open8_Bus.Rd_En <= '1'; |
1076,17 → 1089,29
|
elsif( rising_edge(Clock) )then |
|
CPU_State <= CPU_Next_State; |
|
-- Register the halt request and acknowledge lines |
|
CPU_Halt_Req <= Halt_Req; |
Halt_Ack <= CPU_Halt_Ack; |
|
Open8_Bus.Wr_En <= '0'; |
Open8_Bus.Wr_Data <= OPEN8_NULLBUS; |
Open8_Bus.Rd_En <= '0'; |
|
------------------------------------------------------------------------------- |
-- Instruction/Operand caching for pipelined memory access |
------------------------------------------------------------------------------- |
CPU_State <= CPU_Next_State; |
|
-- To avoid putting too much load on the (usually massive) wire-OR'd bus, |
-- the CPU loads Rd_Data into one of four registers - instruction, |
-- operand 1 or 2, or the instruction prefetch registers. The first is |
-- used to decode an instruction when the prefetch isn't valid, while |
-- the two operand registers are used to hold any additional argument |
-- for multi-byte instructions. Because of the memory pipelining, some |
-- longer instructions can cache the next instruction as part of their |
-- execution in a prefetch register, allowing the CPU to skip loading |
-- it again later. Unfortunate, because instructions aren't all the same |
-- length, it is not feasible to cache their operands without adding a |
-- second partial decode stage that would obviate any savings. |
|
case Cache_Ctrl is |
when CACHE_INSTR => |
Opcode <= Rd_Data(7 downto 3); |
1116,6 → 1141,14
------------------------------------------------------------------------------- |
-- Program Counter |
------------------------------------------------------------------------------- |
|
-- The program counter is a bit unusual in that it always subtracts two |
-- from itself plus the signed offset. This is because of the way the |
-- assembler works when computing branches. Thus, to "IDLE" the counter, |
-- the offset is set to 2, while "NEXT" sets the offset to 3. Depending |
-- on how an instruction interacts with memory, or is pipelined, the |
-- offset can vary from -1 to 3 |
|
Offset_SX(15 downto 8) := (others => PC_Ctrl.Offset(7)); |
Offset_SX(7 downto 0) := PC_Ctrl.Offset; |
|
1133,6 → 1166,16
------------------------------------------------------------------------------- |
-- (Write) Data Path |
------------------------------------------------------------------------------- |
|
-- Note that this code handles both the Rd_En and Wr_En signals. These |
-- were separated to make downstream logic simpler (As opposed to the |
-- more classic RD_WRn and ADDR_STROBE scheme) It is also true to the |
-- original core, which also had separate read and write enable outputs |
|
Open8_Bus.Wr_En <= '0'; |
Open8_Bus.Wr_Data <= OPEN8_NULLBUS; |
Open8_Bus.Rd_En <= '0'; |
|
case DP_Ctrl.Src is |
when DATA_BUS_IDLE => |
null; |
1217,6 → 1260,9
|
Pending <= i_Ints or Pending; |
|
-- If Sequential_Interrupts is set true, Wait_for_ISR should follow the |
-- I bit, preventing a new interrupt from starting until the I bit is |
-- cleared. |
if( Sequential_Interrupts )then |
Wait_for_ISR <= Flags(PSR_I); |
else |
1271,6 → 1317,12
------------------------------------------------------------------------------- |
-- ALU (Arithmetic / Logic Unit) |
------------------------------------------------------------------------------- |
|
-- The ALU code is responsible for (and should be the only code altering) |
-- the register file. Most of the "instructions" directly map to opcodes |
-- but a few are for internal use only, such as operations involving the |
-- stack pointer of interrupt mask. |
|
Index := conv_integer(ALU_Ctrl.Reg); |
Sum := (others => '0'); |
Temp := (others => '0'); |