OpenCores
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 180 to Rev 181
    Reverse comparison

Rev 180 → Rev 181

/open8_urisc/trunk/VHDL/Open8.vhd
1,4 → 1,4
-- Copyright (c)2006,2011,2012,2013,2015 Jeremy Seth Henry
-- Copyright (c)2006, 2011, 2012, 2013, 2015, 2019 Jeremy Seth Henry
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
21,7 → 21,7
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- VHDL Units : Open8_CPU
-- VHDL Units : o8_cpu
-- Description: VHDL model of a RISC 8-bit processor core loosely based on the
-- : V8/ARC uRISC instruction set. Requires Open8_pkg.vhd
-- :
39,9 → 39,22
-- : Allow_Stack_Address_Move is false.
-- :
-- : Allow_Stack_Address_Move, when set true, allows the RSP to be
-- : programmed via thet RSP instruction. If enabled, the contents
-- : of R1:R0 are used to initialize the stack pointer.
-- : programmed via thet RSP instruction. If enabled, the
-- : instruction changes into TSX or TXS based on the flag
-- : specified by Stack_Xfer_Flag. If the flag is '0', RSP will
-- : copy the current stack pointer to R1:R0 (TSX). If the flag
-- : is '1', RSP will copy R1:R0 to the stack pointer (TXS). This
-- : allows the processor to backup and restore stack pointers
-- : in a multi-process environment. Note that no flags are
-- : modified by either form of this instruction.
-- :
-- : Stack_Xfer_Flag instructs the core to use the specified ALU
-- : flag to alter the behavior of the RSP instruction when
-- : Allow_Stack_Address_Move is set TRUE, otherwise it is ignored.
-- : While technically any of the status bits may be used, the
-- : intent was to use FL_GP[1,2,3,4], as these are not modified
-- : by ordinary ALU operations.
-- :
-- : The Enable_Auto_Increment generic can be used to modify the
-- : indexed instructions such that specifying an odd register
-- : will use the next lower register pair, post-incrementing the
145,6 → 158,10
-- faster logic that simply does priority encoding.
-- Seth Henry 08/06/13 Removed HALT functionality
-- Seth Henry 10/29/15 Fixed inverted carry logic in CMP and SBC instrs
-- Seth Henry 03/09/20 Modified RSP instruction to work with a CPU flag
-- allowing true backup/restore of the stack pointer
-- Also modified LDX to reduce the compexity of the
-- address logic.
 
library ieee;
use ieee.std_logic_1164.all;
161,6 → 178,7
ISR_Start_Addr : ADDRESS_TYPE := x"FFF0"; -- Bottom of ISR vec's
Stack_Start_Addr : ADDRESS_TYPE := x"03FF"; -- Top of Stack
Allow_Stack_Address_Move : boolean := false; -- Use Normal v8 RSP
Stack_Xfer_Flag : integer := FL_GP1; -- If enabled, use GP1 to control RSP
Enable_Auto_Increment : boolean := false; -- Modify indexed instr
BRK_Implements_WAI : boolean := false; -- BRK -> Wait for Int
Enable_NMI : boolean := true; -- Force INTR0 enabled
328,7 → 346,15
case SubOp is
when SOP_RSP =>
PC_Ctrl.Oper <= PC_INCR;
SP_Ctrl.Oper <= SP_RSET;
if( not Allow_Stack_Address_Move )then
SP_Ctrl.Oper <= SP_CLR;
end if;
if( Allow_Stack_Address_Move and Flags(Stack_Xfer_Flag) = '1' )then
SP_Ctrl.Oper <= SP_SET;
end if;
if( Allow_Stack_Address_Move and Flags(Stack_Xfer_Flag) = '0')then
ALU_Ctrl.Oper <= ALU_TSX;
end if;
 
when SOP_RTS | SOP_RTI =>
CPU_Next_State <= RTS_C1;
370,15 → 396,16
 
