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
- from Rev 251 to Rev 252
- ↔ Reverse comparison
Rev 251 → Rev 252
/trunk/VHDL/o8_cpu.vhd
229,6 → 229,11
-- Seth Henry 05/24/20 Removed the Default_Int_Flag, as it is covered by |
-- Supervisor_Mode. If Supervisor_Mode isn't set, |
-- code can simply use STP to set the bit |
-- Seth Henry 06/09/20 Added ability to use unsigned index offsets for |
-- LDO/SDO. Also pipelined the address calculation |
-- for indexed instructions, reducing the final |
-- address generator to a multiplexor fed only by |
-- registers. |
|
library ieee; |
use ieee.std_logic_1164.all; |
252,6 → 257,7
Sequential_Interrupts : boolean := false; -- Interruptable ISRs |
RTI_Ignores_GP_Flags : boolean := false; -- RTI sets all flags |
Supervisor_Mode : boolean := false; -- I bit is restricted |
Unsigned_Index_Offsets : boolean := false; -- Offsets are signed |
Default_Interrupt_Mask : DATA_TYPE := x"FF"; -- Enable all Ints |
Clock_Frequency : real -- Clock Frequency |
); |
329,6 → 335,14
signal Wait_for_FSM : std_logic := '0'; |
signal Wait_for_ISR : std_logic := '0'; |
|
signal IDX_Offset : ADDRESS_TYPE := x"0000"; |
|
signal IDX_Reg_l : integer := 0; |
signal IDX_Reg_h : integer := 0; |
|
signal IDX_NoOffset_Calc : ADDRESS_TYPE := x"0000"; |
signal IDX_Offset_Calc : ADDRESS_TYPE := x"0000"; |
|
begin |
|
------------------------------------------------------------------------------- |
368,23 → 382,54
-- Address bus selection/generation logic |
------------------------------------------------------------------------------- |
|
Address_Logic: process(CPU_State, Regfile, SubOp, SubOp_p1, Operand1, |
Operand2, Program_Ctr, Stack_Ptr, ISR_Addr ) |
-- The original model treated the offset to LDO/STO as a signed value |
-- allowing access to locations -128 to +127 from [Rn+1:Rn]. This isn't |
-- always helpful, so the generic allows the CPU to use unsigned math |
-- for the offsets. This makes the range 0 to +255 instead. |
Unsigned_Idx_Offsets : if( Unsigned_Index_Offsets )generate |
IDX_Offset(15 downto 8) <= (others => '0'); |
IDX_Offset(7 downto 0) <= Operand1; |
end generate; |
|
Signed_Idx_Offsets: if( not Unsigned_Index_Offsets )generate |
IDX_Offset(15 downto 8) <= (others => Operand1(7)); |
IDX_Offset(7 downto 0) <= Operand1; |
end generate; |
|
-- Enable_Auto_Increment uses the LSB to determine whether or not to |
-- do the auto-increment, so we need to lock the LSB for each operand |
-- if it is enabled. This forces [ODD:EVEN] pairing. |
|
Auto_Incr_Set: if( Enable_Auto_Increment )generate |
IDX_Reg_l <= conv_integer(SubOp(2 downto 1) & '0'); |
IDX_Reg_h <= conv_integer(SubOp(2 downto 1) & '1'); |
end generate; |
|
Auto_Incr_Not_Set: if( not Enable_Auto_Increment )generate |
IDX_Reg_l <= conv_integer(SubOp); |
IDX_Reg_h <= conv_integer(SubOp_p1); |
end generate; |
|
-- Pipeline registers for the indexed and indexed with offset addresses. |
Idx_Addr_Calc_proc: process( Clock, Reset ) |
variable Reg, Reg_1 : integer range 0 to 7 := 0; |
variable Offset_SX : ADDRESS_TYPE; |
begin |
|
if( Enable_Auto_Increment )then |
Reg := conv_integer(SubOp(2 downto 1) & '0'); |
Reg_1 := conv_integer(SubOp(2 downto 1) & '1'); |
else |
Reg := conv_integer(SubOp); |
Reg_1 := conv_integer(SubOp_p1); |
if( Reset = Reset_Level )then |
IDX_NoOffset_Calc <= x"0000"; |
IDX_Offset_Calc <= x"0000"; |
elsif( rising_edge(Clock))then |
IDX_NoOffset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)); |
IDX_Offset_Calc <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) + |
IDX_Offset; |
end if; |
end process; |
|
Offset_SX(15 downto 0) := (others => Operand1(7)); |
Offset_SX(7 downto 0) := Operand1; |
|
-- Address selection logic based on current CPU state. This is combinatorial, |
-- as adding pipeline registration would add a clock cycle to every instr, |
-- without really adding the Fmax to compensate. |
Address_Logic: process(CPU_State, Operand1, Operand2, IDX_NoOffset_Calc, |
IDX_Offset_Calc, ISR_Addr, Stack_Ptr, Program_Ctr ) |
begin |
case( CPU_State )is |
|
when LDA_C2 | STA_C2 => |
391,10 → 436,10
Open8_Bus.Address <= Operand2 & Operand1; |
|
when LDX_C1 | STX_C1 => |
Open8_Bus.Address <= (Regfile(Reg_1) & Regfile(Reg)); |
Open8_Bus.Address <= IDX_NoOffset_Calc; |
|
when LDO_C1 | STO_C1 => |
Open8_Bus.Address <= (Regfile(Reg_1) & Regfile(Reg)) + Offset_SX; |
when LDO_C2 | STO_C2 => |
Open8_Bus.Address <= IDX_Offset_Calc; |
|
when ISR_C1 | ISR_C2 => |
Open8_Bus.Address <= ISR_Addr; |
406,7 → 451,6
Open8_Bus.Address <= Program_Ctr; |
|
end case; |
|
end process; |
|
------------------------------------------------------------------------------- |
612,9 → 656,7
when OP_STO => |
CPU_Next_State <= STO_C1; |
Cache_Ctrl <= CACHE_OPER1; |
PC_Ctrl.Offset <= PC_REV2; |
DP_Ctrl.Src <= DATA_WR_REG; |
DP_Ctrl.Reg <= ACCUM; |
PC_Ctrl.Offset <= PC_REV1; |
|
when OP_STX => |
CPU_Next_State <= STX_C1; |
734,6 → 776,9
ALU_Ctrl.Reg <= SubOp; |
|
when LDO_C1 => |
CPU_Next_State <= LDO_C2; |
|
when LDO_C2 => |
CPU_Next_State <= LDX_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Enable_Auto_Increment and SubOp(0) = '1' )then |
783,17 → 828,22
PC_Ctrl.Offset <= PC_NEXT; |
|
when STO_C1 => |
CPU_Next_State <= IPF_C0; |
CPU_Next_State <= STO_C2; |
Cache_Ctrl <= CACHE_PREFETCH; |
DP_Ctrl.Src <= DATA_WR_REG; |
DP_Ctrl.Reg <= ACCUM; |
|
when STO_C2 => |
CPU_Next_State <= IPF_C1; |
PC_Ctrl.Offset <= PC_NEXT; |
if( Enable_Auto_Increment and SubOp(0) = '1' )then |
CPU_Next_State <= STO_C2; |
CPU_Next_State <= STO_C3; |
ALU_Ctrl.Oper <= ALU_UPP; |
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0'; |
end if; |
|
when STO_C2 => |
CPU_Next_State <= IPF_C1; |
when STO_C3 => |
CPU_Next_State <= IPF_C2; |
PC_Ctrl.Offset <= PC_NEXT; |
ALU_Ctrl.Oper <= ALU_UPP2; |
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '1'; |