OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_cpu.vhd] - Diff between revs 248 and 252

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 248 Rev 252
Line 227... Line 227...
-- Seth Henry      05/21/20 Supervisor_Mode now protects the interrupt mask
-- Seth Henry      05/21/20 Supervisor_Mode now protects the interrupt mask
--                           and stack pointer as well.
--                           and stack pointer as well.
-- Seth Henry      05/24/20 Removed the Default_Int_Flag, as it is covered by
-- Seth Henry      05/24/20 Removed the Default_Int_Flag, as it is covered by
--                           Supervisor_Mode. If Supervisor_Mode isn't set,
--                           Supervisor_Mode. If Supervisor_Mode isn't set,
--                           code can simply use STP to set the bit
--                           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;
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 250... Line 255...
    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
    Sequential_Interrupts    : boolean      := false;   -- Interruptable ISRs
    Sequential_Interrupts    : boolean      := false;   -- Interruptable ISRs
    RTI_Ignores_GP_Flags     : boolean      := false;   -- RTI sets all flags
    RTI_Ignores_GP_Flags     : boolean      := false;   -- RTI sets all flags
    Supervisor_Mode          : boolean      := false;   -- I bit is restricted
    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
    Default_Interrupt_Mask   : DATA_TYPE    := x"FF";   -- Enable all Ints
    Clock_Frequency          : real                     -- Clock Frequency
    Clock_Frequency          : real                     -- Clock Frequency
);
);
  port(
  port(
    Clock                    : in  std_logic;
    Clock                    : in  std_logic;
Line 327... Line 333...
  signal i_Ints              : INTERRUPT_BUNDLE := x"00";
  signal i_Ints              : INTERRUPT_BUNDLE := x"00";
  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';
  signal Wait_for_ISR        : 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
begin
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Reset & uSec Tick
-- Reset & uSec Tick
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Line 366... Line 380...
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Address bus selection/generation logic
-- Address bus selection/generation logic
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
 
  Address_Logic: process(CPU_State, Regfile, SubOp, SubOp_p1, Operand1,
  -- The original model treated the offset to LDO/STO as a signed value
                         Operand2, Program_Ctr, Stack_Ptr, ISR_Addr )
  --  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 Reg, Reg_1      : integer range 0 to 7 := 0;
    variable Offset_SX       : ADDRESS_TYPE;
 
  begin
  begin
 
    if( Reset = Reset_Level )then
    if( Enable_Auto_Increment )then
      IDX_NoOffset_Calc      <= x"0000";
      Reg                    := conv_integer(SubOp(2 downto 1) & '0');
      IDX_Offset_Calc        <= x"0000";
      Reg_1                  := conv_integer(SubOp(2 downto 1) & '1');
    elsif( rising_edge(Clock))then
    else
      IDX_NoOffset_Calc      <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l));
      Reg                    := conv_integer(SubOp);
      IDX_Offset_Calc        <= (Regfile(IDX_Reg_h) & Regfile(IDX_Reg_l)) +
      Reg_1                  := conv_integer(SubOp_p1);
                                IDX_Offset;
    end if;
    end if;
 
  end process;
 
 
    Offset_SX(15 downto 0)   := (others => Operand1(7));
  -- Address selection logic based on current CPU state. This is combinatorial,
    Offset_SX(7 downto 0)    := Operand1;
  --  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
    case( CPU_State )is
 
 
      when LDA_C2 | STA_C2 =>
      when LDA_C2 | STA_C2 =>
        Open8_Bus.Address    <= Operand2 & Operand1;
        Open8_Bus.Address    <= Operand2 & Operand1;
 
 
      when LDX_C1 | STX_C1 =>
      when LDX_C1 | STX_C1 =>
        Open8_Bus.Address    <= (Regfile(Reg_1) & Regfile(Reg));
        Open8_Bus.Address    <= IDX_NoOffset_Calc;
 
 
      when LDO_C1 | STO_C1 =>
      when LDO_C2 | STO_C2 =>
        Open8_Bus.Address    <= (Regfile(Reg_1) & Regfile(Reg)) + Offset_SX;
        Open8_Bus.Address    <= IDX_Offset_Calc;
 
 
      when ISR_C1 | ISR_C2 =>
      when ISR_C1 | ISR_C2 =>
        Open8_Bus.Address    <= ISR_Addr;
        Open8_Bus.Address    <= ISR_Addr;
 
 
      when PSH_C1 | POP_C1 | ISR_C3 | JSR_C1 | JSR_C2 | RTS_C1 | RTS_C2 | RTS_C3 =>
      when PSH_C1 | POP_C1 | ISR_C3 | JSR_C1 | JSR_C2 | RTS_C1 | RTS_C2 | RTS_C3 =>
Line 404... Line 449...
 
 
      when others =>
      when others =>
        Open8_Bus.Address    <= Program_Ctr;
        Open8_Bus.Address    <= Program_Ctr;
 
 
    end case;
    end case;
 
 
  end process;
  end process;
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Combinatorial portion of CPU finite state machine
-- Combinatorial portion of CPU finite state machine
-- State Logic / Instruction Decoding & Execution
-- State Logic / Instruction Decoding & Execution
Line 610... Line 654...
            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.Offset   <= PC_REV2;
            PC_Ctrl.Offset   <= PC_REV1;
            DP_Ctrl.Src      <= DATA_WR_REG;
 
            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.Offset   <= PC_REV2;
            PC_Ctrl.Offset   <= PC_REV2;
Line 732... Line 774...
        PC_Ctrl.Offset       <= PC_NEXT;
        PC_Ctrl.Offset       <= PC_NEXT;
        ALU_Ctrl.Oper        <= ALU_LDI;
        ALU_Ctrl.Oper        <= ALU_LDI;
        ALU_Ctrl.Reg         <= SubOp;
        ALU_Ctrl.Reg         <= SubOp;
 
 
      when LDO_C1 =>
      when LDO_C1 =>
 
        CPU_Next_State       <= LDO_C2;
 
 
 
      when LDO_C2 =>
        CPU_Next_State       <= LDX_C2;
        CPU_Next_State       <= LDX_C2;
        PC_Ctrl.Offset       <= PC_NEXT;
        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';
Line 781... Line 826...
        CPU_Next_State       <= IPF_C2;
        CPU_Next_State       <= IPF_C2;
        Cache_Ctrl           <= CACHE_PREFETCH;
        Cache_Ctrl           <= CACHE_PREFETCH;
        PC_Ctrl.Offset       <= PC_NEXT;
        PC_Ctrl.Offset       <= PC_NEXT;
 
 
      when STO_C1 =>
      when STO_C1 =>
        CPU_Next_State       <= IPF_C0;
        CPU_Next_State       <= STO_C2;
        Cache_Ctrl           <= CACHE_PREFETCH;
        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;
        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_C3;
          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_C3 =>
        CPU_Next_State       <= IPF_C1;
        CPU_Next_State       <= IPF_C2;
        PC_Ctrl.Offset       <= PC_NEXT;
        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 =>

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.