when OP_MUL =>
CPU_Next_State <= MUL_C1;
-- We need to back the PC up by 1, and allow it to refill. An
-- unfortunate consequence of the pipelining. We can get away with
-- only 1 extra clock by pre-fetching the next instruction, though
-- Multiplication requires a single clock cycle to calculate PRIOR
-- to the ALU writing the result to registers. As a result, this
-- state needs to idle the ALU initially, and back the PC up by 1
-- We can get away with only 1 extra clock by pre-fetching the
-- next instruction, though.
Cache_Ctrl <= CACHE_PREFETCH;
PC_Ctrl.Oper <= PC_REV1;
-- Multiplication is automatic, but requires a single clock cycle.
-- We need to specify the register for Rn (R1:R0 = R0 * Rn) now,
-- but will issue the multiply command on the next clock to copy
-- the results to the specified register.
-- Note that both the multiply process AND ALU process need the
-- source register for Rn (R1:R0 = R0 * Rn). Assert ALU_Ctrl.reg
-- now, but hold off on the ALU command until the next state.
ALU_Ctrl.Oper <= ALU_IDLE;
ALU_Ctrl.Reg <= SubOp;
 
405,21 → 432,8
 
when OP_LDX =>
CPU_Next_State <= LDX_C1;
Cache_Ctrl <= CACHE_PREFETCH;
PC_Ctrl.Oper <= PC_REV2;
-- If auto-increment is disabled, use the specified register pair,
-- otherwise, for an odd:even pair, and issue the first half of
-- a UPP instruction to the ALU
if( not Enable_Auto_Increment )then
Address <= Regfile(Reg_1) & Regfile(Reg);
else
Reg := conv_integer(SubOp(2 downto 1) & '0');
Reg_1 := conv_integer(SubOp(2 downto 1) & '1');
Address <= Regfile(Reg_1) & Regfile(Reg);
if( SubOp(0) = '1' )then
ALU_Ctrl.Oper<= ALU_UPP;
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
end if;
end if;
 
when OP_STA =>
CPU_Next_State <= STA_C1;
509,7 → 523,7
ALU_Ctrl.Data <= Operand1;
 
when LDO_C1 =>
CPU_Next_State <= LDX_C1;
CPU_Next_State <= LDX_C2;
PC_Ctrl.Oper <= PC_INCR;
if( Enable_Auto_Increment )then
Reg := conv_integer(SubOp(2 downto 1) & '0');
516,8 → 530,8
Reg_1 := conv_integer(SubOp(2 downto 1) & '1');
Address <= (Regfile(Reg_1) & Regfile(Reg)) + Offset_SX;
if( SubOp(0) = '1' )then
ALU_Ctrl.Oper<= ALU_UPP;
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
ALU_Ctrl.Oper <= ALU_UPP;
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
end if;
else
Address <= (Regfile(Reg_1) & Regfile(Reg)) + Offset_SX;
525,18 → 539,32
 
when LDX_C1 =>
CPU_Next_State <= LDX_C2;
PC_Ctrl.Oper <= PC_INCR;
if( Enable_Auto_Increment )then
Reg := conv_integer(SubOp(2 downto 1) & '0');
Reg_1 := conv_integer(SubOp(2 downto 1) & '1');
Address <= (Regfile(Reg_1) & Regfile(Reg));
if( SubOp(0) = '1' )then
ALU_Ctrl.Oper <= ALU_UPP;
ALU_Ctrl.Reg <= SubOp(2 downto 1) & '0';
end if;
else
Address <= (Regfile(Reg_1) & Regfile(Reg));
end if;
 
when LDX_C2 =>
CPU_Next_State <= LDX_C3;
PC_Ctrl.Oper <= PC_INCR;
 
when LDX_C3 =>
CPU_Next_State <= LDX_C4;
PC_Ctrl.Oper <= PC_INCR;
Cache_Ctrl <= CACHE_OPER1;
 
when LDX_C3 =>
when LDX_C4 =>
CPU_Next_State <= INSTR_DECODE;
Cache_Ctrl <= CACHE_INSTR;
PC_Ctrl.Oper <= PC_INCR;
ALU_Ctrl.Oper <= ALU_LDX;
ALU_Ctrl.Oper <= ALU_LDI;
ALU_Ctrl.Reg <= ACCUM;
ALU_Ctrl.Data <= Operand1;
 
