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 256 and 260

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

Rev 256 Rev 260
Line 68... Line 68...
--            :
--            :
--            :  Enable_NMI overrides the mask bit for interrupt 0, creating a
--            :  Enable_NMI overrides the mask bit for interrupt 0, creating a
--            :   non-maskable interrupt at the highest priority. To remain
--            :   non-maskable interrupt at the highest priority. To remain
--            :   true to the original core, this should be set false.
--            :   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
--            :  RTI_Ignores_GP_Flags alters the set of flag bits restored
--            :   after an interrupt. By default, all of the flag bits are put
--            :   after an interrupt. By default, all of the flag bits are put
--            :   back to their original state. If this flag is set true, only
--            :   back to their original state. If this flag is set true, only
--            :   the lower four bits are restored, allowing ISR code to alter
--            :   the lower four bits are restored, allowing ISR code to alter
--            :   the GP flags persistently.
--            :   the GP flags persistently.
Line 86... Line 100...
--            :   initialization code may be run in an ISR context, initially
--            :   initialization code may be run in an ISR context, initially
--            :   bypassing memory protection. Init code should clear the I bit
--            :   bypassing memory protection. Init code should clear the I bit
--            :   when done;
--            :   when done;
--            :
--            :
--            :  Unsigned_Index_Offsets alters the way offsets are added to
--            :  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
--            :   behavior treats these offsets as signed values, allowing
--            :   instructions to offset by -128 to +127 from [Rn+1:Rn].
--            :   instructions to offset by -128 to +127 from [Rn+1:Rn].
--            :   Setting this generic to TRUE will switch to unsigned offsets,
--            :   Setting this generic to TRUE will switch to unsigned offsets,
--            :   switching the range to 0 to 255 instead.
--            :   switching the range to 0 to 255 instead.
--            :
--            :
Line 591... Line 605...
                  --  increment the PC similar to an ISR flow.
                  --  increment the PC similar to an ISR flow.
                  CPU_Next_State  <= WAI_Cx;
                  CPU_Next_State  <= WAI_Cx;
                  PC_Ctrl.Offset  <= PC_NEXT;
                  PC_Ctrl.Offset  <= PC_NEXT;
                else
                else
                -- If Break is implemented normally, back the PC up by
                -- 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
                --  clock cycle delay
                  CPU_Next_State  <= BRK_C1;
                  CPU_Next_State  <= BRK_C1;
                  PC_Ctrl.Offset  <= PC_REV2;
                  PC_Ctrl.Offset  <= PC_REV2;
                end if;
                end if;
 
 
Line 928... Line 942...
        if( Int_Req = '1' )then
        if( Int_Req = '1' )then
          CPU_Next_State     <= ISR_C1;
          CPU_Next_State     <= ISR_C1;
          -- Rewind the PC by 3 to put the PC back to would have been the next
          -- Rewind the PC by 3 to put the PC back to would have been the next
          --  instruction, compensating for the pipeline registers.
          --  instruction, compensating for the pipeline registers.
          PC_Ctrl.Offset     <= PC_REV3;
          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;
          DP_Ctrl.Src        <= DATA_RD_MEM;
        end if;
        end if;
 
 
      when WAH_Cx => -- Holds until CPU_Halt_Req is deasserted.
      when WAH_Cx => -- Holds until CPU_Halt_Req is deasserted.
        CPU_Halt_Ack         <= '1';
        CPU_Halt_Ack         <= '1';
