diff options
Diffstat (limited to 'zpu/hdl/zpu4/src/zpu_core_small.vhd')
-rw-r--r-- | zpu/hdl/zpu4/src/zpu_core_small.vhd | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/zpu/hdl/zpu4/src/zpu_core_small.vhd b/zpu/hdl/zpu4/src/zpu_core_small.vhd new file mode 100644 index 0000000..4d73f88 --- /dev/null +++ b/zpu/hdl/zpu4/src/zpu_core_small.vhd @@ -0,0 +1,433 @@ +-- Company: ZPU3 +-- Engineer: Øyvind Harboe + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_UNSIGNED.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 : std_logic_vector(maxAddrBit downto minAddrBit); +signal memAWrite : std_logic_vector(wordSize-1 downto 0); +signal memARead : std_logic_vector(wordSize-1 downto 0); +signal memBWriteEnable : std_logic; +signal memBAddr : std_logic_vector(maxAddrBit downto minAddrBit); +signal memBWrite : std_logic_vector(wordSize-1 downto 0); +signal memBRead : std_logic_vector(wordSize-1 downto 0); + + + +signal pc : std_logic_vector(maxAddrBit downto 0); +signal sp : std_logic_vector(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; + +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; + + + memory: dualport_ram port map ( + clk => clk, + memAWriteEnable => memAWriteEnable, + memAAddr => memAAddr(maxAddrBitBRAM downto minAddrBit), + memAWrite => memAWrite, + memARead => memARead, + memBWriteEnable => memBWriteEnable, + memBAddr => memBAddr(maxAddrBitBRAM downto minAddrBit), + memBWrite => memBWrite, + memBRead => memBRead + ); + + + + decodeControl: + process(memBRead, pc) + variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0); + begin + tOpcode := memBRead((wordBytes-1-conv_integer(pc(minAddrBit-1 downto 0))+1)*8-1 downto (wordBytes-1-conv_integer(pc(minAddrBit-1 downto 0)))*8); + + 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 : std_logic_vector(4 downto 0); + begin + if areset = '1' then + state <= State_Resync; + break <= '0'; + sp <= 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'); + 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 <= memARead(maxAddrBitIncIO downto 0); + mem_write <= 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) <= pc; + trace_opcode <= opcode; + trace_sp <= (others => '0'); + trace_sp(maxAddrBit downto minAddrBit) <= sp; + trace_topOfStack <= memARead; + trace_topOfStackB <= memBRead; + + -- during the next cycle we'll be reading the next opcode + spOffset(4):=not opcode(4); + spOffset(3 downto 0):=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) <= opcode(6 downto 0); + else + memAAddr <= sp; + memAWrite(wordSize-1 downto 7) <= memARead(wordSize-8 downto 0); + memAWrite(6 downto 0) <= 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) <= 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 <= 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 <= mem_read; + end if; + when State_WriteIO => + sp <= sp + 1; + out_mem_writeEnable <= '1'; + out_mem_addr <= memARead(maxAddrBitIncIO downto 0); + mem_write <= 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; |