617,7 → 645,9
-------------------------------------------------------------------------------
 
-- Because we have to backup the pipeline by 1 to refetch the 2nd
-- instruction/first operand, we have to return through PF2
-- instruction/first operand, we have to return through PF2. Also, we
-- 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;
PC_Ctrl.Oper <= PC_INCR;
924,17 → 954,19
when SP_IDLE =>
null;
 
when SP_RSET =>
 
-- The original RSP instruction simply reset the stack pointer to the preset
-- address set at compile time. However, with little extra effort, we can
-- modify the instruction to allow the stack pointer to be moved anywhere in
-- the memory map. Since RSP can't have an sub-opcode, R1:R0 was chosen as
-- a fixed source
 
when SP_CLR =>
Stack_Ptr <= Stack_Start_Addr;
if( Allow_Stack_Address_Move )then
Stack_Ptr <= Regfile(1) & Regfile(0);
end if;
 
when SP_SET =>
Stack_Ptr <= Regfile(1) & Regfile(0);
 
when SP_POP =>
Stack_Ptr <= Stack_Ptr + 1;
 
1157,14 → 1189,13
when ALU_POP => -- Rn <= Data
Regfile(Index) <= ALU_Ctrl.Data;
 
when ALU_LDX => -- R0 <= Data : Flags N,Z
Flags(FL_ZERO) <= nor_reduce(ALU_Ctrl.Data);
Flags(FL_NEG) <= ALU_Ctrl.Data(7);
Regfile(0) <= ALU_Ctrl.Data;
 
when ALU_RFLG =>
Flags <= ALU_Ctrl.Data;
 
when ALU_TSX =>
Regfile(0) <= Stack_Ptr(7 downto 0);
Regfile(1) <= Stack_Ptr(15 downto 8);
 
when others =>
null;
end case;
1172,4 → 1203,4
end if;
end process;
 
end architecture;
end architecture;
/open8_urisc/trunk/VHDL/Open8_pkg.vhd
1,242 → 1,243
-- Copyright (c)2006,2011,2012,2013,2015 Jeremy Seth Henry
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
-- * Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- * Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution,
-- where applicable (as part of a user interface, debugging port, etc.)
--
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-- VHDL Units : Open8_pkg
-- Description: Contains constant definitions for the Open8 processor
-- Revision History
-- Author Date Change
------------------ -------- ---------------------------------------------------
-- Seth Henry 07/22/06 Design Start
-- Seth Henry 02/03/12 Updated generics to match current model
-- Seth Henry 10/29/15 Migrated type/constant definitions to this file
 
library ieee;
use ieee.std_logic_1164.all;
 
package Open8_pkg is
 
-------------------------------------------------------------------------------
-- External constants and type declarations
--
-- These subtypes can be used with external peripherals to simplify
-- connection to the core.
-------------------------------------------------------------------------------
 
-- These must never be changed, as the core requires them to be these static
-- values for proper operation. These are ONLY defined here to allow user
-- code to dynamically configure itself to match the Open8 core ONLY.
 
constant OPEN8_ADDR_WIDTH : integer := 16; -- DON'T EVEN CONTEMPLATE
constant OPEN8_DATA_WIDTH : integer := 8; -- CHANGING THESE!
 
subtype ADDRESS_TYPE is std_logic_vector(OPEN8_ADDR_WIDTH - 1 downto 0);
subtype DATA_TYPE is std_logic_vector(OPEN8_DATA_WIDTH - 1 downto 0);
-- Note: INTERRUPT_BUNDLE must be exactly the same width as DATA_TYPE
subtype INTERRUPT_BUNDLE is DATA_TYPE;
 