Line 1028... Line 1040...
    variable Sum             : std_logic_vector(8 downto 0) := "000000000";
    variable Sum             : std_logic_vector(8 downto 0) := "000000000";
    variable Temp            : std_logic_vector(8 downto 0) := "000000000";
    variable Temp            : std_logic_vector(8 downto 0) := "000000000";
  begin
  begin
    if( Reset = Reset_Level )then
    if( Reset = Reset_Level )then
      CPU_State              <= IPF_C0;
      CPU_State              <= IPF_C0;
 
 
 
      CPU_Halt_Req           <= '0';
 
      Halt_Ack               <= '0';
 
 
      Opcode                 <= OP_INC;
      Opcode                 <= OP_INC;
      SubOp                  <= ACCUM;
      SubOp                  <= ACCUM;
      SubOp_p1               <= ACCUM;
      SubOp_p1               <= ACCUM;
      Operand1               <= x"00";
      Operand1               <= x"00";
      Operand2               <= x"00";
      Operand2               <= x"00";
      Instr_Prefetch         <= '0';
      Instr_Prefetch         <= '0';
      Prefetch               <= x"00";
      Prefetch               <= x"00";
 
 
      CPU_Halt_Req           <= '0';
 
      Halt_Ack               <= '0';
 
 
 
      Open8_Bus.Wr_En        <= '0';
      Open8_Bus.Wr_En        <= '0';
      Open8_Bus.Wr_Data      <= OPEN8_NULLBUS;
      Open8_Bus.Wr_Data      <= OPEN8_NULLBUS;
      Open8_Bus.Rd_En        <= '1';
      Open8_Bus.Rd_En        <= '1';
 
 
      Program_Ctr            <= Program_Start_Addr;
      Program_Ctr            <= Program_Start_Addr;
Line 1074... Line 1087...
 
 
      Open8_Bus.GP_Flags     <= (others => '0');
      Open8_Bus.GP_Flags     <= (others => '0');
 
 
    elsif( rising_edge(Clock) )then
    elsif( rising_edge(Clock) )then
 
 
 
      CPU_State              <= CPU_Next_State;
 
 
 
-- Register the halt request and acknowledge lines
 
 
      CPU_Halt_Req           <= Halt_Req;
      CPU_Halt_Req           <= Halt_Req;
      Halt_Ack               <= CPU_Halt_Ack;
      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
-- 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
      case Cache_Ctrl is
        when CACHE_INSTR =>
        when CACHE_INSTR =>
          Opcode             <= Rd_Data(7 downto 3);
          Opcode             <= Rd_Data(7 downto 3);
          SubOp              <= Rd_Data(2 downto 0);
          SubOp              <= Rd_Data(2 downto 0);
          SubOp_p1           <= Rd_Data(2 downto 0) + 1;
          SubOp_p1           <= Rd_Data(2 downto 0) + 1;
Line 1114... Line 1139...
      end case;
      end case;
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Program Counter
-- 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(15 downto 8) := (others => PC_Ctrl.Offset(7));
      Offset_SX(7 downto 0)  := PC_Ctrl.Offset;
      Offset_SX(7 downto 0)  := PC_Ctrl.Offset;
 
 
      case PC_Ctrl.Oper is
      case PC_Ctrl.Oper is
        when PC_INCR =>
        when PC_INCR =>
Line 1131... Line 1164...
      end case;
      end case;
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- (Write) Data Path
-- (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
      case DP_Ctrl.Src is
        when DATA_BUS_IDLE =>
        when DATA_BUS_IDLE =>
          null;
          null;
 
 
        when DATA_RD_MEM =>
        when DATA_RD_MEM =>
Line 1215... Line 1258...
      i_Ints                 := (Interrupts or INT_Ctrl.Soft_Ints) and
      i_Ints                 := (Interrupts or INT_Ctrl.Soft_Ints) and
                                Int_Mask;
                                Int_Mask;
 
 
      Pending                <= i_Ints or Pending;
      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
      if( Sequential_Interrupts )then
        Wait_for_ISR         <= Flags(PSR_I);
        Wait_for_ISR         <= Flags(PSR_I);
      else
      else
        Wait_for_ISR         <= '0';
        Wait_for_ISR         <= '0';
      end if;
      end if;
Line 1269... Line 1315...
      end if;
      end if;
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- ALU (Arithmetic / Logic Unit)
-- 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);
      Index                  := conv_integer(ALU_Ctrl.Reg);
      Sum                    := (others => '0');
      Sum                    := (others => '0');
      Temp                   := (others => '0');
      Temp                   := (others => '0');
 
 
      case ALU_Ctrl.Oper is
      case ALU_Ctrl.Oper is

powered by: WebSVN 2.1.0

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