summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--zpu/hdl/zpu4/core/zpu_config.vhd32
-rw-r--r--zpu/hdl/zpu4/core/zpu_core.vhd1820
-rw-r--r--zpu/hdl/zpu4/core/zpu_core_small.vhd1065
-rw-r--r--zpu/hdl/zpu4/core/zpupkg.vhd338
4 files changed, 1679 insertions, 1576 deletions
diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd
index 4fecf01..112dd01 100644
--- a/zpu/hdl/zpu4/core/zpu_config.vhd
+++ b/zpu/hdl/zpu4/core/zpu_config.vhd
@@ -39,19 +39,21 @@ use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
package zpu_config is
- -- generate trace output or not.
- constant Generate_Trace : boolean := false;
- constant wordPower : integer := 5;
- -- during simulation, set this to '0' to get matching trace.txt
- constant DontCareValue : std_logic := 'X';
- -- Clock frequency in MHz.
- constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"64";
- -- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
- constant maxAddrBitIncIO : integer := 15;
- constant maxAddrBitBRAM : integer := 14;
-
- -- start byte address of stack.
- -- point to top of RAM - 2*words
- constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) :=
- conv_std_logic_vector((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1);
+
+ -- generate trace output or not.
+ constant Generate_Trace : boolean := false;
+ constant wordPower : integer := 5;
+ -- during simulation, set this to '0' to get matching trace.txt
+ constant DontCareValue : std_logic := 'X';
+ -- Clock frequency in MHz.
+ constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"64";
+ -- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
+ constant maxAddrBitIncIO : integer := 15;
+ constant maxAddrBitBRAM : integer := 14;
+
+ -- start byte address of stack.
+ -- point to top of RAM - 2*words
+ constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) :=
+ conv_std_logic_vector((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1);
+
end zpu_config;
diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd
index 69da686..ff9449f 100644
--- a/zpu/hdl/zpu4/core/zpu_core.vhd
+++ b/zpu/hdl/zpu4/core/zpu_core.vhd
@@ -33,8 +33,8 @@
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
-library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
+library ieee;
+use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
@@ -58,899 +58,957 @@ use work.zpupkg.all;
-- write request
-- break - set to '1' when CPU hits break instruction
-- interrupt - set to '1' until interrupts are cleared by CPU.
-
+
entity zpu_core is
- Port ( clk : in std_logic;
- areset : in std_logic;
- enable : in std_logic;
- in_mem_busy : in std_logic;
- mem_read : in std_logic_vector(wordSize-1 downto 0);
- mem_write : out std_logic_vector(wordSize-1 downto 0);
- out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
- out_mem_writeEnable : out std_logic;
- out_mem_readEnable : out std_logic;
- mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
- interrupt : in std_logic;
- break : out std_logic);
+ port (
+ clk : in std_logic;
+ areset : in std_logic;
+ enable : in std_logic;
+ in_mem_busy : in std_logic;
+ mem_read : in std_logic_vector(wordSize-1 downto 0);
+ mem_write : out std_logic_vector(wordSize-1 downto 0);
+ out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
+ out_mem_writeEnable : out std_logic;
+ out_mem_readEnable : out std_logic;
+ mem_writeMask : out std_logic_vector(wordBytes-1 downto 0);
+ interrupt : in std_logic;
+ break : out std_logic
+ );
end zpu_core;
architecture behave of zpu_core is
-type InsnType is
-(
-State_AddTop,
-State_Dup,
-State_DupStackB,
-State_Pop,
-State_Popdown,
-State_Add,
-State_Or,
-State_And,
-State_Store,
-State_AddSP,
-State_Shift,
-State_Nop,
-State_Im,
-State_LoadSP,
-State_StoreSP,
-State_Emulate,
-State_Load,
-State_PushPC,
-State_PushSP,
-State_PopPC,
-State_PopPCRel,
-State_Not,
-State_Flip,
-State_PopSP,
-State_Neqbranch,
-State_Eq,
-State_Loadb,
-State_Mult,
-State_Lessthan,
-State_Lessthanorequal,
-State_Ulessthanorequal,
-State_Ulessthan,
-State_Pushspadd,
-State_Call,
-State_Callpcrel,
-State_Sub,
-State_Break,
-State_Storeb,
-State_InsnFetch
-);
-
-type StateType is
-(
-State_Load2,
-State_Popped,
-State_LoadSP2,
-State_LoadSP3,
-State_AddSP2,
-State_Fetch,
-State_Execute,
-State_Decode,
-State_Decode2,
-State_Resync,
-
-State_StoreSP2,
-State_Resync2,
-State_Resync3,
-State_Loadb2,
-State_Storeb2,
-State_Mult2,
-State_Mult3,
-State_Mult5,
-State_Mult4,
-State_BinaryOpResult2,
-State_BinaryOpResult,
-State_Idle,
-State_Interrupt
-);
-
-
-signal pc : unsigned(maxAddrBitIncIO downto 0);
-signal sp : unsigned(maxAddrBitIncIO downto minAddrBit);
-signal incSp : unsigned(maxAddrBitIncIO downto minAddrBit);
-signal incIncSp : unsigned(maxAddrBitIncIO downto minAddrBit);
-signal decSp : unsigned(maxAddrBitIncIO downto minAddrBit);
-signal stackA : unsigned(wordSize-1 downto 0);
-signal binaryOpResult : unsigned(wordSize-1 downto 0);
-signal binaryOpResult2 : unsigned(wordSize-1 downto 0);
-signal multResult2 : unsigned(wordSize-1 downto 0);
-signal multResult3 : unsigned(wordSize-1 downto 0);
-signal multResult : unsigned(wordSize-1 downto 0);
-signal multA : unsigned(wordSize-1 downto 0);
-signal multB : unsigned(wordSize-1 downto 0);
-signal stackB : unsigned(wordSize-1 downto 0);
-signal idim_flag : std_logic;
-signal busy : std_logic;
-signal mem_writeEnable : std_logic;
-signal mem_readEnable : std_logic;
-signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal mem_delayReadEnable : std_logic;
-
-signal inInterrupt: std_logic;
-
-signal decodeWord : std_logic_vector(wordSize-1 downto 0);
-
-
-signal state : StateType;
-signal insn : InsnType;
-type InsnArray is array(0 to wordBytes-1) of InsnType;
-signal decodedOpcode : InsnArray;
-
-type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
-
-signal opcode : OpcodeArray;
-
-
-
-
-signal begin_inst : std_logic;
-signal trace_opcode : std_logic_vector(7 downto 0);
-signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
-signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
-signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
+ type InsnType is (
+ State_AddTop,
+ State_Dup,
+ State_DupStackB,
+ State_Pop,
+ State_Popdown,
+ State_Add,
+ State_Or,
+ State_And,
+ State_Store,
+ State_AddSP,
+ State_Shift,
+ State_Nop,
+ State_Im,
+ State_LoadSP,
+ State_StoreSP,
+ State_Emulate,
+ State_Load,
+ State_PushPC,
+ State_PushSP,
+ State_PopPC,
+ State_PopPCRel,
+ State_Not,
+ State_Flip,
+ State_PopSP,
+ State_Neqbranch,
+ State_Eq,
+ State_Loadb,
+ State_Mult,
+ State_Lessthan,
+ State_Lessthanorequal,
+ State_Ulessthanorequal,
+ State_Ulessthan,
+ State_Pushspadd,
+ State_Call,
+ State_Callpcrel,
+ State_Sub,
+ State_Break,
+ State_Storeb,
+ State_InsnFetch
+ );
+
+ type StateType is (
+ State_Load2,
+ State_Popped,
+ State_LoadSP2,
+ State_LoadSP3,
+ State_AddSP2,
+ State_Fetch,
+ State_Execute,
+ State_Decode,
+ State_Decode2,
+ State_Resync,
+
+ State_StoreSP2,
+ State_Resync2,
+ State_Resync3,
+ State_Loadb2,
+ State_Storeb2,
+ State_Mult2,
+ State_Mult3,
+ State_Mult5,
+ State_Mult4,
+ State_BinaryOpResult2,
+ State_BinaryOpResult,
+ State_Idle,
+ State_Interrupt
+ );
+
+
+ signal pc : unsigned(maxAddrBitIncIO downto 0);
+ signal sp : unsigned(maxAddrBitIncIO downto minAddrBit);
+ signal incSp : unsigned(maxAddrBitIncIO downto minAddrBit);
+ signal incIncSp : unsigned(maxAddrBitIncIO downto minAddrBit);
+ signal decSp : unsigned(maxAddrBitIncIO downto minAddrBit);
+ signal stackA : unsigned(wordSize-1 downto 0);
+ signal binaryOpResult : unsigned(wordSize-1 downto 0);
+ signal binaryOpResult2 : unsigned(wordSize-1 downto 0);
+ signal multResult2 : unsigned(wordSize-1 downto 0);
+ signal multResult3 : unsigned(wordSize-1 downto 0);
+ signal multResult : unsigned(wordSize-1 downto 0);
+ signal multA : unsigned(wordSize-1 downto 0);
+ signal multB : unsigned(wordSize-1 downto 0);
+ signal stackB : unsigned(wordSize-1 downto 0);
+ signal idim_flag : std_logic;
+ signal busy : std_logic;
+ signal mem_writeEnable : std_logic;
+ signal mem_readEnable : std_logic;
+ signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ signal mem_delayReadEnable : std_logic;
+ --
+ signal inInterrupt : std_logic;
+ --
+ signal decodeWord : std_logic_vector(wordSize-1 downto 0);
+ --
+ --
+ signal state : StateType;
+ signal insn : InsnType;
+ type InsnArray is array(0 to wordBytes-1) of InsnType;
+ signal decodedOpcode : InsnArray;
+ --
+ type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
+ --
+ signal opcode : OpcodeArray;
+
+
+
+
+ signal begin_inst : std_logic;
+ signal trace_opcode : std_logic_vector(7 downto 0);
+ signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
+ signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
+ signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
-- state machine.
begin
- traceFileGenerate:
- if Generate_Trace generate
- trace_file: trace port map (
- clk => clk,
- begin_inst => begin_inst,
- pc => trace_pc,
- opcode => trace_opcode,
- sp => trace_sp,
- memA => trace_topOfStack,
- memB => trace_topOfStackB,
- busy => busy,
- intsp => (others => 'U')
- );
- end generate;
-
-
- -- the memory subsystem will tell us one cycle later whether or
- -- not it is busy
- out_mem_writeEnable <= mem_writeEnable;
- out_mem_readEnable <= mem_readEnable;
- out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
- out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
-
- incSp <= sp + 1;
- incIncSp <= sp + 2;
- decSp <= sp - 1;
-
-
- opcodeControl:
- process(clk, areset)
- variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
- variable spOffset : unsigned(4 downto 0);
- variable tSpOffset : unsigned(4 downto 0);
- variable nextPC : unsigned(maxAddrBitIncIO downto 0);
- variable tNextState : InsnType;
- variable tDecodedOpcode : InsnArray;
- variable tMultResult : unsigned(wordSize*2-1 downto 0);
- begin
- if areset = '1' then
- state <= State_Idle;
- break <= '0';
- sp <= unsigned(spStart(maxAddrBitIncIO downto minAddrBit));
-
- pc <= (others => '0');
- idim_flag <= '0';
- begin_inst <= '0';
- inInterrupt <= '0';
- mem_writeEnable <= '0';
- mem_readEnable <= '0';
- multA <= (others => '0');
- multB <= (others => '0');
- mem_writeMask <= (others => '1');
- elsif (clk'event and clk = '1') then
- -- we must multiply unconditionally to get pipelined multiplication
- tMultResult := multA * multB;
- multResult3 <= multResult2;
- multResult2 <= multResult;
- multResult <= tMultResult(wordSize-1 downto 0);
-
-
- binaryOpResult2 <= binaryOpResult; -- pipeline a bit.
-
-
- multA <= (others => DontCareValue);
- multB <= (others => DontCareValue);
-
-
- mem_addr <= (others => DontCareValue);
- mem_readEnable <='0';
- mem_writeEnable <='0';
- mem_write <= (others => DontCareValue);
-
- if (mem_writeEnable = '1') and (mem_readEnable = '1') then
- report "read/write collision" severity failure;
- end if;
-
-
-
-
- spOffset(4):=not opcode(to_integer(pc(byteBits-1 downto 0)))(4);
- spOffset(3 downto 0):=unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(3 downto 0));
- nextPC := pc + 1;
-
- -- prepare trace snapshot
- trace_opcode <= opcode(to_integer(pc(byteBits-1 downto 0)));
- trace_pc <= std_logic_vector(pc);
- trace_sp <= std_logic_vector(sp);
- trace_topOfStack <= std_logic_vector(stackA);
- trace_topOfStackB <= std_logic_vector(stackB);
- begin_inst <= '0';
-
- if (interrupt='0') then
- -- Interrupt ended, we can serve ISR again
- inInterrupt <= '0';
- end if;
-
- case state is
- when State_Idle =>
- if enable='1' then
- state <= State_Resync;
- end if;
- -- Initial state of ZPU, fetch top of stack + first instruction
- when State_Resync =>
- if in_mem_busy='0' then
- mem_addr <= std_logic_vector(sp);
- mem_readEnable <= '1';
- state <= State_Resync2;
- end if;
- when State_Resync2 =>
- if in_mem_busy='0' then
- stackA <= unsigned(mem_read);
- mem_addr <= std_logic_vector(incSp);
- mem_readEnable <= '1';
- state <= State_Resync3;
- end if;
- when State_Resync3 =>
- if in_mem_busy='0' then
- stackB <= unsigned(mem_read);
- mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- state <= State_Decode;
- end if;
- when State_Decode =>
- if in_mem_busy='0' then
- decodeWord <= mem_read;
- state <= State_Decode2;
- -- Do not recurse into ISR while interrupt line is active
- if interrupt='1' and inInterrupt='0' and idim_flag='0' then
- -- We got an interrupt, execute interrupt instead of next instruction
- inInterrupt <= '1';
- sp <= decSp;
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc;
- stackB <= stackA;
- pc <= to_unsigned(32, maxAddrBitIncIO+1);
- state <= State_Interrupt;
- end if;
- end if;
- when State_Interrupt =>
- if in_mem_busy='0' then
- mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- state <= State_Decode;
- report "ZPU jumped to interrupt!" severity note;
- end if;
- when State_Decode2 =>
- -- decode 4 instructions in parallel
- for i in 0 to wordBytes-1 loop
- tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
-
- tSpOffset(4):=not tOpcode(4);
- tSpOffset(3 downto 0):=unsigned(tOpcode(3 downto 0));
-
- opcode(i) <= tOpcode;
- if (tOpcode(7 downto 7)=OpCode_Im) then
- tNextState:=State_Im;
- elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
- if tSpOffset = 0 then
- tNextState := State_Pop;
- elsif tSpOffset=1 then
- tNextState := State_PopDown;
- else
- tNextState :=State_StoreSP;
- end if;
- elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
- if tSpOffset = 0 then
- tNextState :=State_Dup;
- elsif tSpOffset = 1 then
- tNextState :=State_DupStackB;
- else
- tNextState :=State_LoadSP;
- end if;
- elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
- tNextState :=State_Emulate;
- if tOpcode(5 downto 0)=OpCode_Neqbranch then
- tNextState :=State_Neqbranch;
- elsif tOpcode(5 downto 0)=OpCode_Eq then
- tNextState :=State_Eq;
- elsif tOpcode(5 downto 0)=OpCode_Lessthan then
- tNextState :=State_Lessthan;
- elsif tOpcode(5 downto 0)=OpCode_Lessthanorequal then
- --tNextState :=State_Lessthanorequal;
- elsif tOpcode(5 downto 0)=OpCode_Ulessthan then
- tNextState :=State_Ulessthan;
- elsif tOpcode(5 downto 0)=OpCode_Ulessthanorequal then
- --tNextState :=State_Ulessthanorequal;
- elsif tOpcode(5 downto 0)=OpCode_Loadb then
- tNextState :=State_Loadb;
- elsif tOpcode(5 downto 0)=OpCode_Mult then
- tNextState :=State_Mult;
- elsif tOpcode(5 downto 0)=OpCode_Storeb then
- tNextState :=State_Storeb;
- elsif tOpcode(5 downto 0)=OpCode_Pushspadd then
- tNextState :=State_Pushspadd;
- elsif tOpcode(5 downto 0)=OpCode_Callpcrel then
- tNextState :=State_Callpcrel;
- elsif tOpcode(5 downto 0)=OpCode_Call then
- --tNextState :=State_Call;
- elsif tOpcode(5 downto 0)=OpCode_Sub then
- tNextState :=State_Sub;
- elsif tOpcode(5 downto 0)=OpCode_PopPCRel then
- --tNextState :=State_PopPCRel;
- end if;
- elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
- if tSpOffset = 0 then
- tNextState := State_Shift;
- elsif tSpOffset = 1 then
- tNextState := State_AddTop;
- else
- tNextState :=State_AddSP;
- end if;
- else
- case tOpcode(3 downto 0) is
- when OpCode_Nop =>
- tNextState :=State_Nop;
- when OpCode_PushSP =>
- tNextState :=State_PushSP;
- when OpCode_PopPC =>
- tNextState :=State_PopPC;
- when OpCode_Add =>
- tNextState :=State_Add;
- when OpCode_Or =>
- tNextState :=State_Or;
- when OpCode_And =>
- tNextState :=State_And;
- when OpCode_Load =>
- tNextState :=State_Load;
- when OpCode_Not =>
- tNextState :=State_Not;
- when OpCode_Flip =>
- tNextState :=State_Flip;
- when OpCode_Store =>
- tNextState :=State_Store;
- when OpCode_PopSP =>
- tNextState :=State_PopSP;
- when others =>
- tNextState := State_Break;
-
- end case;
- end if;
- tDecodedOpcode(i) := tNextState;
-
- end loop;
-
- insn <= tDecodedOpcode(to_integer(pc(byteBits-1 downto 0)));
-
- -- once we wrap, we need to fetch
- tDecodedOpcode(0) := State_InsnFetch;
-
- decodedOpcode <= tDecodedOpcode;
- state <= State_Execute;
-
-
-
- -- Each instruction must:
- --
- -- 1. set idim_flag
- -- 2. increase pc if applicable
- -- 3. set next state if appliable
- -- 4. do it's operation
-
- when State_Execute =>
- insn <= decodedOpcode(to_integer(nextPC(byteBits-1 downto 0)));
-
- case insn is
- when State_InsnFetch =>
- state <= State_Fetch;
- when State_Im =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '1';
- pc <= pc + 1;
-
- if idim_flag='1' then
- stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
- stackA(6 downto 0) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(6 downto 0));
- else
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- stackB <= stackA;
- sp <= decSp;
- for i in wordSize-1 downto 7 loop
- stackA(i) <= opcode(to_integer(pc(byteBits-1 downto 0)))(6);
- end loop;
- stackA(6 downto 0) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(6 downto 0));
- end if;
- end if;
- when State_StoreSP =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_StoreSP2;
-
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(sp+spOffset);
- mem_write <= std_logic_vector(stackA);
- stackA <= stackB;
- sp <= incSp;
- end if;
-
-
- when State_LoadSP =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_LoadSP2;
-
- sp <= decSp;
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- end if;
- when State_Emulate =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- sp <= decSp;
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
- stackB <= stackA;
-
- -- The emulate address is:
- -- 98 7654 3210
- -- 0000 00aa aaa0 0000
- pc <= (others => '0');
- pc(9 downto 5) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(4 downto 0));
- state <= State_Fetch;
- end if;
- when State_Callpcrel =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
-
- pc <= pc + stackA(maxAddrBitIncIO downto 0);
- state <= State_Fetch;
- end if;
- when State_Call =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
- pc <= stackA(maxAddrBitIncIO downto 0);
- state <= State_Fetch;
- end if;
- when State_AddSP =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_AddSP2;
-
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(sp+spOffset);
- end if;
- when State_PushSP =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackA <= (others => '0');
- stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
- stackB <= stackA;
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- end if;
- when State_PopPC =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= stackA(maxAddrBitIncIO downto 0);
- sp <= incSp;
-
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- state <= State_Resync;
- end if;
- when State_PopPCRel =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= stackA(maxAddrBitIncIO downto 0) + pc;
- sp <= incSp;
-
- mem_writeEnable <= '1';
- mem_addr <= std_logic_vector(incSp);
- mem_write <= std_logic_vector(stackB);
- state <= State_Resync;
- end if;
- when State_Add =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= stackA + stackB;
-
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(incIncSp);
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_Sub =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- binaryOpResult <= stackB - stackA;
- state <= State_BinaryOpResult;
- end if;
- when State_Pop =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- mem_addr <= std_logic_vector(incIncSp);
- mem_readEnable <= '1';
- sp <= incSp;
- stackA <= stackB;
- state <= State_Popped;
- end if;
- when State_PopDown =>
- if in_mem_busy='0' then
- -- PopDown leaves top of stack unchanged
- begin_inst <= '1';
- idim_flag <= '0';
- mem_addr <= std_logic_vector(incIncSp);
- mem_readEnable <= '1';
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_Or =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= stackA or stackB;
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(incIncSp);
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_And =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- stackA <= stackA and stackB;
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(incIncSp);
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_Eq =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA=stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- end if;
- when State_Ulessthan =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA<stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- end if;
- when State_Ulessthanorequal =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA<=stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- end if;
- when State_Lessthan =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (signed(stackA)<signed(stackB)) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- end if;
- when State_Lessthanorequal =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (signed(stackA)<=signed(stackB)) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- end if;
- when State_Load =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Load2;
-
- mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- end if;
-
- when State_Dup =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackB <= stackA;
- mem_write <= std_logic_vector(stackB);
- mem_addr <= std_logic_vector(incSp);
- mem_writeEnable <= '1';
- end if;
- when State_DupStackB =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackA <= stackB;
- stackB <= stackA;
- mem_write <= std_logic_vector(stackB);
- mem_addr <= std_logic_vector(incSp);
- mem_writeEnable <= '1';
- end if;
- when State_Store =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
- mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
- mem_write <= std_logic_vector(stackB);
- mem_writeEnable <= '1';
- sp <= incIncSp;
- state <= State_Resync;
- end if;
- when State_PopSP =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- mem_write <= std_logic_vector(stackB);
- mem_addr <= std_logic_vector(incSp);
- mem_writeEnable <= '1';
- sp <= stackA(maxAddrBitIncIO downto minAddrBit);
- state <= State_Resync;
- end if;
- when State_Nop =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
- when State_Not =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= not stackA;
- when State_Flip =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- for i in 0 to wordSize-1 loop
- stackA(i) <= stackA(wordSize-1-i);
- end loop;
- when State_AddTop =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= stackA + stackB;
- when State_Shift =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
- stackA(0) <= '0';
- when State_Pushspadd =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= (others => '0');
- stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
- when State_Neqbranch =>
- -- branches are almost always taken as they form loops
- begin_inst <= '1';
- idim_flag <= '0';
- sp <= incIncSp;
- if (stackB/=0) then
- pc <= stackA(maxAddrBitIncIO downto 0) + pc;
- else
- pc <= pc + 1;
- end if;
- -- need to fetch stack again.
- state <= State_Resync;
- when State_Mult =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- multA <= stackA;
- multB <= stackB;
- state <= State_Mult2;
- when State_Break =>
- report "Break instruction encountered" severity failure;
- break <= '1';
-
- when State_Loadb =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Loadb2;
-
- mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- end if;
- when State_Storeb =>
- if in_mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Storeb2;
-
- mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- end if;
-
- when others =>
- sp <= (others => DontCareValue);
- report "Illegal instruction" severity failure;
- break <= '1';
- end case;
-
-
- when State_StoreSP2 =>
- if in_mem_busy='0' then
- mem_addr <= std_logic_vector(incSp);
- mem_readEnable <= '1';
- state <= State_Popped;
- end if;
- when State_LoadSP2 =>
- if in_mem_busy='0' then
- state <= State_LoadSP3;
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(sp+spOffset+1);
- end if;
- when State_LoadSP3 =>
- if in_mem_busy='0' then
- pc <= pc + 1;
- state <= State_Execute;
- stackB <= stackA;
- stackA <= unsigned(mem_read);
- end if;
- when State_AddSP2 =>
- if in_mem_busy='0' then
- pc <= pc + 1;
- state <= State_Execute;
- stackA <= stackA + unsigned(mem_read);
- end if;
- when State_Load2 =>
- if in_mem_busy='0' then
- stackA <= unsigned(mem_read);
- pc <= pc + 1;
- state <= State_Execute;
- end if;
- when State_Loadb2 =>
- if in_mem_busy='0' then
- stackA <= (others => '0');
- stackA(7 downto 0) <= unsigned(mem_read(((wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8));
- pc <= pc + 1;
- state <= State_Execute;
- end if;
- when State_Storeb2 =>
- if in_mem_busy='0' then
- mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
- mem_write <= mem_read;
- mem_write(((wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8) <= std_logic_vector(stackB(7 downto 0));
- mem_writeEnable <= '1';
- pc <= pc + 1;
- sp <= incIncSp;
- state <= State_Resync;
- end if;
- when State_Fetch =>
- if in_mem_busy='0' then
- mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
- mem_readEnable <= '1';
- state <= State_Decode;
- end if;
- when State_Mult2 =>
- state <= State_Mult3;
- when State_Mult3 =>
- state <= State_Mult4;
- when State_Mult4 =>
- state <= State_Mult5;
- when State_Mult5 =>
- if in_mem_busy='0' then
- stackA <= multResult3;
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(incIncSp);
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_BinaryOpResult =>
- state <= State_BinaryOpResult2;
- when State_BinaryOpResult2 =>
- mem_readEnable <= '1';
- mem_addr <= std_logic_vector(incIncSp);
- sp <= incSp;
- stackA <= binaryOpResult2;
- state <= State_Popped;
- when State_Popped =>
- if in_mem_busy='0' then
- pc <= pc + 1;
- stackB <= unsigned(mem_read);
- state <= State_Execute;
- end if;
- when others =>
- sp <= (others => DontCareValue);
- report "Illegal state" severity failure;
- break <= '1';
- end case;
- end if;
- end process;
+ traceFileGenerate :
+ if Generate_Trace generate
+ trace_file : trace port map (
+ clk => clk,
+ begin_inst => begin_inst,
+ pc => trace_pc,
+ opcode => trace_opcode,
+ sp => trace_sp,
+ memA => trace_topOfStack,
+ memB => trace_topOfStackB,
+ busy => busy,
+ intsp => (others => 'U')
+ );
+ end generate;
+
+
+ -- the memory subsystem will tell us one cycle later whether or
+ -- not it is busy
+ out_mem_writeEnable <= mem_writeEnable;
+ out_mem_readEnable <= mem_readEnable;
+ out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
+ out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
+
+ incSp <= sp + 1;
+ incIncSp <= sp + 2;
+ decSp <= sp - 1;
+
+
+ opcodeControl : process(clk, areset)
+ variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
+ variable spOffset : unsigned(4 downto 0);
+ variable tSpOffset : unsigned(4 downto 0);
+ variable nextPC : unsigned(maxAddrBitIncIO downto 0);
+ variable tNextState : InsnType;
+ variable tDecodedOpcode : InsnArray;
+ variable tMultResult : unsigned(wordSize*2-1 downto 0);
+ begin
+ if areset = '1' then
+ state <= State_Idle;
+ break <= '0';
+ sp <= unsigned(spStart(maxAddrBitIncIO downto minAddrBit));
+
+ pc <= (others => '0');
+ idim_flag <= '0';
+ begin_inst <= '0';
+ inInterrupt <= '0';
+ mem_writeEnable <= '0';
+ mem_readEnable <= '0';
+ multA <= (others => '0');
+ multB <= (others => '0');
+ mem_writeMask <= (others => '1');
+ elsif (clk'event and clk = '1') then
+ -- we must multiply unconditionally to get pipelined multiplication
+ tMultResult := multA * multB;
+ multResult3 <= multResult2;
+ multResult2 <= multResult;
+ multResult <= tMultResult(wordSize-1 downto 0);
+
+
+ binaryOpResult2 <= binaryOpResult; -- pipeline a bit.
+
+
+ multA <= (others => DontCareValue);
+ multB <= (others => DontCareValue);
+
+
+ mem_addr <= (others => DontCareValue);
+ mem_readEnable <= '0';
+ mem_writeEnable <= '0';
+ mem_write <= (others => DontCareValue);
+
+ if (mem_writeEnable = '1') and (mem_readEnable = '1') then
+ report "read/write collision" severity failure;
+ end if;
+
+
+
+
+ spOffset(4) := not opcode(to_integer(pc(byteBits-1 downto 0)))(4);
+ spOffset(3 downto 0) := unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(3 downto 0));
+ nextPC := pc + 1;
+
+ -- prepare trace snapshot
+ trace_opcode <= opcode(to_integer(pc(byteBits-1 downto 0)));
+ trace_pc <= std_logic_vector(pc);
+ trace_sp <= std_logic_vector(sp);
+ trace_topOfStack <= std_logic_vector(stackA);
+ trace_topOfStackB <= std_logic_vector(stackB);
+ begin_inst <= '0';
+
+ if (interrupt = '0') then
+ -- Interrupt ended, we can serve ISR again
+ inInterrupt <= '0';
+ end if;
+
+ case state is
+
+ when State_Idle =>
+ if enable = '1' then
+ state <= State_Resync;
+ end if;
+ -- Initial state of ZPU, fetch top of stack + first instruction
+
+ when State_Resync =>
+ if in_mem_busy = '0' then
+ mem_addr <= std_logic_vector(sp);
+ mem_readEnable <= '1';
+ state <= State_Resync2;
+ end if;
+
+ when State_Resync2 =>
+ if in_mem_busy = '0' then
+ stackA <= unsigned(mem_read);
+ mem_addr <= std_logic_vector(incSp);
+ mem_readEnable <= '1';
+ state <= State_Resync3;
+ end if;
+
+ when State_Resync3 =>
+ if in_mem_busy = '0' then
+ stackB <= unsigned(mem_read);
+ mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ state <= State_Decode;
+ end if;
+
+ when State_Decode =>
+ if in_mem_busy = '0' then
+ decodeWord <= mem_read;
+ state <= State_Decode2;
+ -- Do not recurse into ISR while interrupt line is active
+ if interrupt = '1' and inInterrupt = '0' and idim_flag = '0' then
+ -- We got an interrupt, execute interrupt instead of next instruction
+ inInterrupt <= '1';
+ sp <= decSp;
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc;
+ stackB <= stackA;
+ pc <= to_unsigned(32, maxAddrBitIncIO+1);
+ state <= State_Interrupt;
+ end if; -- interrupt
+ end if; -- in_mem_busy
+
+ when State_Interrupt =>
+ if in_mem_busy = '0' then
+ mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ state <= State_Decode;
+ report "ZPU jumped to interrupt!" severity note;
+ end if;
+
+ when State_Decode2 =>
+ -- decode 4 instructions in parallel
+ for i in 0 to wordBytes-1 loop
+ tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
+
+ tSpOffset(4) := not tOpcode(4);
+ tSpOffset(3 downto 0) := unsigned(tOpcode(3 downto 0));
+
+ opcode(i) <= tOpcode;
+ if (tOpcode(7 downto 7) = OpCode_Im) then
+ tNextState := State_Im;
+ elsif (tOpcode(7 downto 5) = OpCode_StoreSP) then
+ if tSpOffset = 0 then
+ tNextState := State_Pop;
+ elsif tSpOffset = 1 then
+ tNextState := State_PopDown;
+ else
+ tNextState := State_StoreSP;
+ end if;
+ elsif (tOpcode(7 downto 5) = OpCode_LoadSP) then
+ if tSpOffset = 0 then
+ tNextState := State_Dup;
+ elsif tSpOffset = 1 then
+ tNextState := State_DupStackB;
+ else
+ tNextState := State_LoadSP;
+ end if;
+ elsif (tOpcode(7 downto 5) = OpCode_Emulate) then
+ tNextState := State_Emulate;
+ if tOpcode(5 downto 0) = OpCode_Neqbranch then
+ tNextState := State_Neqbranch;
+ elsif tOpcode(5 downto 0) = OpCode_Eq then
+ tNextState := State_Eq;
+ elsif tOpcode(5 downto 0) = OpCode_Lessthan then
+ tNextState := State_Lessthan;
+ elsif tOpcode(5 downto 0) = OpCode_Lessthanorequal then
+ --tNextState :=State_Lessthanorequal;
+ elsif tOpcode(5 downto 0) = OpCode_Ulessthan then
+ tNextState := State_Ulessthan;
+ elsif tOpcode(5 downto 0) = OpCode_Ulessthanorequal then
+ --tNextState :=State_Ulessthanorequal;
+ elsif tOpcode(5 downto 0) = OpCode_Loadb then
+ tNextState := State_Loadb;
+ elsif tOpcode(5 downto 0) = OpCode_Mult then
+ tNextState := State_Mult;
+ elsif tOpcode(5 downto 0) = OpCode_Storeb then
+ tNextState := State_Storeb;
+ elsif tOpcode(5 downto 0) = OpCode_Pushspadd then
+ tNextState := State_Pushspadd;
+ elsif tOpcode(5 downto 0) = OpCode_Callpcrel then
+ tNextState := State_Callpcrel;
+ elsif tOpcode(5 downto 0) = OpCode_Call then
+ --tNextState :=State_Call;
+ elsif tOpcode(5 downto 0) = OpCode_Sub then
+ tNextState := State_Sub;
+ elsif tOpcode(5 downto 0) = OpCode_PopPCRel then
+ --tNextState :=State_PopPCRel;
+ end if;
+ elsif (tOpcode(7 downto 4) = OpCode_AddSP) then
+ if tSpOffset = 0 then
+ tNextState := State_Shift;
+ elsif tSpOffset = 1 then
+ tNextState := State_AddTop;
+ else
+ tNextState := State_AddSP;
+ end if;
+ else
+ case tOpcode(3 downto 0) is
+ when OpCode_Nop =>
+ tNextState := State_Nop;
+ when OpCode_PushSP =>
+ tNextState := State_PushSP;
+ when OpCode_PopPC =>
+ tNextState := State_PopPC;
+ when OpCode_Add =>
+ tNextState := State_Add;
+ when OpCode_Or =>
+ tNextState := State_Or;
+ when OpCode_And =>
+ tNextState := State_And;
+ when OpCode_Load =>
+ tNextState := State_Load;
+ when OpCode_Not =>
+ tNextState := State_Not;
+ when OpCode_Flip =>
+ tNextState := State_Flip;
+ when OpCode_Store =>
+ tNextState := State_Store;
+ when OpCode_PopSP =>
+ tNextState := State_PopSP;
+ when others =>
+ tNextState := State_Break;
+
+ end case; -- tOpcode(3 downto 0)
+ end if; -- tOpcode
+ tDecodedOpcode(i) := tNextState;
+
+ end loop; -- 0 to wordBytes-1
+
+ insn <= tDecodedOpcode(to_integer(pc(byteBits-1 downto 0)));
+
+ -- once we wrap, we need to fetch
+ tDecodedOpcode(0) := State_InsnFetch;
+
+ decodedOpcode <= tDecodedOpcode;
+ state <= State_Execute;
+
+
+
+ -- Each instruction must:
+ --
+ -- 1. set idim_flag
+ -- 2. increase pc if applicable
+ -- 3. set next state if appliable
+ -- 4. do it's operation
+
+ when State_Execute =>
+ insn <= decodedOpcode(to_integer(nextPC(byteBits-1 downto 0)));
+
+ case insn is
+
+ when State_InsnFetch =>
+ state <= State_Fetch;
+
+ when State_Im =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '1';
+ pc <= pc + 1;
+
+ if idim_flag = '1' then
+ stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
+ stackA(6 downto 0) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(6 downto 0));
+ else
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ stackB <= stackA;
+ sp <= decSp;
+ for i in wordSize-1 downto 7 loop
+ stackA(i) <= opcode(to_integer(pc(byteBits-1 downto 0)))(6);
+ end loop;
+ stackA(6 downto 0) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(6 downto 0));
+ end if; -- idim_flag
+ end if; -- in_mem_busy
+
+ when State_StoreSP =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_StoreSP2;
+
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(sp+spOffset);
+ mem_write <= std_logic_vector(stackA);
+ stackA <= stackB;
+ sp <= incSp;
+ end if;
+
+
+ when State_LoadSP =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_LoadSP2;
+
+ sp <= decSp;
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ end if;
+
+ when State_Emulate =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ sp <= decSp;
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+ stackB <= stackA;
+
+ -- The emulate address is:
+ -- 98 7654 3210
+ -- 0000 00aa aaa0 0000
+ pc <= (others => '0');
+ pc(9 downto 5) <= unsigned(opcode(to_integer(pc(byteBits-1 downto 0)))(4 downto 0));
+ state <= State_Fetch;
+ end if; -- in_mem_busy
+
+ when State_Callpcrel =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+
+ pc <= pc + stackA(maxAddrBitIncIO downto 0);
+ state <= State_Fetch;
+ end if;
+
+ when State_Call =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+ pc <= stackA(maxAddrBitIncIO downto 0);
+ state <= State_Fetch;
+ end if;
+
+ when State_AddSP =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_AddSP2;
+
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(sp+spOffset);
+ end if;
+
+ when State_PushSP =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackA <= (others => '0');
+ stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
+ stackB <= stackA;
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ end if;
+
+ when State_PopPC =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= stackA(maxAddrBitIncIO downto 0);
+ sp <= incSp;
+
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ state <= State_Resync;
+ end if;
+
+ when State_PopPCRel =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= stackA(maxAddrBitIncIO downto 0) + pc;
+ sp <= incSp;
+
+ mem_writeEnable <= '1';
+ mem_addr <= std_logic_vector(incSp);
+ mem_write <= std_logic_vector(stackB);
+ state <= State_Resync;
+ end if;
+
+ when State_Add =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= stackA + stackB;
+
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(incIncSp);
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+
+ when State_Sub =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ binaryOpResult <= stackB - stackA;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Pop =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ mem_addr <= std_logic_vector(incIncSp);
+ mem_readEnable <= '1';
+ sp <= incSp;
+ stackA <= stackB;
+ state <= State_Popped;
+ end if;
+
+ when State_PopDown =>
+ if in_mem_busy = '0' then
+ -- PopDown leaves top of stack unchanged
+ begin_inst <= '1';
+ idim_flag <= '0';
+ mem_addr <= std_logic_vector(incIncSp);
+ mem_readEnable <= '1';
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+
+ when State_Or =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= stackA or stackB;
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(incIncSp);
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+
+ when State_And =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ stackA <= stackA and stackB;
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(incIncSp);
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+
+ when State_Eq =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA = stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Ulessthan =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA < stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Ulessthanorequal =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA <= stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Lessthan =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (signed(stackA) < signed(stackB)) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Lessthanorequal =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (signed(stackA) <= signed(stackB)) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ end if;
+
+ when State_Load =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Load2;
+
+ mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ end if;
+
+ when State_Dup =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackB <= stackA;
+ mem_write <= std_logic_vector(stackB);
+ mem_addr <= std_logic_vector(incSp);
+ mem_writeEnable <= '1';
+ end if;
+
+ when State_DupStackB =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackA <= stackB;
+ stackB <= stackA;
+ mem_write <= std_logic_vector(stackB);
+ mem_addr <= std_logic_vector(incSp);
+ mem_writeEnable <= '1';
+ end if;
+
+ when State_Store =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+ mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
+ mem_write <= std_logic_vector(stackB);
+ mem_writeEnable <= '1';
+ sp <= incIncSp;
+ state <= State_Resync;
+ end if;
+
+ when State_PopSP =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ mem_write <= std_logic_vector(stackB);
+ mem_addr <= std_logic_vector(incSp);
+ mem_writeEnable <= '1';
+ sp <= stackA(maxAddrBitIncIO downto minAddrBit);
+ state <= State_Resync;
+ end if;
+
+ when State_Nop =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ when State_Not =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= not stackA;
+
+ when State_Flip =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ for i in 0 to wordSize-1 loop
+ stackA(i) <= stackA(wordSize-1-i);
+ end loop;
+
+ when State_AddTop =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= stackA + stackB;
+
+ when State_Shift =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
+ stackA(0) <= '0';
+
+ when State_Pushspadd =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= (others => '0');
+ stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
+
+ when State_Neqbranch =>
+ -- branches are almost always taken as they form loops
+ begin_inst <= '1';
+ idim_flag <= '0';
+ sp <= incIncSp;
+ if (stackB /= 0) then
+ pc <= stackA(maxAddrBitIncIO downto 0) + pc;
+ else
+ pc <= pc + 1;
+ end if;
+ -- need to fetch stack again.
+ state <= State_Resync;
+
+ when State_Mult =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ multA <= stackA;
+ multB <= stackB;
+ state <= State_Mult2;
+
+ when State_Break =>
+ report "Break instruction encountered" severity failure;
+ break <= '1';
+
+ when State_Loadb =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Loadb2;
+
+ mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ end if;
+
+ when State_Storeb =>
+ if in_mem_busy = '0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Storeb2;
+
+ mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ end if;
+
+ when others =>
+ sp <= (others => DontCareValue);
+ report "Illegal instruction" severity failure;
+ break <= '1';
+
+ end case; -- insn/State_Execute
+
+
+ when State_StoreSP2 =>
+ if in_mem_busy = '0' then
+ mem_addr <= std_logic_vector(incSp);
+ mem_readEnable <= '1';
+ state <= State_Popped;
+ end if;
+
+ when State_LoadSP2 =>
+ if in_mem_busy = '0' then
+ state <= State_LoadSP3;
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(sp+spOffset+1);
+ end if;
+
+ when State_LoadSP3 =>
+ if in_mem_busy = '0' then
+ pc <= pc + 1;
+ state <= State_Execute;
+ stackB <= stackA;
+ stackA <= unsigned(mem_read);
+ end if;
+
+ when State_AddSP2 =>
+ if in_mem_busy = '0' then
+ pc <= pc + 1;
+ state <= State_Execute;
+ stackA <= stackA + unsigned(mem_read);
+ end if;
+
+ when State_Load2 =>
+ if in_mem_busy = '0' then
+ stackA <= unsigned(mem_read);
+ pc <= pc + 1;
+ state <= State_Execute;
+ end if;
+
+ when State_Loadb2 =>
+ if in_mem_busy = '0' then
+ stackA <= (others => '0');
+ stackA(7 downto 0) <= unsigned(mem_read(((wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8));
+ pc <= pc + 1;
+ state <= State_Execute;
+ end if;
+
+ when State_Storeb2 =>
+ if in_mem_busy = '0' then
+ mem_addr <= std_logic_vector(stackA(maxAddrBitIncIO downto minAddrBit));
+ mem_write <= mem_read;
+ mem_write(((wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-to_integer(stackA(byteBits-1 downto 0)))*8) <= std_logic_vector(stackB(7 downto 0));
+ mem_writeEnable <= '1';
+ pc <= pc + 1;
+ sp <= incIncSp;
+ state <= State_Resync;
+ end if;
+
+ when State_Fetch =>
+ if in_mem_busy = '0' then
+ mem_addr <= std_logic_vector(pc(maxAddrBitIncIO downto minAddrBit));
+ mem_readEnable <= '1';
+ state <= State_Decode;
+ end if;
+
+ when State_Mult2 =>
+ state <= State_Mult3;
+
+ when State_Mult3 =>
+ state <= State_Mult4;
+
+ when State_Mult4 =>
+ state <= State_Mult5;
+
+ when State_Mult5 =>
+ if in_mem_busy = '0' then
+ stackA <= multResult3;
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(incIncSp);
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+
+ when State_BinaryOpResult =>
+ state <= State_BinaryOpResult2;
+
+ when State_BinaryOpResult2 =>
+ mem_readEnable <= '1';
+ mem_addr <= std_logic_vector(incIncSp);
+ sp <= incSp;
+ stackA <= binaryOpResult2;
+ state <= State_Popped;
+
+ when State_Popped =>
+ if in_mem_busy = '0' then
+ pc <= pc + 1;
+ stackB <= unsigned(mem_read);
+ state <= State_Execute;
+ end if;
+
+ when others =>
+ sp <= (others => DontCareValue);
+ report "Illegal state" severity failure;
+ break <= '1';
+
+ end case; -- state
+ end if; -- clk'event
+ end process;
diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd
index 681fb09..1df9546 100644
--- a/zpu/hdl/zpu4/core/zpu_core_small.vhd
+++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd
@@ -32,8 +32,8 @@
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
-library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
+library ieee;
+use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
@@ -42,531 +42,560 @@ use work.zpupkg.all;
entity zpu_core is
- Port ( clk : in std_logic;
- -- asynchronous reset signal
- areset : in std_logic;
- -- this particular implementation of the ZPU does not
- -- have a clocked enable signal
- enable : in std_logic;
- in_mem_busy : in std_logic;
- mem_read : in std_logic_vector(wordSize-1 downto 0);
- mem_write : out std_logic_vector(wordSize-1 downto 0);
- out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
- out_mem_writeEnable : out std_logic;
- out_mem_readEnable : out std_logic;
- -- this implementation of the ZPU *always* reads and writes entire
- -- 32 bit words, so mem_writeMask is tied to (others => '1').
- mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
- -- Set to one to jump to interrupt vector
- -- The ZPU will communicate with the hardware that caused the
- -- interrupt via memory mapped IO or the interrupt flag can
- -- be cleared automatically
- interrupt : in std_logic;
- -- Signal that the break instruction is executed, normally only used
- -- in simulation to stop simulation
- break : out std_logic);
+ port (
+ clk : in std_logic;
+ -- asynchronous reset signal
+ areset : in std_logic;
+ -- this particular implementation of the ZPU does not
+ -- have a clocked enable signal
+ enable : in std_logic;
+ in_mem_busy : in std_logic;
+ mem_read : in std_logic_vector(wordSize-1 downto 0);
+ mem_write : out std_logic_vector(wordSize-1 downto 0);
+ out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
+ out_mem_writeEnable : out std_logic;
+ out_mem_readEnable : out std_logic;
+ -- this implementation of the ZPU *always* reads and writes entire
+ -- 32 bit words, so mem_writeMask is tied to (others => '1').
+ mem_writeMask : out std_logic_vector(wordBytes-1 downto 0);
+ -- Set to one to jump to interrupt vector
+ -- The ZPU will communicate with the hardware that caused the
+ -- interrupt via memory mapped IO or the interrupt flag can
+ -- be cleared automatically
+ interrupt : in std_logic;
+ -- Signal that the break instruction is executed, normally only used
+ -- in simulation to stop simulation
+ break : out std_logic
+ );
end zpu_core;
-architecture behave of zpu_core is
-signal readIO : std_logic;
-
-
-signal memAWriteEnable : std_logic;
-signal memAAddr : unsigned(maxAddrBit downto minAddrBit);
-signal memAWrite : unsigned(wordSize-1 downto 0);
-signal memARead : unsigned(wordSize-1 downto 0);
-signal memBWriteEnable : std_logic;
-signal memBAddr : unsigned(maxAddrBit downto minAddrBit);
-signal memBWrite : unsigned(wordSize-1 downto 0);
-signal memBRead : unsigned(wordSize-1 downto 0);
-
-
-
-signal pc : unsigned(maxAddrBit downto 0);
-signal sp : unsigned(maxAddrBit downto minAddrBit);
-
--- this signal is set upon executing an IM instruction
--- the subsequence IM instruction will then behave differently.
--- all other instructions will clear the idim_flag.
--- this yields highly compact immediate instructions.
-signal idim_flag : std_logic;
-
-signal busy : std_logic;
-
-signal begin_inst : std_logic;
-
-
-
-signal trace_opcode : std_logic_vector(7 downto 0);
-signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
-signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
-signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
-
--- state machine.
-type State_Type is
-(
-State_Fetch,
-State_WriteIODone,
-State_Execute,
-State_StoreToStack,
-State_Add,
-State_Or,
-State_And,
-State_Store,
-State_ReadIO,
-State_WriteIO,
-State_Load,
-State_FetchNext,
-State_AddSP,
-State_ReadIODone,
-State_Decode,
-State_Resync,
-State_Interrupt
-
-);
-
-type DecodedOpcodeType is
-(
-Decoded_Nop,
-Decoded_Im,
-Decoded_ImShift,
-Decoded_LoadSP,
-Decoded_StoreSP ,
-Decoded_AddSP,
-Decoded_Emulate,
-Decoded_Break,
-Decoded_PushSP,
-Decoded_PopPC,
-Decoded_Add,
-Decoded_Or,
-Decoded_And,
-Decoded_Load,
-Decoded_Not,
-Decoded_Flip,
-Decoded_Store,
-Decoded_PopSP,
-Decoded_Interrupt
-);
-
-
-
-signal sampledOpcode : std_logic_vector(OpCode_Size-1 downto 0);
-signal opcode : std_logic_vector(OpCode_Size-1 downto 0);
-
-signal decodedOpcode : DecodedOpcodeType;
-signal sampledDecodedOpcode : DecodedOpcodeType;
-
-
-signal state : State_Type;
-
-subtype AddrBitBRAM_range is natural range maxAddrBitBRAM downto minAddrBit;
-signal memAAddr_stdlogic : std_logic_vector(AddrBitBRAM_range);
-signal memAWrite_stdlogic : std_logic_vector(memAWrite'range);
-signal memARead_stdlogic : std_logic_vector(memARead'range);
-signal memBAddr_stdlogic : std_logic_vector(AddrBitBRAM_range);
-signal memBWrite_stdlogic : std_logic_vector(memBWrite'range);
-signal memBRead_stdlogic : std_logic_vector(memBRead'range);
-
-subtype index is integer range 0 to 3;
-
-signal tOpcode_sel : index;
-
-
-signal inInterrupt : std_logic;
+architecture behave of zpu_core is
+
+ signal memAWriteEnable : std_logic;
+ signal memAAddr : unsigned(maxAddrBit downto minAddrBit);
+ signal memAWrite : unsigned(wordSize-1 downto 0);
+ signal memARead : unsigned(wordSize-1 downto 0);
+ signal memBWriteEnable : std_logic;
+ signal memBAddr : unsigned(maxAddrBit downto minAddrBit);
+ signal memBWrite : unsigned(wordSize-1 downto 0);
+ signal memBRead : unsigned(wordSize-1 downto 0);
+
+
+
+ signal pc : unsigned(maxAddrBit downto 0);
+ signal sp : unsigned(maxAddrBit downto minAddrBit);
+
+ -- this signal is set upon executing an IM instruction
+ -- the subsequence IM instruction will then behave differently.
+ -- all other instructions will clear the idim_flag.
+ -- this yields highly compact immediate instructions.
+ signal idim_flag : std_logic;
+ --
+ signal busy : std_logic;
+ --
+ signal begin_inst : std_logic;
+
+
+ signal trace_opcode : std_logic_vector(7 downto 0);
+ signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
+ signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
+ signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
+
+ -- state machine.
+ type State_Type is (
+ State_Fetch,
+ State_WriteIODone,
+ State_Execute,
+ State_StoreToStack,
+ State_Add,
+ State_Or,
+ State_And,
+ State_Store,
+ State_ReadIO,
+ State_WriteIO,
+ State_Load,
+ State_FetchNext,
+ State_AddSP,
+ State_ReadIODone,
+ State_Decode,
+ State_Resync,
+ State_Interrupt
+ );
+
+ type DecodedOpcodeType is (
+ Decoded_Nop,
+ Decoded_Im,
+ Decoded_ImShift,
+ Decoded_LoadSP,
+ Decoded_StoreSP ,
+ Decoded_AddSP,
+ Decoded_Emulate,
+ Decoded_Break,
+ Decoded_PushSP,
+ Decoded_PopPC,
+ Decoded_Add,
+ Decoded_Or,
+ Decoded_And,
+ Decoded_Load,
+ Decoded_Not,
+ Decoded_Flip,
+ Decoded_Store,
+ Decoded_PopSP,
+ Decoded_Interrupt
+ );
+
+
+
+ signal sampledOpcode : std_logic_vector(OpCode_Size-1 downto 0);
+ signal opcode : std_logic_vector(OpCode_Size-1 downto 0);
+ --
+ signal decodedOpcode : DecodedOpcodeType;
+ signal sampledDecodedOpcode : DecodedOpcodeType;
+
+
+ signal state : State_Type;
+ --
+ subtype AddrBitBRAM_range is natural range maxAddrBitBRAM downto minAddrBit;
+ signal memAAddr_stdlogic : std_logic_vector(AddrBitBRAM_range);
+ signal memAWrite_stdlogic : std_logic_vector(memAWrite'range);
+ signal memARead_stdlogic : std_logic_vector(memARead'range);
+ signal memBAddr_stdlogic : std_logic_vector(AddrBitBRAM_range);
+ signal memBWrite_stdlogic : std_logic_vector(memBWrite'range);
+ signal memBRead_stdlogic : std_logic_vector(memBRead'range);
+ --
+ subtype index is integer range 0 to 3;
+ --
+ signal tOpcode_sel : index;
+ --
+ signal inInterrupt : std_logic;
begin
- -- generate a trace file.
- --
- -- This is only used in simulation to see what instructions are
- -- executed.
- --
- -- a quick & dirty regression test is then to commit trace files
- -- to CVS and compare the latest trace file against the last known
- -- good trace file
- traceFileGenerate:
- if Generate_Trace generate
- trace_file: trace port map (
- clk => clk,
- begin_inst => begin_inst,
- pc => trace_pc,
- opcode => trace_opcode,
- sp => trace_sp,
- memA => trace_topOfStack,
- memB => trace_topOfStackB,
- busy => busy,
- intsp => (others => 'U')
- );
- end generate;
-
-
-
- -- mem_writeMask is not used in this design, tie it to 1
- mem_writeMask <= (others => '1');
-
-
-
- memAAddr_stdlogic <= std_logic_vector(memAAddr(AddrBitBRAM_range));
- memAWrite_stdlogic <= std_logic_vector(memAWrite);
- memBAddr_stdlogic <= std_logic_vector(memBAddr(AddrBitBRAM_range));
- memBWrite_stdlogic <= std_logic_vector(memBWrite);
-
-
- -- dualport_ram must be defined by the application.
- --
- -- How this can be implemented is highly dependent on the FPGA
- -- and synthesis technology used.
- --
- -- sometimes it can be instantiated as in the
- -- zpu/example/helloworld.vhd, using inference,
- -- but oftentimes it must be instantiated directly
- -- portmapping to part specific FPGA resources
- --
- --
- -- DANGER!!!!!! If inference fails, then synthesis will try
- -- to implement the memory using basic logic resources. This
- -- will almost certainly cause the compiler to get "stuck"
- -- since synthesising such a huge number of basic logic resources
- -- will take more or less forever.
- --
- -- So: if your compiler gets "stuck" then inference is not
- -- the way to go.
- memory: dualport_ram port map (
- clk => clk,
- memAWriteEnable => memAWriteEnable,
- memAAddr => memAAddr_stdlogic,
- memAWrite => memAWrite_stdlogic,
- memARead => memARead_stdlogic,
- memBWriteEnable => memBWriteEnable,
- memBAddr => memBAddr_stdlogic,
- memBWrite => memBWrite_stdlogic,
- memBRead => memBRead_stdlogic
- );
- memARead <= unsigned(memARead_stdlogic);
- memBRead <= unsigned(memBRead_stdlogic);
-
-
-
- tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0));
-
-
-
- -- move out calculation of the opcode to a seperate process
- -- to make things a bit easier to read
- decodeControl:
- process(memBRead, pc,tOpcode_sel)
- variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
- begin
-
- -- simplify opcode selection a bit so it passes more synthesizers
- case (tOpcode_sel) is
-
- when 0 => tOpcode := std_logic_vector(memBRead(31 downto 24));
-
- when 1 => tOpcode := std_logic_vector(memBRead(23 downto 16));
-
- when 2 => tOpcode := std_logic_vector(memBRead(15 downto 8));
-
- when 3 => tOpcode := std_logic_vector(memBRead(7 downto 0));
-
- when others => tOpcode := std_logic_vector(memBRead(7 downto 0));
- end case;
-
- sampledOpcode <= tOpcode;
-
- if (tOpcode(7 downto 7)=OpCode_Im) then
- sampledDecodedOpcode<=Decoded_Im;
- elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
- sampledDecodedOpcode<=Decoded_StoreSP;
- elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
- sampledDecodedOpcode<=Decoded_LoadSP;
- elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
- sampledDecodedOpcode<=Decoded_Emulate;
- elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
- sampledDecodedOpcode<=Decoded_AddSP;
- else
- case tOpcode(3 downto 0) is
- when OpCode_Break =>
- sampledDecodedOpcode<=Decoded_Break;
- when OpCode_PushSP =>
- sampledDecodedOpcode<=Decoded_PushSP;
- when OpCode_PopPC =>
- sampledDecodedOpcode<=Decoded_PopPC;
- when OpCode_Add =>
- sampledDecodedOpcode<=Decoded_Add;
- when OpCode_Or =>
- sampledDecodedOpcode<=Decoded_Or;
- when OpCode_And =>
- sampledDecodedOpcode<=Decoded_And;
- when OpCode_Load =>
- sampledDecodedOpcode<=Decoded_Load;
- when OpCode_Not =>
- sampledDecodedOpcode<=Decoded_Not;
- when OpCode_Flip =>
- sampledDecodedOpcode<=Decoded_Flip;
- when OpCode_Store =>
- sampledDecodedOpcode<=Decoded_Store;
- when OpCode_PopSP =>
- sampledDecodedOpcode<=Decoded_PopSP;
- when others =>
- sampledDecodedOpcode<=Decoded_Nop;
- end case;
- end if;
- end process;
-
-
- opcodeControl:
- process(clk, areset)
- variable spOffset : unsigned(4 downto 0);
- begin
- if areset = '1' then
- state <= State_Resync;
- break <= '0';
- sp <= unsigned(spStart(maxAddrBit downto minAddrBit));
- pc <= (others => '0');
- idim_flag <= '0';
- begin_inst <= '0';
- memAAddr <= (others => '0');
- memBAddr <= (others => '0');
- memAWriteEnable <= '0';
- memBWriteEnable <= '0';
- out_mem_writeEnable <= '0';
- out_mem_readEnable <= '0';
- memAWrite <= (others => '0');
- memBWrite <= (others => '0');
- inInterrupt <= '0';
- elsif (clk'event and clk = '1') then
- memAWriteEnable <= '0';
- memBWriteEnable <= '0';
- -- This saves ca. 100 LUT's, by explicitly declaring that the
- -- memAWrite can be left at whatever value if memAWriteEnable is
- -- not set.
- memAWrite <= (others => DontCareValue);
- memBWrite <= (others => DontCareValue);
--- out_mem_addr <= (others => DontCareValue);
--- mem_write <= (others => DontCareValue);
- spOffset := (others => DontCareValue);
- memAAddr <= (others => DontCareValue);
- memBAddr <= (others => DontCareValue);
-
- out_mem_writeEnable <= '0';
- out_mem_readEnable <= '0';
- begin_inst <= '0';
- out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
- mem_write <= std_logic_vector(memBRead);
-
- decodedOpcode <= sampledDecodedOpcode;
- opcode <= sampledOpcode;
- if interrupt='0' then
- inInterrupt <= '0'; -- no longer in an interrupt
- end if;
-
- case state is
- when State_Execute =>
- state <= State_Fetch;
- -- at this point:
- -- memBRead contains opcode word
- -- memARead contains top of stack
- pc <= pc + 1;
-
- -- trace
- begin_inst <= '1';
- trace_pc <= (others => '0');
- trace_pc(maxAddrBit downto 0) <= std_logic_vector(pc);
- trace_opcode <= opcode;
- trace_sp <= (others => '0');
- trace_sp(maxAddrBit downto minAddrBit) <= std_logic_vector(sp);
- trace_topOfStack <= std_logic_vector(memARead);
- trace_topOfStackB <= std_logic_vector(memBRead);
-
- -- during the next cycle we'll be reading the next opcode
- spOffset(4):=not opcode(4);
- spOffset(3 downto 0) := unsigned(opcode(3 downto 0));
-
- idim_flag <= '0';
- case decodedOpcode is
- when Decoded_Interrupt =>
- sp <= sp - 1;
- memAAddr <= sp - 1;
- memAWriteEnable <= '1';
- memAWrite <= (others => DontCareValue);
- memAWrite(maxAddrBit downto 0) <= pc;
- pc <= to_unsigned(32, maxAddrBit+1); -- interrupt address
- report "ZPU jumped to interrupt!" severity note;
- when Decoded_Im =>
- idim_flag <= '1';
- memAWriteEnable <= '1';
- if (idim_flag='0') then
- sp <= sp - 1;
- memAAddr <= sp-1;
- for i in wordSize-1 downto 7 loop
- memAWrite(i) <= opcode(6);
- end loop;
- memAWrite(6 downto 0) <= unsigned(opcode(6 downto 0));
- else
- memAAddr <= sp;
- memAWrite(wordSize-1 downto 7) <= memARead(wordSize-8 downto 0);
- memAWrite(6 downto 0) <= unsigned(opcode(6 downto 0));
- end if;
- when Decoded_StoreSP =>
- memBWriteEnable <= '1';
- memBAddr <= sp+spOffset;
- memBWrite <= memARead;
- sp <= sp + 1;
- state <= State_Resync;
- when Decoded_LoadSP =>
- sp <= sp - 1;
- memAAddr <= sp+spOffset;
- when Decoded_Emulate =>
- sp <= sp - 1;
- memAWriteEnable <= '1';
- memAAddr <= sp - 1;
- memAWrite <= (others => DontCareValue);
- memAWrite(maxAddrBit downto 0) <= pc + 1;
- -- The emulate address is:
- -- 98 7654 3210
- -- 0000 00aa aaa0 0000
- pc <= (others => '0');
- pc(9 downto 5) <= unsigned(opcode(4 downto 0));
- when Decoded_AddSP =>
- memAAddr <= sp;
- memBAddr <= sp+spOffset;
- state <= State_AddSP;
- when Decoded_Break =>
- report "Break instruction encountered" severity failure;
- break <= '1';
- when Decoded_PushSP =>
- memAWriteEnable <= '1';
- memAAddr <= sp - 1;
- sp <= sp - 1;
- memAWrite <= (others => DontCareValue);
- memAWrite(maxAddrBit downto minAddrBit) <= sp;
- when Decoded_PopPC =>
- pc <= memARead(maxAddrBit downto 0);
- sp <= sp + 1;
- state <= State_Resync;
- when Decoded_Add =>
- sp <= sp + 1;
- state <= State_Add;
- when Decoded_Or =>
- sp <= sp + 1;
- state <= State_Or;
- when Decoded_And =>
- sp <= sp + 1;
- state <= State_And;
- when Decoded_Load =>
- if (memARead(ioBit)='1') then
- out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
- out_mem_readEnable <= '1';
- state <= State_ReadIO;
- else
- memAAddr <= memARead(maxAddrBit downto minAddrBit);
- end if;
- when Decoded_Not =>
- memAAddr <= sp(maxAddrBit downto minAddrBit);
- memAWriteEnable <= '1';
- memAWrite <= not memARead;
- when Decoded_Flip =>
- memAAddr <= sp(maxAddrBit downto minAddrBit);
- memAWriteEnable <= '1';
- for i in 0 to wordSize-1 loop
- memAWrite(i) <= memARead(wordSize-1-i);
- end loop;
- when Decoded_Store =>
- memBAddr <= sp + 1;
- sp <= sp + 1;
- if (memARead(ioBit)='1') then
- state <= State_WriteIO;
- else
- state <= State_Store;
- end if;
- when Decoded_PopSP =>
- sp <= memARead(maxAddrBit downto minAddrBit);
- state <= State_Resync;
- when Decoded_Nop =>
- memAAddr <= sp;
- when others =>
- null;
- end case;
- when State_ReadIO =>
- memAAddr <= sp;
- if (in_mem_busy = '0') then
- state <= State_Fetch;
- memAWriteEnable <= '1';
- memAWrite <= unsigned(mem_read);
- end if;
- when State_WriteIO =>
- sp <= sp + 1;
- out_mem_writeEnable <= '1';
- out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
- mem_write <= std_logic_vector(memBRead);
- state <= State_WriteIODone;
- when State_WriteIODone =>
- if (in_mem_busy = '0') then
- state <= State_Resync;
- end if;
- when State_Fetch =>
- -- We need to resync. During the *next* cycle
- -- we'll fetch the opcode @ pc and thus it will
- -- be available for State_Execute the cycle after
- -- next
- memBAddr <= pc(maxAddrBit downto minAddrBit);
- state <= State_FetchNext;
- when State_FetchNext =>
- -- at this point memARead contains the value that is either
- -- from the top of stack or should be copied to the top of the stack
- memAWriteEnable <= '1';
- memAWrite <= memARead;
- memAAddr <= sp;
- memBAddr <= sp + 1;
- state <= State_Decode;
- when State_Decode =>
- if interrupt='1' and inInterrupt='0' and idim_flag='0' then
- -- We got an interrupt, execute interrupt instead of next instruction
- inInterrupt <= '1';
- decodedOpcode <= Decoded_Interrupt;
- end if;
- -- during the State_Execute cycle we'll be fetching SP+1
- memAAddr <= sp;
- memBAddr <= sp + 1;
- state <= State_Execute;
- when State_Store =>
- sp <= sp + 1;
- memAWriteEnable <= '1';
- memAAddr <= memARead(maxAddrBit downto minAddrBit);
- memAWrite <= memBRead;
- state <= State_Resync;
- when State_AddSP =>
- state <= State_Add;
- when State_Add =>
- memAAddr <= sp;
- memAWriteEnable <= '1';
- memAWrite <= memARead + memBRead;
- state <= State_Fetch;
- when State_Or =>
- memAAddr <= sp;
- memAWriteEnable <= '1';
- memAWrite <= memARead or memBRead;
- state <= State_Fetch;
- when State_Resync =>
- memAAddr <= sp;
- state <= State_Fetch;
- when State_And =>
- memAAddr <= sp;
- memAWriteEnable <= '1';
- memAWrite <= memARead and memBRead;
- state <= State_Fetch;
- when others =>
- null;
- end case;
-
- end if;
- end process;
+ -- generate a trace file.
+ --
+ -- This is only used in simulation to see what instructions are
+ -- executed.
+ --
+ -- a quick & dirty regression test is then to commit trace files
+ -- to CVS and compare the latest trace file against the last known
+ -- good trace file
+ traceFileGenerate : if Generate_Trace generate
+ trace_file : trace port map (
+ clk => clk,
+ begin_inst => begin_inst,
+ pc => trace_pc,
+ opcode => trace_opcode,
+ sp => trace_sp,
+ memA => trace_topOfStack,
+ memB => trace_topOfStackB,
+ busy => busy,
+ intsp => (others => 'U')
+ );
+ end generate;
+
+
+ -- mem_writeMask is not used in this design, tie it to 1
+ mem_writeMask <= (others => '1');
+
+
+
+ memAAddr_stdlogic <= std_logic_vector(memAAddr(AddrBitBRAM_range));
+ memAWrite_stdlogic <= std_logic_vector(memAWrite);
+ memBAddr_stdlogic <= std_logic_vector(memBAddr(AddrBitBRAM_range));
+ memBWrite_stdlogic <= std_logic_vector(memBWrite);
+
+
+ -- dualport_ram must be defined by the application.
+ --
+ -- How this can be implemented is highly dependent on the FPGA
+ -- and synthesis technology used.
+ --
+ -- sometimes it can be instantiated as in the
+ -- zpu/example/helloworld.vhd, using inference,
+ -- but oftentimes it must be instantiated directly
+ -- portmapping to part specific FPGA resources
+ --
+ --
+ -- DANGER!!!!!! If inference fails, then synthesis will try
+ -- to implement the memory using basic logic resources. This
+ -- will almost certainly cause the compiler to get "stuck"
+ -- since synthesising such a huge number of basic logic resources
+ -- will take more or less forever.
+ --
+ -- So: if your compiler gets "stuck" then inference is not
+ -- the way to go.
+ memory : dualport_ram port map (
+ clk => clk,
+ memAWriteEnable => memAWriteEnable,
+ memAAddr => memAAddr_stdlogic,
+ memAWrite => memAWrite_stdlogic,
+ memARead => memARead_stdlogic,
+ memBWriteEnable => memBWriteEnable,
+ memBAddr => memBAddr_stdlogic,
+ memBWrite => memBWrite_stdlogic,
+ memBRead => memBRead_stdlogic
+ );
+ memARead <= unsigned(memARead_stdlogic);
+ memBRead <= unsigned(memBRead_stdlogic);
+
+
+
+ tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0));
+
+
+
+ -- move out calculation of the opcode to a seperate process
+ -- to make things a bit easier to read
+ decodeControl : process(memBRead, pc, tOpcode_sel)
+ variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
+ begin
+
+ -- simplify opcode selection a bit so it passes more synthesizers
+ case (tOpcode_sel) is
+
+ when 0 => tOpcode := std_logic_vector(memBRead(31 downto 24));
+
+ when 1 => tOpcode := std_logic_vector(memBRead(23 downto 16));
+
+ when 2 => tOpcode := std_logic_vector(memBRead(15 downto 8));
+
+ when 3 => tOpcode := std_logic_vector(memBRead(7 downto 0));
+
+ when others => tOpcode := std_logic_vector(memBRead(7 downto 0));
+ end case;
+
+ sampledOpcode <= tOpcode;
+
+ if (tOpcode(7 downto 7) = OpCode_Im) then
+ sampledDecodedOpcode <= Decoded_Im;
+ elsif (tOpcode(7 downto 5) = OpCode_StoreSP) then
+ sampledDecodedOpcode <= Decoded_StoreSP;
+ elsif (tOpcode(7 downto 5) = OpCode_LoadSP) then
+ sampledDecodedOpcode <= Decoded_LoadSP;
+ elsif (tOpcode(7 downto 5) = OpCode_Emulate) then
+ sampledDecodedOpcode <= Decoded_Emulate;
+ elsif (tOpcode(7 downto 4) = OpCode_AddSP) then
+ sampledDecodedOpcode <= Decoded_AddSP;
+ else
+ case tOpcode(3 downto 0) is
+ when OpCode_Break =>
+ sampledDecodedOpcode <= Decoded_Break;
+ when OpCode_PushSP =>
+ sampledDecodedOpcode <= Decoded_PushSP;
+ when OpCode_PopPC =>
+ sampledDecodedOpcode <= Decoded_PopPC;
+ when OpCode_Add =>
+ sampledDecodedOpcode <= Decoded_Add;
+ when OpCode_Or =>
+ sampledDecodedOpcode <= Decoded_Or;
+ when OpCode_And =>
+ sampledDecodedOpcode <= Decoded_And;
+ when OpCode_Load =>
+ sampledDecodedOpcode <= Decoded_Load;
+ when OpCode_Not =>
+ sampledDecodedOpcode <= Decoded_Not;
+ when OpCode_Flip =>
+ sampledDecodedOpcode <= Decoded_Flip;
+ when OpCode_Store =>
+ sampledDecodedOpcode <= Decoded_Store;
+ when OpCode_PopSP =>
+ sampledDecodedOpcode <= Decoded_PopSP;
+ when others =>
+ sampledDecodedOpcode <= Decoded_Nop;
+ end case; -- tOpcode(3 downto 0)
+ end if; tOpcode
+ end process;
+
+
+ opcodeControl: process(clk, areset)
+ variable spOffset : unsigned(4 downto 0);
+ begin
+
+ if areset = '1' then
+ state <= State_Resync;
+ break <= '0';
+ sp <= unsigned(spStart(maxAddrBit downto minAddrBit));
+ pc <= (others => '0');
+ idim_flag <= '0';
+ begin_inst <= '0';
+ memAAddr <= (others => '0');
+ memBAddr <= (others => '0');
+ memAWriteEnable <= '0';
+ memBWriteEnable <= '0';
+ out_mem_writeEnable <= '0';
+ out_mem_readEnable <= '0';
+ memAWrite <= (others => '0');
+ memBWrite <= (others => '0');
+ inInterrupt <= '0';
+
+ elsif (clk'event and clk = '1') then
+ memAWriteEnable <= '0';
+ memBWriteEnable <= '0';
+ -- This saves ca. 100 LUT's, by explicitly declaring that the
+ -- memAWrite can be left at whatever value if memAWriteEnable is
+ -- not set.
+ memAWrite <= (others => DontCareValue);
+ memBWrite <= (others => DontCareValue);
+-- out_mem_addr <= (others => DontCareValue);
+-- mem_write <= (others => DontCareValue);
+ spOffset := (others => DontCareValue);
+ memAAddr <= (others => DontCareValue);
+ memBAddr <= (others => DontCareValue);
+
+ out_mem_writeEnable <= '0';
+ out_mem_readEnable <= '0';
+ begin_inst <= '0';
+ out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
+ mem_write <= std_logic_vector(memBRead);
+
+ decodedOpcode <= sampledDecodedOpcode;
+ opcode <= sampledOpcode;
+ if interrupt = '0' then
+ inInterrupt <= '0'; -- no longer in an interrupt
+ end if;
+
+ case state is
+
+ when State_Execute =>
+ state <= State_Fetch;
+ -- at this point:
+ -- memBRead contains opcode word
+ -- memARead contains top of stack
+ pc <= pc + 1;
+
+ -- trace
+ begin_inst <= '1';
+ trace_pc <= (others => '0');
+ trace_pc(maxAddrBit downto 0) <= std_logic_vector(pc);
+ trace_opcode <= opcode;
+ trace_sp <= (others => '0');
+ trace_sp(maxAddrBit downto minAddrBit) <= std_logic_vector(sp);
+ trace_topOfStack <= std_logic_vector(memARead);
+ trace_topOfStackB <= std_logic_vector(memBRead);
+
+ -- during the next cycle we'll be reading the next opcode
+ spOffset(4) := not opcode(4);
+ spOffset(3 downto 0) := unsigned(opcode(3 downto 0));
+
+ idim_flag <= '0';
+
+ case decodedOpcode is
+
+ when Decoded_Interrupt =>
+ sp <= sp - 1;
+ memAAddr <= sp - 1;
+ memAWriteEnable <= '1';
+ memAWrite <= (others => DontCareValue);
+ memAWrite(maxAddrBit downto 0) <= pc;
+ pc <= to_unsigned(32, maxAddrBit+1); -- interrupt address
+ report "ZPU jumped to interrupt!" severity note;
+
+ when Decoded_Im =>
+ idim_flag <= '1';
+ memAWriteEnable <= '1';
+ if (idim_flag = '0') then
+ sp <= sp - 1;
+ memAAddr <= sp-1;
+ for i in wordSize-1 downto 7 loop
+ memAWrite(i) <= opcode(6);
+ end loop;
+ memAWrite(6 downto 0) <= unsigned(opcode(6 downto 0));
+ else
+ memAAddr <= sp;
+ memAWrite(wordSize-1 downto 7) <= memARead(wordSize-8 downto 0);
+ memAWrite(6 downto 0) <= unsigned(opcode(6 downto 0));
+ end if; -- idim_flag
+
+ when Decoded_StoreSP =>
+ memBWriteEnable <= '1';
+ memBAddr <= sp+spOffset;
+ memBWrite <= memARead;
+ sp <= sp + 1;
+ state <= State_Resync;
+
+ when Decoded_LoadSP =>
+ sp <= sp - 1;
+ memAAddr <= sp+spOffset;
+
+ when Decoded_Emulate =>
+ sp <= sp - 1;
+ memAWriteEnable <= '1';
+ memAAddr <= sp - 1;
+ memAWrite <= (others => DontCareValue);
+ memAWrite(maxAddrBit downto 0) <= pc + 1;
+ -- The emulate address is:
+ -- 98 7654 3210
+ -- 0000 00aa aaa0 0000
+ pc <= (others => '0');
+ pc(9 downto 5) <= unsigned(opcode(4 downto 0));
+
+ when Decoded_AddSP =>
+ memAAddr <= sp;
+ memBAddr <= sp+spOffset;
+ state <= State_AddSP;
+
+ when Decoded_Break =>
+ report "Break instruction encountered" severity failure;
+ break <= '1';
+
+ when Decoded_PushSP =>
+ memAWriteEnable <= '1';
+ memAAddr <= sp - 1;
+ sp <= sp - 1;
+ memAWrite <= (others => DontCareValue);
+ memAWrite(maxAddrBit downto minAddrBit) <= sp;
+
+ when Decoded_PopPC =>
+ pc <= memARead(maxAddrBit downto 0);
+ sp <= sp + 1;
+ state <= State_Resync;
+
+ when Decoded_Add =>
+ sp <= sp + 1;
+ state <= State_Add;
+
+ when Decoded_Or =>
+ sp <= sp + 1;
+ state <= State_Or;
+
+ when Decoded_And =>
+ sp <= sp + 1;
+ state <= State_And;
+
+ when Decoded_Load =>
+ if (memARead(ioBit) = '1') then
+ out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
+ out_mem_readEnable <= '1';
+ state <= State_ReadIO;
+ else
+ memAAddr <= memARead(maxAddrBit downto minAddrBit);
+ end if;
+
+ when Decoded_Not =>
+ memAAddr <= sp(maxAddrBit downto minAddrBit);
+ memAWriteEnable <= '1';
+ memAWrite <= not memARead;
+
+ when Decoded_Flip =>
+ memAAddr <= sp(maxAddrBit downto minAddrBit);
+ memAWriteEnable <= '1';
+ for i in 0 to wordSize-1 loop
+ memAWrite(i) <= memARead(wordSize-1-i);
+ end loop;
+
+ when Decoded_Store =>
+ memBAddr <= sp + 1;
+ sp <= sp + 1;
+ if (memARead(ioBit) = '1') then
+ state <= State_WriteIO;
+ else
+ state <= State_Store;
+ end if;
+
+ when Decoded_PopSP =>
+ sp <= memARead(maxAddrBit downto minAddrBit);
+ state <= State_Resync;
+
+ when Decoded_Nop =>
+ memAAddr <= sp;
+
+ when others =>
+ null;
+
+ end case; -- decodedOpcode
+
+ when State_ReadIO =>
+ memAAddr <= sp;
+ if (in_mem_busy = '0') then
+ state <= State_Fetch;
+ memAWriteEnable <= '1';
+ memAWrite <= unsigned(mem_read);
+ end if;
+
+ when State_WriteIO =>
+ sp <= sp + 1;
+ out_mem_writeEnable <= '1';
+ out_mem_addr <= std_logic_vector(memARead(maxAddrBitIncIO downto 0));
+ mem_write <= std_logic_vector(memBRead);
+ state <= State_WriteIODone;
+
+ when State_WriteIODone =>
+ if (in_mem_busy = '0') then
+ state <= State_Resync;
+ end if;
+
+ when State_Fetch =>
+ -- We need to resync. During the *next* cycle
+ -- we'll fetch the opcode @ pc and thus it will
+ -- be available for State_Execute the cycle after
+ -- next
+ memBAddr <= pc(maxAddrBit downto minAddrBit);
+ state <= State_FetchNext;
+
+ when State_FetchNext =>
+ -- at this point memARead contains the value that is either
+ -- from the top of stack or should be copied to the top of the stack
+ memAWriteEnable <= '1';
+ memAWrite <= memARead;
+ memAAddr <= sp;
+ memBAddr <= sp + 1;
+ state <= State_Decode;
+
+ when State_Decode =>
+ if interrupt = '1' and inInterrupt = '0' and idim_flag = '0' then
+ -- We got an interrupt, execute interrupt instead of next instruction
+ inInterrupt <= '1';
+ decodedOpcode <= Decoded_Interrupt;
+ end if;
+ -- during the State_Execute cycle we'll be fetching SP+1
+ memAAddr <= sp;
+ memBAddr <= sp + 1;
+ state <= State_Execute;
+
+ when State_Store =>
+ sp <= sp + 1;
+ memAWriteEnable <= '1';
+ memAAddr <= memARead(maxAddrBit downto minAddrBit);
+ memAWrite <= memBRead;
+ state <= State_Resync;
+
+ when State_AddSP =>
+ state <= State_Add;
+
+ when State_Add =>
+ memAAddr <= sp;
+ memAWriteEnable <= '1';
+ memAWrite <= memARead + memBRead;
+ state <= State_Fetch;
+
+ when State_Or =>
+ memAAddr <= sp;
+ memAWriteEnable <= '1';
+ memAWrite <= memARead or memBRead;
+ state <= State_Fetch;
+
+ when State_Resync =>
+ memAAddr <= sp;
+ state <= State_Fetch;
+
+ when State_And =>
+ memAAddr <= sp;
+ memAWriteEnable <= '1';
+ memAWrite <= memARead and memBRead;
+ state <= State_Fetch;
+
+ when others =>
+ null;
+
+ end case; -- state
+
+ end if; -- reset, enable
+ end process;
diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd
index 59d26e5..f6823f5 100644
--- a/zpu/hdl/zpu4/core/zpupkg.vhd
+++ b/zpu/hdl/zpu4/core/zpupkg.vhd
@@ -32,173 +32,187 @@
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
-library IEEE;
-use IEEE.STD_LOGIC_1164.all;
+library ieee;
+use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.zpu_config.all;
+
package zpupkg is
- -- This bit is set for read/writes to IO
- -- FIX!!! eventually this should be set to wordSize-1 so as to
- -- to make the address of IO independent of amount of memory
- -- reserved for CPU. Requires trivial tweaks in toolchain/runtime
- -- libraries.
-
- constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
- constant maxAddrBit : integer := maxAddrBitIncIO-1;
- constant ioBit : integer := maxAddrBit+1;
- constant wordSize : integer := 2**wordPower;
- constant wordBytes : integer := wordSize/8;
- constant minAddrBit : integer := byteBits;
- -- configurable internal stack size. Probably going to be 16 after toolchain is done
- constant stack_bits : integer := 5;
- constant stack_size : integer := 2**stack_bits;
-
-
- component dualport_ram is
- port (clk : in std_logic;
- memAWriteEnable : in std_logic;
- memAAddr : in std_logic_vector(maxAddrBitBRAM downto minAddrBit);
- memAWrite : in std_logic_vector(wordSize-1 downto 0);
- memARead : out std_logic_vector(wordSize-1 downto 0);
- memBWriteEnable : in std_logic;
- memBAddr : in std_logic_vector(maxAddrBitBRAM downto minAddrBit);
- memBWrite : in std_logic_vector(wordSize-1 downto 0);
- memBRead : out std_logic_vector(wordSize-1 downto 0));
- end component;
-
-
- component dram is
- port (clk : in std_logic;
- areset : in std_logic;
- mem_writeEnable : in std_logic;
- mem_readEnable : in std_logic;
- mem_addr : in std_logic_vector(maxAddrBit downto 0);
- mem_write : in std_logic_vector(wordSize-1 downto 0);
- mem_read : out std_logic_vector(wordSize-1 downto 0);
- mem_busy : out std_logic;
- mem_writeMask : in std_logic_vector(wordBytes-1 downto 0));
- end component;
-
-
- component trace is
- port(
- clk : in std_logic;
- begin_inst : in std_logic;
- pc : in std_logic_vector(maxAddrBitIncIO downto 0);
- opcode : in std_logic_vector(7 downto 0);
- sp : in std_logic_vector(maxAddrBitIncIO downto minAddrBit);
- memA : in std_logic_vector(wordSize-1 downto 0);
- memB : in std_logic_vector(wordSize-1 downto 0);
- busy : in std_logic;
- intSp : in std_logic_vector(stack_bits-1 downto 0)
- );
- end component;
-
- component zpu_core is
- port ( clk : in std_logic;
- areset : in std_logic;
- enable : in std_logic;
- in_mem_busy : in std_logic;
- mem_read : in std_logic_vector(wordSize-1 downto 0);
- mem_write : out std_logic_vector(wordSize-1 downto 0);
- out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
- out_mem_writeEnable : out std_logic;
- out_mem_readEnable : out std_logic;
- mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
- interrupt : in std_logic;
- break : out std_logic);
- end component;
-
-
-
- component timer is
- port(
- clk : in std_logic;
- areset : in std_logic;
- we : in std_logic;
- din : in std_logic_vector(7 downto 0);
- adr : in std_logic_vector(2 downto 0);
- dout : out std_logic_vector(7 downto 0));
- end component;
-
- component zpuio is
- port ( areset : in std_logic;
- cpu_clk : in std_logic;
- clk_status : in std_logic_vector(2 downto 0);
- cpu_din : in std_logic_vector(15 downto 0);
- cpu_a : in std_logic_vector(20 downto 0);
- cpu_we : in std_logic_vector(1 downto 0);
- cpu_re : in std_logic;
- cpu_dout : inout std_logic_vector(15 downto 0));
- end component;
-
-
-
-
- -- opcode decode constants
- constant OpCode_Im : std_logic_vector(7 downto 7) := "1";
- constant OpCode_StoreSP : std_logic_vector(7 downto 5) := "010";
- constant OpCode_LoadSP : std_logic_vector(7 downto 5) := "011";
- constant OpCode_Emulate : std_logic_vector(7 downto 5) := "001";
- constant OpCode_AddSP : std_logic_vector(7 downto 4) := "0001";
- constant OpCode_Short : std_logic_vector(7 downto 4) := "0000";
-
- constant OpCode_Break : std_logic_vector(3 downto 0) := "0000";
- constant OpCode_NA4 : std_logic_vector(3 downto 0) := "0001";
- constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010";
- constant OpCode_NA3 : std_logic_vector(3 downto 0) := "0011";
-
- constant OpCode_PopPC : std_logic_vector(3 downto 0) := "0100";
- constant OpCode_Add : std_logic_vector(3 downto 0) := "0101";
- constant OpCode_And : std_logic_vector(3 downto 0) := "0110";
- constant OpCode_Or : std_logic_vector(3 downto 0) := "0111";
-
- constant OpCode_Load : std_logic_vector(3 downto 0) := "1000";
- constant OpCode_Not : std_logic_vector(3 downto 0) := "1001";
- constant OpCode_Flip : std_logic_vector(3 downto 0) := "1010";
- constant OpCode_Nop : std_logic_vector(3 downto 0) := "1011";
-
- constant OpCode_Store : std_logic_vector(3 downto 0) := "1100";
- constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101";
- constant OpCode_NA2 : std_logic_vector(3 downto 0) := "1110";
- constant OpCode_NA : std_logic_vector(3 downto 0) := "1111";
-
- constant OpCode_Lessthan : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(36, 6));
- constant OpCode_Lessthanorequal : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(37, 6));
- constant OpCode_Ulessthan : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(38, 6));
- constant OpCode_Ulessthanorequal : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(39, 6));
-
- constant OpCode_Swap : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(40, 6));
- constant OpCode_Mult : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(41, 6));
-
- constant OpCode_Lshiftright : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(42, 6));
- constant OpCode_Ashiftleft : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(43, 6));
- constant OpCode_Ashiftright : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(44, 6));
- constant OpCode_Call : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(45, 6));
-
- constant OpCode_Eq : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(46, 6));
- constant OpCode_Neq : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(47, 6));
-
- constant OpCode_Sub : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(49, 6));
- constant OpCode_Loadb : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(51, 6));
- constant OpCode_Storeb : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(52, 6));
-
- constant OpCode_Eqbranch : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(55, 6));
- constant OpCode_Neqbranch : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(56, 6));
- constant OpCode_Poppcrel : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(57, 6));
-
- constant OpCode_Pushspadd : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(61, 6));
- constant OpCode_Mult16x16 : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(62, 6));
- constant OpCode_Callpcrel : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(63, 6));
-
-
-
- constant OpCode_Size : integer := 8;
-
-
-
+ -- This bit is set for read/writes to IO
+ -- FIX!!! eventually this should be set to wordSize-1 so as to
+ -- to make the address of IO independent of amount of memory
+ -- reserved for CPU. Requires trivial tweaks in toolchain/runtime
+ -- libraries.
+
+ constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
+ constant maxAddrBit : integer := maxAddrBitIncIO-1;
+ constant ioBit : integer := maxAddrBit+1;
+ constant wordSize : integer := 2**wordPower;
+ constant wordBytes : integer := wordSize/8;
+ constant minAddrBit : integer := byteBits;
+ -- configurable internal stack size. Probably going to be 16 after toolchain is done
+ constant stack_bits : integer := 5;
+ constant stack_size : integer := 2**stack_bits;
+
+
+ ------------------------------------------------------------
+ -- components
+
+ component dualport_ram is
+ port (
+ clk : in std_logic;
+ memAWriteEnable : in std_logic;
+ memAAddr : in std_logic_vector(maxAddrBitBRAM downto minAddrBit);
+ memAWrite : in std_logic_vector(wordSize-1 downto 0);
+ memARead : out std_logic_vector(wordSize-1 downto 0);
+ memBWriteEnable : in std_logic;
+ memBAddr : in std_logic_vector(maxAddrBitBRAM downto minAddrBit);
+ memBWrite : in std_logic_vector(wordSize-1 downto 0);
+ memBRead : out std_logic_vector(wordSize-1 downto 0)
+ );
+ end component dualport_ram;
+
+
+ component dram is
+ port (
+ clk : in std_logic;
+ areset : in std_logic;
+ mem_writeEnable : in std_logic;
+ mem_readEnable : in std_logic;
+ mem_addr : in std_logic_vector(maxAddrBit downto 0);
+ mem_write : in std_logic_vector(wordSize-1 downto 0);
+ mem_read : out std_logic_vector(wordSize-1 downto 0);
+ mem_busy : out std_logic;
+ mem_writeMask : in std_logic_vector(wordBytes-1 downto 0)
+ );
+ end component dram;
+
+
+ component trace is
+ port (
+ clk : in std_logic;
+ begin_inst : in std_logic;
+ pc : in std_logic_vector(maxAddrBitIncIO downto 0);
+ opcode : in std_logic_vector(7 downto 0);
+ sp : in std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ memA : in std_logic_vector(wordSize-1 downto 0);
+ memB : in std_logic_vector(wordSize-1 downto 0);
+ busy : in std_logic;
+ intSp : in std_logic_vector(stack_bits-1 downto 0)
+ );
+ end component trace;
+
+
+ component zpu_core is
+ port (
+ clk : in std_logic;
+ areset : in std_logic;
+ enable : in std_logic;
+ in_mem_busy : in std_logic;
+ mem_read : in std_logic_vector(wordSize-1 downto 0);
+ mem_write : out std_logic_vector(wordSize-1 downto 0);
+ out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
+ out_mem_writeEnable : out std_logic;
+ out_mem_readEnable : out std_logic;
+ mem_writeMask : out std_logic_vector(wordBytes-1 downto 0);
+ interrupt : in std_logic;
+ break : out std_logic
+ );
+ end component zpu_core;
+
+
+ component timer is
+ port (
+ clk : in std_logic;
+ areset : in std_logic;
+ we : in std_logic;
+ din : in std_logic_vector(7 downto 0);
+ adr : in std_logic_vector(2 downto 0);
+ dout : out std_logic_vector(7 downto 0)
+ );
+ end component timer;
+
+
+ component zpuio is
+ port (
+ areset : in std_logic;
+ cpu_clk : in std_logic;
+ clk_status : in std_logic_vector(2 downto 0);
+ cpu_din : in std_logic_vector(15 downto 0);
+ cpu_a : in std_logic_vector(20 downto 0);
+ cpu_we : in std_logic_vector(1 downto 0);
+ cpu_re : in std_logic;
+ cpu_dout : inout std_logic_vector(15 downto 0)
+ );
+ end component zpuio;
+
+
+ ------------------------------------------------------------
+ -- constants
+
+ -- opcode decode constants
+ constant OpCode_Im : std_logic_vector(7 downto 7) := "1";
+ constant OpCode_StoreSP : std_logic_vector(7 downto 5) := "010";
+ constant OpCode_LoadSP : std_logic_vector(7 downto 5) := "011";
+ constant OpCode_Emulate : std_logic_vector(7 downto 5) := "001";
+ constant OpCode_AddSP : std_logic_vector(7 downto 4) := "0001";
+ constant OpCode_Short : std_logic_vector(7 downto 4) := "0000";
+ --
+ constant OpCode_Break : std_logic_vector(3 downto 0) := "0000";
+ constant OpCode_NA4 : std_logic_vector(3 downto 0) := "0001";
+ constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010";
+ constant OpCode_NA3 : std_logic_vector(3 downto 0) := "0011";
+ --
+ constant OpCode_PopPC : std_logic_vector(3 downto 0) := "0100";
+ constant OpCode_Add : std_logic_vector(3 downto 0) := "0101";
+ constant OpCode_And : std_logic_vector(3 downto 0) := "0110";
+ constant OpCode_Or : std_logic_vector(3 downto 0) := "0111";
+ --
+ constant OpCode_Load : std_logic_vector(3 downto 0) := "1000";
+ constant OpCode_Not : std_logic_vector(3 downto 0) := "1001";
+ constant OpCode_Flip : std_logic_vector(3 downto 0) := "1010";
+ constant OpCode_Nop : std_logic_vector(3 downto 0) := "1011";
+ --
+ constant OpCode_Store : std_logic_vector(3 downto 0) := "1100";
+ constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101";
+ constant OpCode_NA2 : std_logic_vector(3 downto 0) := "1110";
+ constant OpCode_NA : std_logic_vector(3 downto 0) := "1111";
+ --
+ constant OpCode_Lessthan : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(36, 6));
+ constant OpCode_Lessthanorequal : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(37, 6));
+ constant OpCode_Ulessthan : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(38, 6));
+ constant OpCode_Ulessthanorequal : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(39, 6));
+ --
+ constant OpCode_Swap : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(40, 6));
+ constant OpCode_Mult : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(41, 6));
+ --
+ constant OpCode_Lshiftright : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(42, 6));
+ constant OpCode_Ashiftleft : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(43, 6));
+ constant OpCode_Ashiftright : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(44, 6));
+ constant OpCode_Call : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(45, 6));
+ --
+ constant OpCode_Eq : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(46, 6));
+ constant OpCode_Neq : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(47, 6));
+ --
+ constant OpCode_Sub : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(49, 6));
+ constant OpCode_Loadb : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(51, 6));
+ constant OpCode_Storeb : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(52, 6));
+ --
+ constant OpCode_Eqbranch : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(55, 6));
+ constant OpCode_Neqbranch : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(56, 6));
+ constant OpCode_Poppcrel : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(57, 6));
+ --
+ constant OpCode_Pushspadd : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(61, 6));
+ constant OpCode_Mult16x16 : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(62, 6));
+ constant OpCode_Callpcrel : std_logic_vector(5 downto 0) := std_logic_vector(to_unsigned(63, 6));
+ --
+ --
+ constant OpCode_Size : integer := 8;
+
+
+
end zpupkg;
OpenPOWER on IntegriCloud