From b93ac48f3c323a11a97a39338897c521780a16b9 Mon Sep 17 00:00:00 2001 From: oharboe Date: Sun, 4 May 2008 20:44:27 +0000 Subject: * moved ZPU core files to seperate folder * deleted some obsolete files --- zpu/hdl/zpu4/core/zpu_config.vhd | 16 + zpu/hdl/zpu4/core/zpu_core.vhd | 897 +++++++++++++++++++++++++++++++ zpu/hdl/zpu4/core/zpu_core_small.vhd | 464 ++++++++++++++++ zpu/hdl/zpu4/core/zpu_core_small_wip.vhd | 497 +++++++++++++++++ zpu/hdl/zpu4/core/zpupkg.vhd | 170 ++++++ 5 files changed, 2044 insertions(+) create mode 100644 zpu/hdl/zpu4/core/zpu_config.vhd create mode 100644 zpu/hdl/zpu4/core/zpu_core.vhd create mode 100644 zpu/hdl/zpu4/core/zpu_core_small.vhd create mode 100644 zpu/hdl/zpu4/core/zpu_core_small_wip.vhd create mode 100644 zpu/hdl/zpu4/core/zpupkg.vhd (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd new file mode 100644 index 0000000..a13c0bf --- /dev/null +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -0,0 +1,16 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.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; + +end zpu_config; diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd new file mode 100644 index 0000000..37fa2d1 --- /dev/null +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -0,0 +1,897 @@ + +-- Company: ZPU4 generic memory interface CPU +-- Engineer: Øyvind Harboe + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use ieee.numeric_std.all; + +library work; +use work.zpu_config.all; +use work.zpupkg.all; + + +-- mem_writeEnable - set to '1' for a single cycle to send off a write request. +-- mem_write is valid only while mem_writeEnable='1'. +-- mem_readEnable - set to '1' for a single cycle to send off a read request. +-- +-- mem_busy - It is illegal to send off a read/write request when mem_busy='1'. +-- Set to '0' when mem_read is valid after a read request. +-- If it goes to '1'(busy), it is on the cycle after mem_read/writeEnable +-- is '1'. +-- mem_addr - address for read/write request +-- mem_read - read data. Valid only on the cycle after mem_busy='0' after +-- mem_readEnable='1' for a single cycle. +-- mem_write - data to write +-- mem_writeMask - set to '1' for those bits that are to be written to memory upon +-- 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); +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 +); + + +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 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'; + 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'; + + + 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; + 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 + 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) + 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; + + + +end behave; diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd new file mode 100644 index 0000000..9cda01c --- /dev/null +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -0,0 +1,464 @@ +-- Company: ZPU3 +-- Engineer: Øyvind Harboe + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use ieee.numeric_std.all; + +library work; +use work.zpu_config.all; +use work.zpupkg.all; + + +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); +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); + +signal idim_flag : std_logic; + +--signal storeToStack : std_logic; +--signal fetchNextInstruction : std_logic; +--signal extraCycle : std_logic; +signal busy : std_logic; +--signal fetching : 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 +); + +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 +); + + + +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); + +-- debug +subtype index is integer range 0 to 3; +signal tOpcode_sel : index; + + +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; + + -- not used in this design + 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); + 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)); + + + decodeControl: + process(memBRead, pc,tOpcode_sel) + variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0); + begin + -- not worked with synopsys + -- tOpcode := std_logic_vector(memBRead((wordBytes-1-to_integer(pc(minAddrBit-1 downto 0))+1)*8-1 downto (wordBytes-1-to_integer(pc(minAddrBit-1 downto 0)))*8)); + -- use full case + 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'); + -- avoid Latch in synopsys + -- mem_writeMask <= (others => '1'); + 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; + + 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_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 => + 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 => + -- 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; + + + +end behave; diff --git a/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd b/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd new file mode 100644 index 0000000..8d87804 --- /dev/null +++ b/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd @@ -0,0 +1,497 @@ +-- Company: ZPU3 +-- Engineer: Øyvind Harboe + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use ieee.numeric_std.all; + +library work; +use work.zpu_config.all; +use work.zpupkg.all; + + +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); +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); + +signal idim_flag : std_logic; + +--signal storeToStack : std_logic; +--signal fetchNextInstruction : std_logic; +--signal extraCycle : std_logic; +signal busy : std_logic; +--signal fetching : 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 +); + + + +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 + 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; + + + + -- not used in this design + + 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); + 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)); + + + + 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(maxAddrBitIncIO downto 0) <= pc; + pc <= conv_std_logic_vector(32, maxAddrBitIncIo+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 => + 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 + 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; + + + +end behave; diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd new file mode 100644 index 0000000..f3800b0 --- /dev/null +++ b/zpu/hdl/zpu4/core/zpupkg.vhd @@ -0,0 +1,170 @@ +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_Shiftleft: std_logic_vector(3 downto 0) := "0001"; + constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010"; + constant OpCode_PushInt : 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_Compare : std_logic_vector(3 downto 0) := "1110"; + constant OpCode_PopInt : 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; -- cgit v1.1 From ef1ebefa6075994c4f0a76035b585def8c5c1d3a Mon Sep 17 00:00:00 2001 From: oharboe Date: Mon, 5 May 2008 11:40:45 +0000 Subject: wip --- zpu/hdl/zpu4/core/zpu_core_small_wip.vhd | 1 + 1 file changed, 1 insertion(+) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd b/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd index 8d87804..a169103 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd @@ -453,6 +453,7 @@ begin 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 -- cgit v1.1 From 6c7ee841131808466eb0c93e5c8f112771004fbf Mon Sep 17 00:00:00 2001 From: oharboe Date: Tue, 6 May 2008 06:39:21 +0000 Subject: * Small ZPU now supports interrupts * added simulation example demonstrating interrupts --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 83 ++++-- zpu/hdl/zpu4/core/zpu_core_small_wip.vhd | 498 ------------------------------- 2 files changed, 59 insertions(+), 522 deletions(-) delete mode 100644 zpu/hdl/zpu4/core/zpu_core_small_wip.vhd (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 9cda01c..03526bd 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -81,7 +81,9 @@ State_FetchNext, State_AddSP, State_ReadIODone, State_Decode, -State_Resync +State_Resync, +State_Interrupt + ); type DecodedOpcodeType is @@ -103,7 +105,8 @@ Decoded_Load, Decoded_Not, Decoded_Flip, Decoded_Store, -Decoded_PopSP +Decoded_PopSP, +Decoded_Interrupt ); @@ -125,11 +128,15 @@ signal memBAddr_stdlogic : std_logic_vector(AddrBitBRAM_range); signal memBWrite_stdlogic : std_logic_vector(memBWrite'range); signal memBRead_stdlogic : std_logic_vector(memBRead'range); --- debug -subtype index is integer range 0 to 3; -signal tOpcode_sel : index; - - +subtype index is integer range 0 to 3; + +signal tOpcode_sel : index; + + +signal inInterrupt : std_logic; + + + begin traceFileGenerate: if Generate_Trace generate @@ -146,8 +153,13 @@ begin ); end generate; - -- not used in this design - mem_writeMask <= (others => '1'); + + + -- not used in this design + + mem_writeMask <= (others => '1'); + + memAAddr_stdlogic <= std_logic_vector(memAAddr(AddrBitBRAM_range)); memAWrite_stdlogic <= std_logic_vector(memAWrite); @@ -167,23 +179,31 @@ begin memARead <= unsigned(memARead_stdlogic); memBRead <= unsigned(memBRead_stdlogic); -tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0)); + + + tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0)); + decodeControl: - process(memBRead, pc,tOpcode_sel) + process(memBRead, pc,tOpcode_sel) variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0); begin - -- not worked with synopsys - -- tOpcode := std_logic_vector(memBRead((wordBytes-1-to_integer(pc(minAddrBit-1 downto 0))+1)*8-1 downto (wordBytes-1-to_integer(pc(minAddrBit-1 downto 0)))*8)); - -- use full case - 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; + + -- 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 @@ -246,13 +266,12 @@ tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0)); out_mem_readEnable <= '0'; memAWrite <= (others => '0'); memBWrite <= (others => '0'); - -- avoid Latch in synopsys - -- mem_writeMask <= (others => '1'); + 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 + -- memAWrite can be left at whatever value if memAWriteEnable is -- not set. memAWrite <= (others => DontCareValue); memBWrite <= (others => DontCareValue); @@ -270,6 +289,9 @@ tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0)); decodedOpcode <= sampledDecodedOpcode; opcode <= sampledOpcode; + if interrupt='0' then + inInterrupt <= '0'; -- no longer in an interrupt + end if; case state is when State_Execute => @@ -295,6 +317,14 @@ tOpcode_sel <= to_integer(pc(minAddrBit-1 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'; @@ -422,6 +452,11 @@ tOpcode_sel <= to_integer(pc(minAddrBit-1 downto 0)); 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; diff --git a/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd b/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd deleted file mode 100644 index a169103..0000000 --- a/zpu/hdl/zpu4/core/zpu_core_small_wip.vhd +++ /dev/null @@ -1,498 +0,0 @@ --- Company: ZPU3 --- Engineer: Øyvind Harboe - -library IEEE; -use IEEE.STD_LOGIC_1164.ALL; -use ieee.numeric_std.all; - -library work; -use work.zpu_config.all; -use work.zpupkg.all; - - -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); -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); - -signal idim_flag : std_logic; - ---signal storeToStack : std_logic; ---signal fetchNextInstruction : std_logic; ---signal extraCycle : std_logic; -signal busy : std_logic; ---signal fetching : 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 -); - - - -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 - 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; - - - - -- not used in this design - - 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); - 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)); - - - - 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(maxAddrBitIncIO downto 0) <= pc; - pc <= conv_std_logic_vector(32, maxAddrBitIncIo+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 => - 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; - - - -end behave; -- cgit v1.1 From 10995e1545e11556e84665ff013313f5160f6161 Mon Sep 17 00:00:00 2001 From: oharboe Date: Thu, 7 Aug 2008 13:23:43 +0000 Subject: add missing defs. --- zpu/hdl/zpu4/core/zpu_config.vhd | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd index a13c0bf..ffc144b 100644 --- a/zpu/hdl/zpu4/core/zpu_config.vhd +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -1,6 +1,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; +use ieee.std_logic_arith.all; package zpu_config is -- generate trace output or not. @@ -12,5 +13,10 @@ package zpu_config is 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; -- cgit v1.1 From f9ddc2d50943be4bb9d4864cc277af99b03ade1f Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 8 Aug 2008 12:13:24 +0000 Subject: 2008-08-08 Salvador E. Tropea * zpu/hdl/zpu4/core/histogram.perl - generate opcode histogram from HDL simulation output --- zpu/hdl/zpu4/core/histogram.perl | 218 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 zpu/hdl/zpu4/core/histogram.perl (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/histogram.perl b/zpu/hdl/zpu4/core/histogram.perl new file mode 100644 index 0000000..479ee0f --- /dev/null +++ b/zpu/hdl/zpu4/core/histogram.perl @@ -0,0 +1,218 @@ +#!/usr/bin/perl +############################################################################## +# +# Copyright (c) 2008 Salvador E. Tropea +# Copyright (c) 2008 Instituto Nacional de Tecnología Industrial +# +############################################################################## +# +# Target: Any +# Language: Perl +# Interpreter used: v5.6.1/v5.8.4 +# Text editor: SETEdit 0.5.5 +# +############################################################################## +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA +# +############################################################################## +# +# Description: Takes a ZPU trace and does some raw stats about opcodes +# frequency and speed. +# +############################################################################## +# +# TODO +# +# A lot ... +# + + +# 0x40-0x460 +# div y mod son especiales +@used=(); +@clks=(); + +$line=1; +$startLine=1; +#$endLine=10000; +$endLine=-1; +$lastClk=0; +$lastOpcode=-1; +while (<>) + { + if ($_=~/^(\S+) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+)/) + { + $clk=hex($7); + #print "$line\n"; + if ($line>=$startLine) + { + #print $_; + $addr=hex($1); + $opcode=hex($2); + $sp=hex($3); + $a=hex($4); + $b=hex($5); + if ($addr>=0x40 and $addr<0x460) + { + @used[$opcode+0x100]++; + @clks[$lastOpcodeEmu]+=$clk-$lastClkEmu unless lastOpcodeEmu==-1; + $lastOpcodeEmu=$opcode+0x100; + $lastClkEmu=$clk; + } + else + { + @used[$opcode]++; + @clks[$lastOpcode]+=$clk-$lastClk unless $lastOpcode==-1; + #printf "%d+=%d\n",$lastOpcode,$clk-$lastClk; + $lastOpcode=$opcode; + $lastClk=$clk; + $lastOpcodeEmu=-1; + $lastClkEmu=$clk; + } + } + else + { + $lastClk=$clk; + } + last if $line==$endLine; + $line++; + } + } +@used[$lastOpcode]--; + +$id=0; +# Cluster them +AddSimple('breakpoint',0); +# 1=shiftleft, invalid +AddSimple('pushsp',2); +# 3=pushint, invalid +AddSimple('poppc',4); +AddSimple('add',5); +AddSimple('and',6); +AddSimple('or',7); +AddSimple('load',8); +AddSimple('not',9); +AddSimple('flip',10); +AddSimple('nop',11); +AddSimple('store',12); +AddSimple('popsp',13); +# 14=compare, invalid +# 15=popint, invalid +AddSimpleRange('addsp',16,31); +# 32-63 emulate +AddSimpleRange('storesp',64,95); +AddSimpleRange('loadsp',96,127); +AddSimpleRange('im',128,255); + +# 32 is the reset entry point +# 33 is the interrupt entry point +AddEmulate('loadh',34); +AddEmulate('storeh',35); +AddEmulate('lessthan',36); +AddEmulate('lessthanorequal',37); +AddEmulate('ulessthan',38); +AddEmulate('ulessthanorequal',39); +AddEmulate('swap',40); # unimplemented +AddEmulate('mult',41); +AddEmulate('lshiftright',42); +AddEmulate('ashiftleft',43); +AddEmulate('ashiftright',44); +AddEmulate('call',45); +AddEmulate('eq',46); +AddEmulate('neq',47); +AddEmulate('neg',48); +AddEmulate('sub',49); +AddEmulate('xor',50); +AddEmulate('loadb',51); +AddEmulate('storeb',52); +AddEmulate('div',53); +AddEmulate('mod',54); +AddEmulate('eqbranch',55); +AddEmulate('neqbranch',56); +AddEmulate('poppcrel',57); +AddEmulate('config',58); +AddEmulate('pushpc',59); +AddEmulate('syscall_emulate',60); # unimplemented +AddEmulate('pushspadd',61); +AddEmulate('halfmult',62); # unimplemented +AddEmulate('callpcrel',63); + +$maxID=$id; +print "Total clocks: $lastClk\n"; +print "Unsorted:\n\n"; +for ($i=0; $i<$maxID; $i++) + { + $used=@used_noemu[$i]; + $clkm=0; + $clkm=@clks_noemu[$i]/$used if $used; + printf "%-20s %8d %6.2f\n",$names[$i],$used,$clkm; + $by_times{$i}=$used; + $by_clks{$i}=@clks_noemu[$i]; + } +print "Sorted by consumed clocks:\n\n"; +foreach $key (sort { $by_clks{$b} <=> $by_clks{$a} } keys %by_clks) + { + printf "%5.2f %-20s %8d\n",$by_clks{$key}/$lastClk*100,$names[$key],$by_clks{$key}; + } + + +sub AddSimple +{ + my ($name, $opcode)=@_; + + $names[$id]=$name; + @used_noemu[$id]=@used[$opcode]; + @used_emu[$id]=@used[$opcode+0x100]; + @used_both[$id]=@used[$opcode]+@used[$opcode+0x100]; + @clks_noemu[$id]=@clks[$opcode]; + @clks_emu[$id]=@clks[$opcode+0x100]; + @clks_both[$id]=@clks[$opcode]+@clks[$opcode+0x100]; + $id++; +} + +sub AddEmulate +{ + my ($name, $opcode)=@_; + + $names[$id]=$name; + @used_noemu[$id]=@used[$opcode]; + @used_emu[$id]=@used[$opcode+0x100]; + @used_both[$id]=@used[$opcode]; + @clks_noemu[$id]=@clks[$opcode]; + @clks_emu[$id]=@clks[$opcode+0x100]; + @clks_both[$id]=@clks[$opcode]; + $id++; +} + +sub AddSimpleRange +{ + my ($name, $opStart, $opLast)=@_; + my $i; + + $names[$id]=$name; + for ($i=$opStart; $i<=$opLast; $i++) + { + @used_noemu[$id]+=@used[$i]; + @used_emu[$id]+=@used[$i+0x100]; + @used_both[$id]+=@used[$i]+@used[$i+0x100]; + @clks_noemu[$id]+=@clks[$i]; + @clks_emu[$id]+=@clks[$i+0x100]; + @clks_both[$id]+=@clks[$i]+@clks[$i+0x100]; + } + $id++; +} + + -- cgit v1.1 From eab67ae1b5d86c9c294ef057631d04a448e1727f Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 15 Aug 2008 10:53:01 +0000 Subject: marked unused instruction opcodes as OpCode_NAx --- zpu/hdl/zpu4/core/zpupkg.vhd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd index f3800b0..e8d54a3 100644 --- a/zpu/hdl/zpu4/core/zpupkg.vhd +++ b/zpu/hdl/zpu4/core/zpupkg.vhd @@ -114,9 +114,9 @@ package zpupkg is constant OpCode_Short : std_logic_vector(7 downto 4) := "0000"; constant OpCode_Break : std_logic_vector(3 downto 0) := "0000"; - constant OpCode_Shiftleft: std_logic_vector(3 downto 0) := "0001"; + constant OpCode_NA4 : std_logic_vector(3 downto 0) := "0001"; constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010"; - constant OpCode_PushInt : std_logic_vector(3 downto 0) := "0011"; + 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"; @@ -130,8 +130,8 @@ package zpupkg is constant OpCode_Store : std_logic_vector(3 downto 0) := "1100"; constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101"; - constant OpCode_Compare : std_logic_vector(3 downto 0) := "1110"; - constant OpCode_PopInt : std_logic_vector(3 downto 0) := "1111"; + 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)); -- cgit v1.1 From 5d329cc628e4174874382547397149e414ec0ad8 Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 15 Aug 2008 20:11:36 +0000 Subject: added FreeBSD license. Finally. --- zpu/hdl/zpu4/core/zpu_config.vhd | 35 +++++++++++++++++++++++++++++++++++ zpu/hdl/zpu4/core/zpu_core.vhd | 36 +++++++++++++++++++++++++++++++++--- zpu/hdl/zpu4/core/zpu_core_small.vhd | 35 +++++++++++++++++++++++++++++++++-- zpu/hdl/zpu4/core/zpupkg.vhd | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 5 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd index ffc144b..4fecf01 100644 --- a/zpu/hdl/zpu4/core/zpu_config.vhd +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -1,3 +1,38 @@ +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; use ieee.std_logic_unsigned.all; diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd index 37fa2d1..012fe1b 100644 --- a/zpu/hdl/zpu4/core/zpu_core.vhd +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -1,6 +1,36 @@ - --- Company: ZPU4 generic memory interface CPU --- Engineer: Øyvind Harboe +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 03526bd..69bbe1a 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -1,5 +1,36 @@ --- Company: ZPU3 --- Engineer: Øyvind Harboe +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd index e8d54a3..59d26e5 100644 --- a/zpu/hdl/zpu4/core/zpupkg.vhd +++ b/zpu/hdl/zpu4/core/zpupkg.vhd @@ -1,3 +1,37 @@ +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; use ieee.numeric_std.all; -- cgit v1.1 From 1de92a77fd154c79d210df2e957ade2a0965243f Mon Sep 17 00:00:00 2001 From: oharboe Date: Tue, 26 Aug 2008 19:09:30 +0000 Subject: fixed comments a bit. --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 69bbe1a..9946fb3 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -186,8 +186,7 @@ begin - -- not used in this design - + -- mem_writeMask is not used in this design, tie it to 1 mem_writeMask <= (others => '1'); -- cgit v1.1 From 76c3ea4351ea2f30ad948249e16d0253949f4f4e Mon Sep 17 00:00:00 2001 From: oharboe Date: Tue, 26 Aug 2008 19:13:29 +0000 Subject: some more comments about dual port ram --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 9946fb3..5587189 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -195,6 +195,27 @@ begin 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, -- cgit v1.1 From 0cc528bc3fc6f11e7997a2f68bf4badb59b3117f Mon Sep 17 00:00:00 2001 From: oharboe Date: Tue, 26 Aug 2008 19:56:25 +0000 Subject: commenting wip --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 5587189..f9484bb 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -43,7 +43,10 @@ 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); @@ -51,8 +54,16 @@ entity zpu_core is 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; @@ -76,13 +87,13 @@ 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 storeToStack : std_logic; ---signal fetchNextInstruction : std_logic; ---signal extraCycle : std_logic; signal busy : std_logic; ---signal fetching : std_logic; signal begin_inst : std_logic; @@ -169,6 +180,15 @@ 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 ( @@ -236,6 +256,8 @@ begin + -- 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); -- cgit v1.1 From 709f5ff71d918f10835d89ed6f349aee9dea340b Mon Sep 17 00:00:00 2001 From: oharboe Date: Wed, 12 Nov 2008 20:50:06 +0000 Subject: =?UTF-8?q?2008-11-12=20=C1lvaro=20Lopes=20=20?= =?UTF-8?q?=09*=20zpu/hdl/zpu4/core/zpu=5Fcore.vhd:=20Basic=20interrupt=20?= =?UTF-8?q?implementation=20=09for=20zpu4=20core.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zpu/hdl/zpu4/core/zpu_core.vhd | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd index 012fe1b..69da686 100644 --- a/zpu/hdl/zpu4/core/zpu_core.vhd +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -1,6 +1,7 @@ -- ZPU -- -- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- Copyright 2008 alvieboy - Álvaro Lopes - alvieboy@alvie.com -- -- The FreeBSD license -- @@ -145,7 +146,8 @@ State_Mult5, State_Mult4, State_BinaryOpResult2, State_BinaryOpResult, -State_Idle +State_Idle, +State_Interrupt ); @@ -171,6 +173,8 @@ 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); @@ -244,6 +248,7 @@ begin pc <= (others => '0'); idim_flag <= '0'; begin_inst <= '0'; + inInterrupt <= '0'; mem_writeEnable <= '0'; mem_readEnable <= '0'; multA <= (others => '0'); @@ -288,6 +293,10 @@ begin 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 => @@ -319,6 +328,27 @@ begin 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 -- cgit v1.1 From c3a6c5f8c614919982ef31c9e8e324525ce105b1 Mon Sep 17 00:00:00 2001 From: Alvaro Date: Fri, 22 Oct 2010 18:18:33 +0200 Subject: zpu_core_small: load memAAddr is not being initialized during IO read operations (LOAD). This might cause spurious writes to invalid addresses, and invalid values to be loaded onto the stack. This patch explicitly sets memAAddr to correct value (sp). --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 1 + 1 file changed, 1 insertion(+) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index f9484bb..681fb09 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -494,6 +494,7 @@ begin null; end case; when State_ReadIO => + memAAddr <= sp; if (in_mem_busy = '0') then state <= State_Fetch; memAWriteEnable <= '1'; -- cgit v1.1 From b103d820a57859fc4aad48f50029e12cc1db7611 Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Tue, 1 Mar 2011 17:36:01 +0100 Subject: beautify Signed-off-by: Bert Lange --- zpu/hdl/zpu4/core/zpu_config.vhd | 32 +- zpu/hdl/zpu4/core/zpu_core.vhd | 1820 ++++++++++++++++++---------------- zpu/hdl/zpu4/core/zpu_core_small.vhd | 1065 ++++++++++---------- zpu/hdl/zpu4/core/zpupkg.vhd | 338 ++++--- 4 files changed, 1679 insertions(+), 1576 deletions(-) (limited to 'zpu/hdl/zpu4/core') 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 - 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) - 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; -- cgit v1.1 From 04772b6a0bbe7017f5f7b44cfa203c3f7efbff64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Harboe?= Date: Tue, 1 Mar 2011 20:52:55 +0100 Subject: whitespace fixes: use fromdos on all .vhd files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Øyvind Harboe --- zpu/hdl/zpu4/core/zpu_config.vhd | 84 +++++++++---------- zpu/hdl/zpu4/core/zpu_core.vhd | 154 +++++++++++++++++------------------ zpu/hdl/zpu4/core/zpu_core_small.vhd | 112 ++++++++++++------------- zpu/hdl/zpu4/core/zpupkg.vhd | 86 +++++++++---------- 4 files changed, 218 insertions(+), 218 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd index 112dd01..5b3110c 100644 --- a/zpu/hdl/zpu4/core/zpu_config.vhd +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -1,44 +1,44 @@ --- ZPU --- --- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com --- --- The FreeBSD license --- --- Redistribution and use in source and binary forms, with or without --- modification, are permitted provided that the following conditions --- are met: --- --- 1. Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- 2. Redistributions in binary form must reproduce the above --- copyright notice, this list of conditions and the following --- disclaimer in the documentation and/or other materials --- provided with the distribution. --- --- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY --- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE --- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, --- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, --- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF --- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- --- The views and conclusions contained in the software and documentation --- 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; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - -package zpu_config is +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; +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; @@ -56,4 +56,4 @@ package zpu_config is constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) := conv_std_logic_vector((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1); -end zpu_config; +end zpu_config; diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd index ff9449f..e2e4781 100644 --- a/zpu/hdl/zpu4/core/zpu_core.vhd +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -1,68 +1,68 @@ --- ZPU --- --- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com --- Copyright 2008 alvieboy - Álvaro Lopes - alvieboy@alvie.com --- --- The FreeBSD license --- --- Redistribution and use in source and binary forms, with or without --- modification, are permitted provided that the following conditions --- are met: --- --- 1. Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- 2. Redistributions in binary form must reproduce the above --- copyright notice, this list of conditions and the following --- disclaimer in the documentation and/or other materials --- provided with the distribution. --- --- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY --- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE --- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, --- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, --- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF --- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- --- The views and conclusions contained in the software and documentation --- are those of the authors and should not be interpreted as representing --- official policies, either expressed or implied, of the ZPU Project. - +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- Copyright 2008 alvieboy - Álvaro Lopes - alvieboy@alvie.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; -use ieee.numeric_std.all; - -library work; -use work.zpu_config.all; -use work.zpupkg.all; - - --- mem_writeEnable - set to '1' for a single cycle to send off a write request. --- mem_write is valid only while mem_writeEnable='1'. --- mem_readEnable - set to '1' for a single cycle to send off a read request. --- --- mem_busy - It is illegal to send off a read/write request when mem_busy='1'. --- Set to '0' when mem_read is valid after a read request. --- If it goes to '1'(busy), it is on the cycle after mem_read/writeEnable --- is '1'. --- mem_addr - address for read/write request --- mem_read - read data. Valid only on the cycle after mem_busy='0' after --- mem_readEnable='1' for a single cycle. --- mem_write - data to write --- mem_writeMask - set to '1' for those bits that are to be written to memory upon --- 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 +use ieee.numeric_std.all; + +library work; +use work.zpu_config.all; +use work.zpupkg.all; + + +-- mem_writeEnable - set to '1' for a single cycle to send off a write request. +-- mem_write is valid only while mem_writeEnable='1'. +-- mem_readEnable - set to '1' for a single cycle to send off a read request. +-- +-- mem_busy - It is illegal to send off a read/write request when mem_busy='1'. +-- Set to '0' when mem_read is valid after a read request. +-- If it goes to '1'(busy), it is on the cycle after mem_read/writeEnable +-- is '1'. +-- mem_addr - address for read/write request +-- mem_read - read data. Valid only on the cycle after mem_busy='0' after +-- mem_readEnable='1' for a single cycle. +-- mem_write - data to write +-- mem_writeMask - set to '1' for those bits that are to be written to memory upon +-- 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; @@ -77,10 +77,10 @@ entity zpu_core is interrupt : in std_logic; break : out std_logic ); -end zpu_core; - -architecture behave of zpu_core is - +end zpu_core; + +architecture behave of zpu_core is + type InsnType is ( State_AddTop, State_Dup, @@ -196,12 +196,12 @@ architecture behave of zpu_core is 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 - - + +-- state machine. + +begin + + traceFileGenerate : if Generate_Trace generate trace_file : trace port map ( @@ -1009,7 +1009,7 @@ begin end case; -- state end if; -- clk'event end process; - - - -end behave; + + + +end behave; diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 1df9546..757d056 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -1,47 +1,47 @@ --- ZPU --- --- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com --- --- The FreeBSD license --- --- Redistribution and use in source and binary forms, with or without --- modification, are permitted provided that the following conditions --- are met: --- --- 1. Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- 2. Redistributions in binary form must reproduce the above --- copyright notice, this list of conditions and the following --- disclaimer in the documentation and/or other materials --- provided with the distribution. --- --- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY --- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE --- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, --- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, --- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF --- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- --- The views and conclusions contained in the software and documentation --- are those of the authors and should not be interpreted as representing --- official policies, either expressed or implied, of the ZPU Project. - +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; -use ieee.numeric_std.all; - -library work; -use work.zpu_config.all; -use work.zpupkg.all; - - -entity zpu_core is +use ieee.numeric_std.all; + +library work; +use work.zpu_config.all; +use work.zpupkg.all; + + +entity zpu_core is port ( clk : in std_logic; -- asynchronous reset signal @@ -67,12 +67,12 @@ entity zpu_core is -- in simulation to stop simulation break : out std_logic ); -end zpu_core; - - - +end zpu_core; + + + architecture behave of zpu_core is - + signal memAWriteEnable : std_logic; signal memAAddr : unsigned(maxAddrBit downto minAddrBit); signal memAWrite : unsigned(wordSize-1 downto 0); @@ -171,11 +171,11 @@ architecture behave of zpu_core is signal tOpcode_sel : index; -- signal inInterrupt : std_logic; - - - -begin - + + + +begin + -- generate a trace file. -- -- This is only used in simulation to see what instructions are @@ -596,7 +596,7 @@ begin end if; -- reset, enable end process; - - - -end behave; + + + +end behave; diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd index f6823f5..a6e749d 100644 --- a/zpu/hdl/zpu4/core/zpupkg.vhd +++ b/zpu/hdl/zpu4/core/zpupkg.vhd @@ -1,47 +1,47 @@ --- ZPU --- --- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com --- --- The FreeBSD license --- --- Redistribution and use in source and binary forms, with or without --- modification, are permitted provided that the following conditions --- are met: --- --- 1. Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- 2. Redistributions in binary form must reproduce the above --- copyright notice, this list of conditions and the following --- disclaimer in the documentation and/or other materials --- provided with the distribution. --- --- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY --- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE --- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, --- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, --- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF --- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- --- The views and conclusions contained in the software and documentation --- are those of the authors and should not be interpreted as representing --- official policies, either expressed or implied, of the ZPU Project. - +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; -use ieee.numeric_std.all; - -library work; -use work.zpu_config.all; - - -package zpupkg is - +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 @@ -215,4 +215,4 @@ package zpupkg is -end zpupkg; +end zpupkg; -- cgit v1.1 From f54a7949bc551f4a4ecc20728453cfe09ae65aed Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Fri, 4 Mar 2011 10:40:56 +0100 Subject: change: switch to ieee.numeric_std.all library Signed-off-by: Bert Lange --- zpu/hdl/zpu4/core/zpu_config.vhd | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd index 5b3110c..b29c561 100644 --- a/zpu/hdl/zpu4/core/zpu_config.vhd +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -35,8 +35,7 @@ library ieee; use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; +use ieee.numeric_std.all; package zpu_config is @@ -54,6 +53,6 @@ package zpu_config is -- 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); + std_logic_vector(to_unsigned((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1)); end zpu_config; -- cgit v1.1 From 509095f846aa8b2393ab7bf974eb2932846b950f Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Thu, 9 Jun 2011 17:54:03 +0200 Subject: fix: missing comment --- zpu/hdl/zpu4/core/zpu_core_small.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index 757d056..b975977 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -308,7 +308,7 @@ begin when others => sampledDecodedOpcode <= Decoded_Nop; end case; -- tOpcode(3 downto 0) - end if; tOpcode + end if; -- tOpcode end process; -- cgit v1.1 From b9ad801c86a4bf2f37be4972737b9c401335a49c Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Thu, 9 Jun 2011 17:59:07 +0200 Subject: change: rename signal areset to reset --- zpu/hdl/zpu4/core/zpu_core.vhd | 6 +++--- zpu/hdl/zpu4/core/zpu_core_small.vhd | 6 +++--- zpu/hdl/zpu4/core/zpupkg.vhd | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd index e2e4781..1b95444 100644 --- a/zpu/hdl/zpu4/core/zpu_core.vhd +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -65,7 +65,7 @@ use work.zpupkg.all; entity zpu_core is port ( clk : in std_logic; - areset : in std_logic; + reset : in std_logic; enable : in std_logic; in_mem_busy : in std_logic; mem_read : in std_logic_vector(wordSize-1 downto 0); @@ -230,7 +230,7 @@ begin decSp <= sp - 1; - opcodeControl : process(clk, areset) + opcodeControl : process(clk, reset) variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0); variable spOffset : unsigned(4 downto 0); variable tSpOffset : unsigned(4 downto 0); @@ -239,7 +239,7 @@ begin variable tDecodedOpcode : InsnArray; variable tMultResult : unsigned(wordSize*2-1 downto 0); begin - if areset = '1' then + if reset = '1' then state <= State_Idle; break <= '0'; sp <= unsigned(spStart(maxAddrBitIncIO downto minAddrBit)); diff --git a/zpu/hdl/zpu4/core/zpu_core_small.vhd b/zpu/hdl/zpu4/core/zpu_core_small.vhd index b975977..9ac35a8 100644 --- a/zpu/hdl/zpu4/core/zpu_core_small.vhd +++ b/zpu/hdl/zpu4/core/zpu_core_small.vhd @@ -45,7 +45,7 @@ entity zpu_core is port ( clk : in std_logic; -- asynchronous reset signal - areset : in std_logic; + reset : in std_logic; -- this particular implementation of the ZPU does not -- have a clocked enable signal enable : in std_logic; @@ -312,11 +312,11 @@ begin end process; - opcodeControl: process(clk, areset) + opcodeControl: process(clk, reset) variable spOffset : unsigned(4 downto 0); begin - if areset = '1' then + if reset = '1' then state <= State_Resync; break <= '0'; sp <= unsigned(spStart(maxAddrBit downto minAddrBit)); diff --git a/zpu/hdl/zpu4/core/zpupkg.vhd b/zpu/hdl/zpu4/core/zpupkg.vhd index a6e749d..0363aca 100644 --- a/zpu/hdl/zpu4/core/zpupkg.vhd +++ b/zpu/hdl/zpu4/core/zpupkg.vhd @@ -110,7 +110,7 @@ package zpupkg is component zpu_core is port ( clk : in std_logic; - areset : in std_logic; + reset : in std_logic; enable : in std_logic; in_mem_busy : in std_logic; mem_read : in std_logic_vector(wordSize-1 downto 0); -- cgit v1.1 From ec177759929085f161b9a5c7c82016406d8867cb Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Tue, 16 Aug 2011 23:43:12 +0200 Subject: beautify indentation --- zpu/hdl/zpu4/core/zpu_config.vhd | 116 +++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_config.vhd b/zpu/hdl/zpu4/core/zpu_config.vhd index b29c561..c678044 100644 --- a/zpu/hdl/zpu4/core/zpu_config.vhd +++ b/zpu/hdl/zpu4/core/zpu_config.vhd @@ -1,58 +1,58 @@ --- ZPU --- --- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com --- --- The FreeBSD license --- --- Redistribution and use in source and binary forms, with or without --- modification, are permitted provided that the following conditions --- are met: --- --- 1. Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- 2. Redistributions in binary form must reproduce the above --- copyright notice, this list of conditions and the following --- disclaimer in the documentation and/or other materials --- provided with the distribution. --- --- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY --- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE --- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, --- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES --- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS --- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) --- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, --- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF --- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- --- The views and conclusions contained in the software and documentation --- 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; -use ieee.numeric_std.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) := - std_logic_vector(to_unsigned((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1)); - -end zpu_config; +-- ZPU +-- +-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com +-- +-- The FreeBSD license +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above +-- copyright notice, this list of conditions and the following +-- disclaimer in the documentation and/or other materials +-- provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY +-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- +-- The views and conclusions contained in the software and documentation +-- 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; +use ieee.numeric_std.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) := + std_logic_vector(to_unsigned((2**(maxAddrBitBRAM+1))-8, maxAddrBitIncIO+1)); + +end zpu_config; -- cgit v1.1 From 6f2e0ea6433ae0042e75bf668c5f10b77e6e2bf7 Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Fri, 30 Mar 2012 08:59:26 +0200 Subject: change: rename 'State' to 'Insn' --- zpu/hdl/zpu4/core/zpu_core.vhd | 243 ++++++++++++++++++++--------------------- 1 file changed, 121 insertions(+), 122 deletions(-) (limited to 'zpu/hdl/zpu4/core') diff --git a/zpu/hdl/zpu4/core/zpu_core.vhd b/zpu/hdl/zpu4/core/zpu_core.vhd index 1b95444..f423f80 100644 --- a/zpu/hdl/zpu4/core/zpu_core.vhd +++ b/zpu/hdl/zpu4/core/zpu_core.vhd @@ -79,48 +79,48 @@ entity zpu_core is ); 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 + Insn_AddTop, + Insn_Dup, + Insn_DupStackB, + Insn_Pop, + Insn_PopDown, + Insn_Add, + Insn_Or, + Insn_And, + Insn_Store, + Insn_AddSP, + Insn_Shift, + Insn_Nop, + Insn_Im, + Insn_LoadSP, + Insn_StoreSP, + Insn_Emulate, + Insn_Load, + Insn_PushSP, + Insn_PopPC, + Insn_PopPCrel, + Insn_Not, + Insn_Flip, + Insn_PopSP, + Insn_Neqbranch, + Insn_Eq, + Insn_Loadb, + Insn_Mult, + Insn_Lessthan, + Insn_Lessthanorequal, + Insn_Ulessthanorequal, + Insn_Ulessthan, + Insn_PushSPadd, + Insn_Call, + Insn_CallPCrel, + Insn_Sub, + Insn_Break, + Insn_Storeb, + Insn_InsnFetch ); type StateType is ( @@ -189,7 +189,6 @@ architecture behave of zpu_core is - signal begin_inst : std_logic; signal trace_opcode : std_logic_vector(7 downto 0); signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0); @@ -235,7 +234,7 @@ begin variable spOffset : unsigned(4 downto 0); variable tSpOffset : unsigned(4 downto 0); variable nextPC : unsigned(maxAddrBitIncIO downto 0); - variable tNextState : InsnType; + variable tNextInsn : InsnType; variable tDecodedOpcode : InsnArray; variable tMultResult : unsigned(wordSize*2-1 downto 0); begin @@ -253,7 +252,7 @@ begin multA <= (others => '0'); multB <= (others => '0'); mem_writeMask <= (others => '1'); - elsif (clk'event and clk = '1') then + elsif rising_edge(clk) then -- we must multiply unconditionally to get pipelined multiplication tMultResult := multA * multB; multResult3 <= multResult2; @@ -366,99 +365,99 @@ begin opcode(i) <= tOpcode; if (tOpcode(7 downto 7) = OpCode_Im) then - tNextState := State_Im; + tNextInsn := Insn_Im; elsif (tOpcode(7 downto 5) = OpCode_StoreSP) then if tSpOffset = 0 then - tNextState := State_Pop; + tNextInsn := Insn_Pop; elsif tSpOffset = 1 then - tNextState := State_PopDown; + tNextInsn := Insn_PopDown; else - tNextState := State_StoreSP; + tNextInsn := Insn_StoreSP; end if; elsif (tOpcode(7 downto 5) = OpCode_LoadSP) then if tSpOffset = 0 then - tNextState := State_Dup; + tNextInsn := Insn_Dup; elsif tSpOffset = 1 then - tNextState := State_DupStackB; + tNextInsn := Insn_DupStackB; else - tNextState := State_LoadSP; + tNextInsn := Insn_LoadSP; end if; elsif (tOpcode(7 downto 5) = OpCode_Emulate) then - tNextState := State_Emulate; + tNextInsn := Insn_Emulate; if tOpcode(5 downto 0) = OpCode_Neqbranch then - tNextState := State_Neqbranch; + tNextInsn := Insn_Neqbranch; elsif tOpcode(5 downto 0) = OpCode_Eq then - tNextState := State_Eq; + tNextInsn := Insn_Eq; elsif tOpcode(5 downto 0) = OpCode_Lessthan then - tNextState := State_Lessthan; + tNextInsn := Insn_Lessthan; elsif tOpcode(5 downto 0) = OpCode_Lessthanorequal then - --tNextState :=State_Lessthanorequal; + --tNextInsn :=Insn_Lessthanorequal; elsif tOpcode(5 downto 0) = OpCode_Ulessthan then - tNextState := State_Ulessthan; + tNextInsn := Insn_Ulessthan; elsif tOpcode(5 downto 0) = OpCode_Ulessthanorequal then - --tNextState :=State_Ulessthanorequal; + --tNextInsn :=Insn_Ulessthanorequal; elsif tOpcode(5 downto 0) = OpCode_Loadb then - tNextState := State_Loadb; + tNextInsn := Insn_Loadb; elsif tOpcode(5 downto 0) = OpCode_Mult then - tNextState := State_Mult; + tNextInsn := Insn_Mult; elsif tOpcode(5 downto 0) = OpCode_Storeb then - tNextState := State_Storeb; + tNextInsn := Insn_Storeb; elsif tOpcode(5 downto 0) = OpCode_Pushspadd then - tNextState := State_Pushspadd; + tNextInsn := Insn_PushSPadd; elsif tOpcode(5 downto 0) = OpCode_Callpcrel then - tNextState := State_Callpcrel; + tNextInsn := Insn_CallPCrel; elsif tOpcode(5 downto 0) = OpCode_Call then - --tNextState :=State_Call; + --tNextInsn :=Insn_Call; elsif tOpcode(5 downto 0) = OpCode_Sub then - tNextState := State_Sub; + tNextInsn := Insn_Sub; elsif tOpcode(5 downto 0) = OpCode_PopPCRel then - --tNextState :=State_PopPCRel; + --tNextInsn :=Insn_PopPCrel; end if; elsif (tOpcode(7 downto 4) = OpCode_AddSP) then if tSpOffset = 0 then - tNextState := State_Shift; + tNextInsn := Insn_Shift; elsif tSpOffset = 1 then - tNextState := State_AddTop; + tNextInsn := Insn_AddTop; else - tNextState := State_AddSP; + tNextInsn := Insn_AddSP; end if; else case tOpcode(3 downto 0) is when OpCode_Nop => - tNextState := State_Nop; + tNextInsn := Insn_Nop; when OpCode_PushSP => - tNextState := State_PushSP; + tNextInsn := Insn_PushSP; when OpCode_PopPC => - tNextState := State_PopPC; + tNextInsn := Insn_PopPC; when OpCode_Add => - tNextState := State_Add; + tNextInsn := Insn_Add; when OpCode_Or => - tNextState := State_Or; + tNextInsn := Insn_Or; when OpCode_And => - tNextState := State_And; + tNextInsn := Insn_And; when OpCode_Load => - tNextState := State_Load; + tNextInsn := Insn_Load; when OpCode_Not => - tNextState := State_Not; + tNextInsn := Insn_Not; when OpCode_Flip => - tNextState := State_Flip; + tNextInsn := Insn_Flip; when OpCode_Store => - tNextState := State_Store; + tNextInsn := Insn_Store; when OpCode_PopSP => - tNextState := State_PopSP; + tNextInsn := Insn_PopSP; when others => - tNextState := State_Break; + tNextInsn := Insn_Break; end case; -- tOpcode(3 downto 0) end if; -- tOpcode - tDecodedOpcode(i) := tNextState; + tDecodedOpcode(i) := tNextInsn; 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; + tDecodedOpcode(0) := Insn_InsnFetch; decodedOpcode <= tDecodedOpcode; state <= State_Execute; @@ -468,7 +467,7 @@ begin -- Each instruction must: -- -- 1. set idim_flag - -- 2. increase pc if applicable + -- 2. increase PC if applicable -- 3. set next state if appliable -- 4. do it's operation @@ -477,10 +476,10 @@ begin case insn is - when State_InsnFetch => + when Insn_InsnFetch => state <= State_Fetch; - when State_Im => + when Insn_Im => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '1'; @@ -502,7 +501,7 @@ begin end if; -- idim_flag end if; -- in_mem_busy - when State_StoreSP => + when Insn_StoreSP => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -516,7 +515,7 @@ begin end if; - when State_LoadSP => + when Insn_LoadSP => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -528,7 +527,7 @@ begin mem_write <= std_logic_vector(stackB); end if; - when State_Emulate => + when Insn_Emulate => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -548,7 +547,7 @@ begin state <= State_Fetch; end if; -- in_mem_busy - when State_Callpcrel => + when Insn_CallPCrel => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -559,7 +558,7 @@ begin state <= State_Fetch; end if; - when State_Call => + when Insn_Call => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -569,7 +568,7 @@ begin state <= State_Fetch; end if; - when State_AddSP => + when Insn_AddSP => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -579,7 +578,7 @@ begin mem_addr <= std_logic_vector(sp+spOffset); end if; - when State_PushSP => + when Insn_PushSP => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -594,7 +593,7 @@ begin mem_write <= std_logic_vector(stackB); end if; - when State_PopPC => + when Insn_PopPC => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -607,7 +606,7 @@ begin state <= State_Resync; end if; - when State_PopPCRel => + when Insn_PopPCrel => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -620,7 +619,7 @@ begin state <= State_Resync; end if; - when State_Add => + when Insn_Add => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -632,7 +631,7 @@ begin state <= State_Popped; end if; - when State_Sub => + when Insn_Sub => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -640,7 +639,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Pop => + when Insn_Pop => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -651,7 +650,7 @@ begin state <= State_Popped; end if; - when State_PopDown => + when Insn_PopDown => if in_mem_busy = '0' then -- PopDown leaves top of stack unchanged begin_inst <= '1'; @@ -662,7 +661,7 @@ begin state <= State_Popped; end if; - when State_Or => + when Insn_Or => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -673,7 +672,7 @@ begin state <= State_Popped; end if; - when State_And => + when Insn_And => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -685,7 +684,7 @@ begin state <= State_Popped; end if; - when State_Eq => + when Insn_Eq => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -697,7 +696,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Ulessthan => + when Insn_Ulessthan => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -709,7 +708,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Ulessthanorequal => + when Insn_Ulessthanorequal => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -721,7 +720,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Lessthan => + when Insn_Lessthan => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -733,7 +732,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Lessthanorequal => + when Insn_Lessthanorequal => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -745,7 +744,7 @@ begin state <= State_BinaryOpResult; end if; - when State_Load => + when Insn_Load => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -755,7 +754,7 @@ begin mem_readEnable <= '1'; end if; - when State_Dup => + when Insn_Dup => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -768,7 +767,7 @@ begin mem_writeEnable <= '1'; end if; - when State_DupStackB => + when Insn_DupStackB => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -782,7 +781,7 @@ begin mem_writeEnable <= '1'; end if; - when State_Store => + when Insn_Store => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -794,7 +793,7 @@ begin state <= State_Resync; end if; - when State_PopSP => + when Insn_PopSP => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -807,19 +806,19 @@ begin state <= State_Resync; end if; - when State_Nop => + when Insn_Nop => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; - when State_Not => + when Insn_Not => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; - stackA <= not stackA; + stackA <= not stackA; - when State_Flip => + when Insn_Flip => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; @@ -828,14 +827,14 @@ begin stackA(i) <= stackA(wordSize-1-i); end loop; - when State_AddTop => + when Insn_AddTop => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; - stackA <= stackA + stackB; + stackA <= stackA + stackB; - when State_Shift => + when Insn_Shift => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; @@ -843,7 +842,7 @@ begin stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0); stackA(0) <= '0'; - when State_Pushspadd => + when Insn_PushSPadd => begin_inst <= '1'; idim_flag <= '0'; pc <= pc + 1; @@ -851,7 +850,7 @@ begin stackA <= (others => '0'); stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp; - when State_Neqbranch => + when Insn_Neqbranch => -- branches are almost always taken as they form loops begin_inst <= '1'; idim_flag <= '0'; @@ -864,7 +863,7 @@ begin -- need to fetch stack again. state <= State_Resync; - when State_Mult => + when Insn_Mult => begin_inst <= '1'; idim_flag <= '0'; @@ -872,11 +871,11 @@ begin multB <= stackB; state <= State_Mult2; - when State_Break => + when Insn_Break => report "Break instruction encountered" severity failure; break <= '1'; - when State_Loadb => + when Insn_Loadb => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; @@ -886,7 +885,7 @@ begin mem_readEnable <= '1'; end if; - when State_Storeb => + when Insn_Storeb => if in_mem_busy = '0' then begin_inst <= '1'; idim_flag <= '0'; -- cgit v1.1