diff options
author | Bert Lange <b.lange@hzdr.de> | 2011-03-01 17:36:01 +0100 |
---|---|---|
committer | Øyvind Harboe <oyvind.harboe@zylin.com> | 2011-03-01 20:46:32 +0100 |
commit | b103d820a57859fc4aad48f50029e12cc1db7611 (patch) | |
tree | ad207a64d4f4e58ea59e77f5faa376956f3db3c9 /zpu/hdl/zpu4/core/zpu_core.vhd | |
parent | c3a6c5f8c614919982ef31c9e8e324525ce105b1 (diff) | |
download | zpu-b103d820a57859fc4aad48f50029e12cc1db7611.zip zpu-b103d820a57859fc4aad48f50029e12cc1db7611.tar.gz |
beautify
Signed-off-by: Bert Lange <b.lange@hzdr.de>
Diffstat (limited to 'zpu/hdl/zpu4/core/zpu_core.vhd')
-rw-r--r-- | zpu/hdl/zpu4/core/zpu_core.vhd | 1820 |
1 files changed, 939 insertions, 881 deletions
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; |