-- Component declaration
-- (assumes a 1K RAM at 0x0000 and ROM at the end of the memory map)
component Open8_CPU is
generic(
Program_Start_Addr : ADDRESS_TYPE := x"8000"; -- Initial PC location
ISR_Start_Addr : ADDRESS_TYPE := x"FFF0"; -- Bottom of ISR vec's
Stack_Start_Addr : ADDRESS_TYPE := x"03FF"; -- Top of Stack
Allow_Stack_Address_Move : boolean := false; -- Use Normal v8 RSP
Enable_Auto_Increment : boolean := false; -- Modify indexed instr
BRK_Implements_WAI : boolean := false; -- BRK -> Wait for Int
Enable_NMI : boolean := true; -- Force INTR0 enabled
Default_Interrupt_Mask : DATA_TYPE := x"FF"; -- Enable all Ints
Reset_Level : std_logic := '0' ); -- Active reset level
port(
Clock : in std_logic;
Reset : in std_logic;
Interrupts : in INTERRUPT_BUNDLE;
Address : out ADDRESS_TYPE;
Rd_Data : in DATA_TYPE;
Rd_Enable : out std_logic;
Wr_Data : out DATA_TYPE;
Wr_Enable : out std_logic );
end component;
 
-------------------------------------------------------------------------------
-- Internal constants and type declarations.
--
-- These are only used in the actual model, and aren't generally useful for
-- external application.
-------------------------------------------------------------------------------
 
subtype OPCODE_TYPE is std_logic_vector(4 downto 0);
subtype SUBOP_TYPE is std_logic_vector(2 downto 0);
 
-- All opcodes should be identical to the opcode used by the assembler
-- In this case, they match the original V8/ARC uRISC ISA
constant OP_INC : OPCODE_TYPE := "00000";
constant OP_ADC : OPCODE_TYPE := "00001";
constant OP_TX0 : OPCODE_TYPE := "00010";
constant OP_OR : OPCODE_TYPE := "00011";
constant OP_AND : OPCODE_TYPE := "00100";
constant OP_XOR : OPCODE_TYPE := "00101";
constant OP_ROL : OPCODE_TYPE := "00110";
constant OP_ROR : OPCODE_TYPE := "00111";
constant OP_DEC : OPCODE_TYPE := "01000";
constant OP_SBC : OPCODE_TYPE := "01001";
constant OP_ADD : OPCODE_TYPE := "01010";
constant OP_STP : OPCODE_TYPE := "01011";
constant OP_BTT : OPCODE_TYPE := "01100";
constant OP_CLP : OPCODE_TYPE := "01101";
constant OP_T0X : OPCODE_TYPE := "01110";
constant OP_CMP : OPCODE_TYPE := "01111";
constant OP_PSH : OPCODE_TYPE := "10000";
constant OP_POP : OPCODE_TYPE := "10001";
constant OP_BR0 : OPCODE_TYPE := "10010";
constant OP_BR1 : OPCODE_TYPE := "10011";
constant OP_DBNZ : OPCODE_TYPE := "10100"; -- USR
constant OP_INT : OPCODE_TYPE := "10101";
constant OP_MUL : OPCODE_TYPE := "10110"; -- USR2
constant OP_STK : OPCODE_TYPE := "10111";
constant OP_UPP : OPCODE_TYPE := "11000";
constant OP_STA : OPCODE_TYPE := "11001";
constant OP_STX : OPCODE_TYPE := "11010";
constant OP_STO : OPCODE_TYPE := "11011";
constant OP_LDI : OPCODE_TYPE := "11100";
constant OP_LDA : OPCODE_TYPE := "11101";
constant OP_LDX : OPCODE_TYPE := "11110";
constant OP_LDO : OPCODE_TYPE := "11111";
 
-- OP_STK uses the lower 3 bits to further refine the instruction by
-- repurposing the source register field. These "sub opcodes" are
-- take the place of the register select for the OP_STK opcode
constant SOP_RSP : SUBOP_TYPE := "000";
constant SOP_RTS : SUBOP_TYPE := "001";
constant SOP_RTI : SUBOP_TYPE := "010";
constant SOP_BRK : SUBOP_TYPE := "011";
constant SOP_JMP : SUBOP_TYPE := "100";
constant SOP_SMSK : SUBOP_TYPE := "101";
constant SOP_GMSK : SUBOP_TYPE := "110";
constant SOP_JSR : SUBOP_TYPE := "111";
 
type CPU_STATES is (
-- Instruction fetch & Decode
PIPE_FILL_0, PIPE_FILL_1, PIPE_FILL_2, INSTR_DECODE,
-- Branching
BRN_C1, DBNZ_C1, JMP_C1, JMP_C2,
-- Loads
LDA_C1, LDA_C2, LDA_C3, LDA_C4, LDI_C1, LDO_C1, LDX_C1, LDX_C2, LDX_C3,
-- Stores
STA_C1, STA_C2, STA_C3, STO_C1, STO_C2, STX_C1, STX_C2,
-- 2-cycle math
MUL_C1, UPP_C1,
-- Stack
PSH_C1, POP_C1, POP_C2, POP_C3, POP_C4,
-- Subroutines & Interrupts
WAIT_FOR_INT, 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 );
 
type CACHE_MODES is (CACHE_IDLE, CACHE_INSTR, CACHE_OPER1, CACHE_OPER2,
CACHE_PREFETCH );
 
type PC_MODES is ( PC_IDLE, PC_REV1, PC_REV2, PC_INCR, PC_LOAD );
 
type PC_CTRL_TYPE is record
Oper : PC_MODES;
Offset : DATA_TYPE;
Addr : ADDRESS_TYPE;
end record;
 
type SP_MODES is ( SP_IDLE, SP_RSET, SP_POP, SP_PUSH );
 
type SP_CTRL_TYPE is record
Oper : SP_MODES;
Addr : ADDRESS_TYPE;
end record;
 
type DP_MODES is ( DATA_BUS_IDLE, DATA_RD_MEM,
DATA_WR_REG, DATA_WR_FLAG, DATA_WR_PC );
 
type DATA_CTRL_TYPE is record
Src : DP_MODES;
Reg : SUBOP_TYPE;
end record;
 
type INT_CTRL_TYPE is record
Mask_Set : std_logic;
Soft_Ints : INTERRUPT_BUNDLE;
Incr_ISR : std_logic;
end record;
 
-- Most of the ALU instructions are the same as their Opcode equivalents with
-- three exceptions (for IDLE, UPP2, and MUL2)
constant ALU_INC : OPCODE_TYPE := "00000"; -- x"00"
constant ALU_ADC : OPCODE_TYPE := "00001"; -- x"01"
constant ALU_TX0 : OPCODE_TYPE := "00010"; -- x"02"
constant ALU_OR : OPCODE_TYPE := "00011"; -- x"03"
constant ALU_AND : OPCODE_TYPE := "00100"; -- x"04"
constant ALU_XOR : OPCODE_TYPE := "00101"; -- x"05"
constant ALU_ROL : OPCODE_TYPE := "00110"; -- x"06"
constant ALU_ROR : OPCODE_TYPE := "00111"; -- x"07"
constant ALU_DEC : OPCODE_TYPE := "01000"; -- x"08"
constant ALU_SBC : OPCODE_TYPE := "01001"; -- x"09"
constant ALU_ADD : OPCODE_TYPE := "01010"; -- x"0A"
constant ALU_STP : OPCODE_TYPE := "01011"; -- x"0B"
constant ALU_BTT : OPCODE_TYPE := "01100"; -- x"0C"
constant ALU_CLP : OPCODE_TYPE := "01101"; -- x"0D"
constant ALU_T0X : OPCODE_TYPE := "01110"; -- x"0E"
constant ALU_CMP : OPCODE_TYPE := "01111"; -- x"0F"
constant ALU_POP : OPCODE_TYPE := "10001"; -- x"11"
constant ALU_MUL : OPCODE_TYPE := "10110"; -- x"16"
constant ALU_UPP : OPCODE_TYPE := "11000"; -- x"18"
constant ALU_LDI : OPCODE_TYPE := "11100"; -- x"1C"
constant ALU_LDX : OPCODE_TYPE := "11110"; -- x"1E"
 
constant ALU_IDLE : OPCODE_TYPE := "10000"; -- x"10"
constant ALU_UPP2 : OPCODE_TYPE := "10010"; -- x"12"
constant ALU_RFLG : OPCODE_TYPE := "10011"; -- x"13"
 
constant FL_ZERO : integer := 0;
constant FL_CARRY : integer := 1;
constant FL_NEG : integer := 2;
constant FL_INT_EN : integer := 3;
constant FL_GP1 : integer := 4;
constant FL_GP2 : integer := 5;
constant FL_GP3 : integer := 6;
constant FL_GP4 : integer := 7;
 
type ALU_CTRL_TYPE is record
Oper : OPCODE_TYPE;
Reg : SUBOP_TYPE;
Data : DATA_TYPE;
end record;
 
constant ACCUM : SUBOP_TYPE := "000";
constant INT_FLAG : SUBOP_TYPE := "011";
 
type REGFILE_TYPE is array (0 to 7) of DATA_TYPE;
 
subtype FLAG_TYPE is DATA_TYPE;
 
end Open8_pkg;
 
package body Open8_pkg is
end package body;
-- Copyright (c)2006,2011,2012,2013,2015 Jeremy Seth Henry
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
-- * Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- * Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution,
-- where applicable (as part of a user interface, debugging port, etc.)
--
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-- VHDL Units : Open8_pkg
-- Description: Contains constant definitions for the Open8 processor
-- Revision History
-- Author Date Change
------------------ -------- ---------------------------------------------------
-- Seth Henry 07/22/06 Design Start
-- Seth Henry 02/03/12 Updated generics to match current model
-- Seth Henry 10/29/15 Migrated type/constant definitions to this file
-- Seth Henry 03/09/20 Created new ALU/SP opcodes for handling new RSP
 
library ieee;
use ieee.std_logic_1164.all;
 
package Open8_pkg is
 
-------------------------------------------------------------------------------
-- External constants and type declarations
--
-- These subtypes can be used with external peripherals to simplify
-- connection to the core.
-------------------------------------------------------------------------------
 
-- These must never be changed, as the core requires them to be these static
-- values for proper operation. These are ONLY defined here to allow user
-- code to dynamically configure itself to match the Open8 core ONLY.
 
constant OPEN8_ADDR_WIDTH : integer := 16; -- DON'T EVEN CONTEMPLATE
constant OPEN8_DATA_WIDTH : integer := 8; -- CHANGING THESE!
 
subtype ADDRESS_TYPE is std_logic_vector(OPEN8_ADDR_WIDTH - 1 downto 0);
subtype DATA_TYPE is std_logic_vector(OPEN8_DATA_WIDTH - 1 downto 0);
-- Note: INTERRUPT_BUNDLE must be exactly the same width as DATA_TYPE
subtype INTERRUPT_BUNDLE is DATA_TYPE;
 
-- Component declaration
-- (assumes a 1K RAM at 0x0000 and ROM at the end of the memory map)
component Open8_CPU is
generic(
Program_Start_Addr : ADDRESS_TYPE := x"8000"; -- Initial PC location
ISR_Start_Addr : ADDRESS_TYPE := x"FFF0"; -- Bottom of ISR vec's
Stack_Start_Addr : ADDRESS_TYPE := x"03FF"; -- Top of Stack
Allow_Stack_Address_Move : boolean := false; -- Use Normal v8 RSP
Stack_Xfer_Flag : integer := 4; -- If enabled, GP1 alters RSP
Enable_Auto_Increment : boolean := false; -- Modify indexed instr
BRK_Implements_WAI : boolean := false; -- BRK -> Wait for Int
Enable_NMI : boolean := true; -- Force INTR0 enabled
Default_Interrupt_Mask : DATA_TYPE := x"FF"; -- Enable all Ints
Reset_Level : std_logic := '0' ); -- Active reset level
port(
Clock : in std_logic;
Reset : in std_logic;
Interrupts : in INTERRUPT_BUNDLE;
Address : out ADDRESS_TYPE;
Rd_Data : in DATA_TYPE;
Rd_Enable : out std_logic;
Wr_Data : out DATA_TYPE;
Wr_Enable : out std_logic );
end component;
 
-------------------------------------------------------------------------------
-- Internal constants and type declarations.
--
-- These are only used in the actual model, and aren't generally useful for
-- external application.
-------------------------------------------------------------------------------
 
subtype OPCODE_TYPE is std_logic_vector(4 downto 0);
subtype SUBOP_TYPE is std_logic_vector(2 downto 0);
 
-- All opcodes should be identical to the opcode used by the assembler
-- In this case, they match the original V8/ARC uRISC ISA
constant OP_INC : OPCODE_TYPE := "00000";
constant OP_ADC : OPCODE_TYPE := "00001";
constant OP_TX0 : OPCODE_TYPE := "00010";
constant OP_OR : OPCODE_TYPE := "00011";
constant OP_AND : OPCODE_TYPE := "00100";
constant OP_XOR : OPCODE_TYPE := "00101";
constant OP_ROL : OPCODE_TYPE := "00110";
constant OP_ROR : OPCODE_TYPE := "00111";
constant OP_DEC : OPCODE_TYPE := "01000";
constant OP_SBC : OPCODE_TYPE := "01001";
constant OP_ADD : OPCODE_TYPE := "01010";
constant OP_STP : OPCODE_TYPE := "01011";
constant OP_BTT : OPCODE_TYPE := "01100";
constant OP_CLP : OPCODE_TYPE := "01101";
constant OP_T0X : OPCODE_TYPE := "01110";
constant OP_CMP : OPCODE_TYPE := "01111";
constant OP_PSH : OPCODE_TYPE := "10000";
constant OP_POP : OPCODE_TYPE := "10001";
constant OP_BR0 : OPCODE_TYPE := "10010";
constant OP_BR1 : OPCODE_TYPE := "10011";
constant OP_DBNZ : OPCODE_TYPE := "10100"; -- USR
constant OP_INT : OPCODE_TYPE := "10101";
constant OP_MUL : OPCODE_TYPE := "10110"; -- USR2
constant OP_STK : OPCODE_TYPE := "10111";
constant OP_UPP : OPCODE_TYPE := "11000";
constant OP_STA : OPCODE_TYPE := "11001";
constant OP_STX : OPCODE_TYPE := "11010";
constant OP_STO : OPCODE_TYPE := "11011";
constant OP_LDI : OPCODE_TYPE := "11100";
constant OP_LDA : OPCODE_TYPE := "11101";
constant OP_LDX : OPCODE_TYPE := "11110";
constant OP_LDO : OPCODE_TYPE := "11111";
 
-- OP_STK uses the lower 3 bits to further refine the instruction by
-- repurposing the source register field. These "sub opcodes" are
-- take the place of the register select for the OP_STK opcode
constant SOP_RSP : SUBOP_TYPE := "000";
constant SOP_RTS : SUBOP_TYPE := "001";
constant SOP_RTI : SUBOP_TYPE := "010";
constant SOP_BRK : SUBOP_TYPE := "011";
constant SOP_JMP : SUBOP_TYPE := "100";
constant SOP_SMSK : SUBOP_TYPE := "101";
constant SOP_GMSK : SUBOP_TYPE := "110";
constant SOP_JSR : SUBOP_TYPE := "111";
 
type CPU_STATES is (
-- Instruction fetch & Decode
PIPE_FILL_0, PIPE_FILL_1, PIPE_FILL_2, INSTR_DECODE,
-- Branching
BRN_C1, DBNZ_C1, JMP_C1, JMP_C2,
-- Loads
LDA_C1, LDA_C2, LDA_C3, LDA_C4, LDI_C1, LDO_C1, LDX_C1, LDX_C2, LDX_C3, LDX_C4,
-- Stores
STA_C1, STA_C2, STA_C3, STO_C1, STO_C2, STX_C1, STX_C2,
-- 2-cycle math
MUL_C1, UPP_C1,
-- Stack
PSH_C1, POP_C1, POP_C2, POP_C3, POP_C4,
-- Subroutines & Interrupts
WAIT_FOR_INT, 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 );
 
type CACHE_MODES is (CACHE_IDLE, CACHE_INSTR, CACHE_OPER1, CACHE_OPER2,
CACHE_PREFETCH );
 
type PC_MODES is ( PC_IDLE, PC_REV1, PC_REV2, PC_INCR, PC_LOAD );
 
type PC_CTRL_TYPE is record
Oper : PC_MODES;
Offset : DATA_TYPE;
Addr : ADDRESS_TYPE;
end record;
 
type SP_MODES is ( SP_IDLE, SP_CLR, SP_SET, SP_POP, SP_PUSH );
 
type SP_CTRL_TYPE is record
Oper : SP_MODES;
end record;
 
type DP_MODES is ( DATA_BUS_IDLE, DATA_RD_MEM,
DATA_WR_REG, DATA_WR_FLAG, DATA_WR_PC );
 
type DATA_CTRL_TYPE is record
Src : DP_MODES;
Reg : SUBOP_TYPE;
end record;
 
type INT_CTRL_TYPE is record
Mask_Set : std_logic;
Soft_Ints : INTERRUPT_BUNDLE;
Incr_ISR : std_logic;
end record;
 
-- Most of the ALU instructions are the same as their Opcode equivalents with
-- three exceptions (for IDLE, UPP2, and MUL2)
constant ALU_INC : OPCODE_TYPE := "00000"; -- x"00"
constant ALU_ADC : OPCODE_TYPE := "00001"; -- x"01"
constant ALU_TX0 : OPCODE_TYPE := "00010"; -- x"02"
constant ALU_OR : OPCODE_TYPE := "00011"; -- x"03"
constant ALU_AND : OPCODE_TYPE := "00100"; -- x"04"
constant ALU_XOR : OPCODE_TYPE := "00101"; -- x"05"
constant ALU_ROL : OPCODE_TYPE := "00110"; -- x"06"
constant ALU_ROR : OPCODE_TYPE := "00111"; -- x"07"
constant ALU_DEC : OPCODE_TYPE := "01000"; -- x"08"
constant ALU_SBC : OPCODE_TYPE := "01001"; -- x"09"
constant ALU_ADD : OPCODE_TYPE := "01010"; -- x"0A"
constant ALU_STP : OPCODE_TYPE := "01011"; -- x"0B"
constant ALU_BTT : OPCODE_TYPE := "01100"; -- x"0C"
constant ALU_CLP : OPCODE_TYPE := "01101"; -- x"0D"
constant ALU_T0X : OPCODE_TYPE := "01110"; -- x"0E"
constant ALU_CMP : OPCODE_TYPE := "01111"; -- x"0F"
constant ALU_POP : OPCODE_TYPE := "10001"; -- x"11"
constant ALU_MUL : OPCODE_TYPE := "10110"; -- x"16"
constant ALU_UPP : OPCODE_TYPE := "11000"; -- x"18"
constant ALU_LDI : OPCODE_TYPE := "11100"; -- x"1C"
 
constant ALU_IDLE : OPCODE_TYPE := "10000"; -- x"10"
constant ALU_UPP2 : OPCODE_TYPE := "10010"; -- x"12"
constant ALU_RFLG : OPCODE_TYPE := "10011"; -- x"13"
constant ALU_TSX : OPCODE_TYPE := "10111"; -- x"17"
 
constant FL_ZERO : integer := 0;
constant FL_CARRY : integer := 1;
constant FL_NEG : integer := 2;
constant FL_INT_EN : integer := 3;
constant FL_GP1 : integer := 4;
constant FL_GP2 : integer := 5;
constant FL_GP3 : integer := 6;
constant FL_GP4 : integer := 7;
 
type ALU_CTRL_TYPE is record
Oper : OPCODE_TYPE;
Reg : SUBOP_TYPE;
Data : DATA_TYPE;
end record;
 
constant ACCUM : SUBOP_TYPE := "000";
constant INT_FLAG : SUBOP_TYPE := "011";
 
type REGFILE_TYPE is array (0 to 7) of DATA_TYPE;
 
subtype FLAG_TYPE is DATA_TYPE;
 
end Open8_pkg;
 
package body Open8_pkg is
end package body;

powered by: WebSVN 2.1.0

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