URL
https://opencores.org/ocsvn/ax8/ax8/trunk
Subversion Repositories ax8
[/] [ax8/] [trunk/] [rtl/] [vhdl/] [AX8.vhd] - Rev 31
Compare with Previous | Blame | View Log
-- -- AT90Sxxxx compatible microcontroller core -- -- Version : 0224 -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- -- All rights reserved -- -- Redistribution and use in source and synthezised forms, with or without -- modification, are permitted provided that the following conditions are met: -- -- Redistributions of source code must retain the above copyright notice, -- this list of conditions and the following disclaimer. -- -- Redistributions in synthesized 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. -- -- Neither the name of the author nor the names of other contributors may -- be used to endorse or promote products derived from this software without -- specific prior written permission. -- -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 AUTHOR 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. -- -- Please report bugs to the author, but before you do so, please -- make sure that this is not a derivative work and that -- you have the latest version of this file. -- -- The latest version of this file can be found at: -- http://www.opencores.org/cvsweb.shtml/ax8/ -- -- Limitations : -- No power down sleep, only 16 bit addresses, no external RAM -- -- File history : -- -- 0146 : First release -- 0220 : Added support for synchronous ROM -- 0221 : Changed tristate buses -- 0221b : Changed tristate buses -- 0224 : Fixed reset library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.AX_Pack.all; entity AX8 is generic( ROMAddressWidth : integer; RAMAddressWidth : integer; BigISet : boolean; TriState : boolean := false ); port( Clk : in std_logic; Reset_n : in std_logic; ROM_Addr : out std_logic_vector(ROMAddressWidth - 1 downto 0); ROM_Data : in std_logic_vector(15 downto 0); Sleep_En : in std_logic; Int_Trig : in std_logic_vector(15 downto 1); Int_Acc : out std_logic_vector(15 downto 1); SREG : out std_logic_vector(7 downto 0); SP : out std_logic_vector(15 downto 0); IO_Rd : out std_logic; IO_Wr : out std_logic; IO_Addr : out std_logic_vector(5 downto 0); IO_RData : in std_logic_vector(7 downto 0); IO_WData : out std_logic_vector(7 downto 0); WDR : out std_logic ); end AX8; architecture rtl of AX8 is -- Registers signal SREG_i : std_logic_vector(7 downto 0); signal SP_i : unsigned(15 downto 0); signal NPC : std_logic_vector(15 downto 0); signal PC : std_logic_vector(15 downto 0); signal PCH : std_logic_vector(7 downto 0); signal Dec_SP : std_logic; signal Inc_SP : std_logic; signal X : unsigned(15 downto 0); signal Y : unsigned(15 downto 0); signal Z : unsigned(15 downto 0); signal Add : std_logic; signal Sub : std_logic; signal AS_Offset : std_logic_vector(5 downto 0); signal Dec_X : std_logic; signal Dec_Y : std_logic; signal Dec_Z : std_logic; signal Inc_X : std_logic; signal Inc_Y : std_logic; signal Inc_Z : std_logic; -- ALU signals signal Do_Other : std_logic; signal Pass_Mux : std_logic_vector(7 downto 0); signal Op_Mux : std_logic_vector(7 downto 0); signal Status_D : std_logic_vector(6 downto 0); signal Status_D_R : std_logic_vector(4 downto 0); signal Status_Wr : std_logic_vector(6 downto 0); signal Status_D_Wr : std_logic; -- Misc signals signal Rd_Addr : std_logic_vector(15 downto 0); signal Rr_Addr : std_logic_vector(15 downto 0); signal IO_Addr_i : std_logic_vector(5 downto 0); signal Wr_Data : std_logic_vector(7 downto 0); signal Rd_Data : std_logic_vector(7 downto 0); signal Rr_Data : std_logic_vector(7 downto 0); signal RAM_Data : std_logic_vector(7 downto 0); signal Offset : std_logic_vector(11 downto 0); signal Q : std_logic_vector(7 downto 0); signal Disp : std_logic_vector(5 downto 0); signal Bit_Pattern : std_logic_vector(7 downto 0); signal IO_BMData : std_logic_vector(7 downto 0); signal IO_BTest : std_logic_vector(7 downto 0); signal Do_SBIC : std_logic; signal Do_SBIS : std_logic; signal CInt : std_logic_vector(3 downto 0); signal IPush : std_logic; signal IPending : std_logic; -- Registered instruction word. signal Inst : std_logic_vector(15 downto 0); -- Control signals signal Rst_r : std_logic; signal IO_IR : std_logic; signal RAM_IR : std_logic; signal PMH_IR : std_logic; signal PML_IR : std_logic; signal IO_IW : std_logic; signal RAM_IW : std_logic; signal Reg_IW : std_logic; signal Reg_Wr : std_logic; signal HPC_Rd : std_logic; signal LPC_Rd : std_logic; signal Reg_Rd : std_logic; signal RAM_Rd : std_logic; signal PMH_Rd : std_logic; signal PML_Rd : std_logic; signal Reg_Wr_ID : std_logic; signal RAM_Wr_ID : std_logic; signal PassB : std_logic; signal IO_Rd_i : std_logic; signal IO_Wr_i : std_logic; signal Z_Skip : std_logic; signal IOZ_Skip : std_logic; signal Pause : std_logic_vector(1 downto 0); signal DidPause : std_logic_vector(1 downto 0); signal PCPause : std_logic; signal IndSkip : std_logic; signal Inst_Skip : std_logic; signal PreDecode : std_logic; signal Imm_Op : std_logic; signal Push : std_logic; signal Pop : std_logic; signal HRet : std_logic; signal LRet : std_logic; signal ZJmp : std_logic; signal RJmp : std_logic; signal CBranch : std_logic; signal Sleep : std_logic; begin PreDecode <= '1' when Rst_r = '0' and Inst_Skip = '0' and (Pause = "00" or DidPause = "01") else '0'; -- Addressing control: -- IO and Rd/Rr address are always generated parallel with fetch -- On indirect addressing the correct address is generated on the next positive clock edge -- The chip selects are only used with 2+ cycle instructions Disp <= Inst(13) & Inst(11 downto 10) & Inst(2 downto 0); Reg_Wr <= '1' when Inst(15 downto 12) = "0010" or Inst(15 downto 14) = "01" or Inst(15 downto 11) = "00001" or Inst(15 downto 11) = "00011" or Inst(15 downto 12) = "1110" or Inst(15 downto 9) = "1111100" or (Inst(15 downto 9) = "1001010" and Inst(3 downto 1) /= "100") or Inst(15 downto 11) = "10110" or Reg_Wr_ID = '1' else '0'; process (Clk) begin if Clk'event and Clk = '1' then Reg_Wr_ID <= Reg_IW; RAM_Wr_ID <= RAM_IW; end if; end process; process (ROM_Data, Inst, DidPause, Pause, SP_i, X, Y, Z, Disp, IPush) begin Rd_Addr <= (others => '-'); Rr_Addr <= (others => '-'); Rd_Addr(4 downto 0) <= ROM_Data(8 downto 4); Rr_Addr(4 downto 0) <= ROM_Data(9) & ROM_Data(3 downto 0); if ROM_Data(15 downto 12) = "0011" or ROM_Data(15 downto 14) = "01" or ROM_Data(15 downto 12) = "1110" then -- Special case for immediate data and four bit address Rd_Addr(4) <= '1'; end if; Dec_X <= '0'; Dec_Y <= '0'; Dec_Z <= '0'; Inc_X <= '0'; Inc_Y <= '0'; Inc_Z <= '0'; Dec_SP <= '0'; Inc_SP <= '0'; if DidPause = "00" and Pause = "01" then if BigIset then if Inst(15 downto 14) = "10" and Inst(12) = '0' then if Inst(9) = '0' and Inst(3) = '0' then -- LDD Z Rd_Addr(4 downto 0) <= Inst(8 downto 4); Rr_Addr <= std_logic_vector(Z + unsigned(Disp)); end if; if Inst(9) = '0' and Inst(3) = '1' then -- LDD Y Rd_Addr(4 downto 0) <= Inst(8 downto 4); Rr_Addr <= std_logic_vector(Y + unsigned(Disp)); end if; if Inst(9) = '1' and Inst(3) = '0' then -- STD Z Rr_Addr(4 downto 0) <= Inst(8 downto 4); Rd_Addr <= std_logic_vector(Z + unsigned(Disp)); end if; if Inst(9) = '1' and Inst(3) = '1' then -- STD Y Rr_Addr(4 downto 0) <= Inst(8 downto 4); Rd_Addr <= std_logic_vector(Y + unsigned(Disp)); end if; end if; if Inst(15 downto 9) = "1001000" then Rd_Addr(4 downto 0) <= Inst(8 downto 4); if Inst(3 downto 0) = "0000" then Rr_Addr <= ROM_Data; end if; if Inst(3 downto 0) = "0001" then Rr_Addr <= std_logic_vector(Z); Inc_Z <= '1'; end if; if Inst(3 downto 0) = "0010" then Rr_Addr <= std_logic_vector(Z - 1); Dec_Z <= '1'; end if; if Inst(3 downto 0) = "1001" then Rr_Addr <= std_logic_vector(Y); Inc_Y <= '1'; end if; if Inst(3 downto 0) = "1010" then Rr_Addr <= std_logic_vector(Y - 1); Dec_Y <= '1'; end if; if Inst(3 downto 0) = "1100" then Rr_Addr <= std_logic_vector(X); end if; if Inst(3 downto 0) = "1101" then Rr_Addr <= std_logic_vector(X); Inc_X <= '1'; end if; if Inst(3 downto 0) = "1110" then Rr_Addr <= std_logic_vector(X - 1); Dec_X <= '1'; end if; if Inst(3 downto 0) = "1111" then -- POP Rr_Addr <= std_logic_vector(SP_i + 1); Inc_SP <= '1'; end if; end if; if Inst(15 downto 9) = "1001001" then Rr_Addr(4 downto 0) <= Inst(8 downto 4); if Inst(3 downto 0) = "0000" then Rd_Addr <= ROM_Data; end if; if Inst(3 downto 0) = "0001" then Rd_Addr <= std_logic_vector(Z); Inc_Z <= '1'; end if; if Inst(3 downto 0) = "0010" then Rd_Addr <= std_logic_vector(Z - 1); Dec_Z <= '1'; end if; if Inst(3 downto 0) = "1001" then Rd_Addr <= std_logic_vector(Y); Inc_Y <= '1'; end if; if Inst(3 downto 0) = "1010" then Rd_Addr <= std_logic_vector(Y - 1); Dec_Y <= '1'; end if; if Inst(3 downto 0) = "1100" then Rd_Addr <= std_logic_vector(X); end if; if Inst(3 downto 0) = "1101" then Rd_Addr <= std_logic_vector(X); Inc_X <= '1'; end if; if Inst(3 downto 0) = "1110" then Rd_Addr <= std_logic_vector(X - 1); Dec_X <= '1'; end if; if Inst(3 downto 0) = "1111" then -- PUSH Rd_Addr <= std_logic_vector(SP_i); Dec_SP <= '1'; end if; end if; else if Inst(15 downto 9) = "1000000" then -- LD Z Rd_Addr(4 downto 0) <= Inst(8 downto 4); Rr_Addr <= std_logic_vector(Z); end if; if Inst(15 downto 9) = "1000001" then -- ST Z Rr_Addr(4 downto 0) <= Inst(8 downto 4); Rd_Addr <= std_logic_vector(Z); end if; end if; end if; if ((DidPause /= "01" and (Inst = "1001010100001001" or Inst(15 downto 12) = "1101")) or IPush = '1') and BigISet then -- RCALL, ICALL Rd_Addr <= std_logic_vector(SP_i); Dec_SP <= '1'; end if; if DidPause(0) = DidPause(1) and (Inst = "1001010100001000" or Inst = "1001010100011000") and BigISet then -- RET, RETI Rr_Addr <= std_logic_vector(SP_i + 1); Inc_SP <= '1'; end if; if DidPause = "00" and Inst = "1001010111001000" and BigISet then -- LPM Rd_Addr(4 downto 0) <= (others => '0'); end if; end process; process (Inst, DidPause, Rd_Addr, Rr_Addr, Dec_SP, Inc_SP, Z) begin IO_IR <= '0'; RAM_IR <= '0'; PMH_IR <= '0'; PML_IR <= '0'; Reg_IW <= '0'; IO_IW <= '0'; RAM_IW <= '0'; if (DidPause = "00" and ((Inst(15 downto 14) = "10" and Inst(12) = '0') or -- LDD/STD Inst(15 downto 10) = "100100")) or -- LD/ST (Dec_SP = '1' or Inc_SP = '1') then if (Dec_SP = '0' and Inc_SP = '0' and Inst(9) = '0') or Inc_SP = '1' then -- LD if Rr_Addr(15 downto 5) = "00000000000" then elsif Rr_Addr(15 downto 7) = "000000000" and Rr_Addr(10 downto 9) /= "00" and Rr_Addr(10 downto 9) /= "11" then IO_IR <= '1'; else RAM_IR <= '1'; end if; if not (Inst = "1001010100001000" or Inst = "1001010100011000") then -- not RETx Reg_IW <= '1'; end if; else if Rd_Addr(15 downto 5) = "00000000000" then Reg_IW <= '1'; elsif Rd_Addr(15 downto 7) = "000000000" and Rd_Addr(10 downto 9) /= "00" and Rd_Addr(10 downto 9) /= "11" then IO_IW <= '1'; else RAM_IW <= '1'; end if; end if; end if; if DidPause = "00" and Inst = "1001010111001000" then -- LPM Reg_IW <= '1'; PMH_IR <= Z(0); PML_IR <= not Z(0); end if; end process; -- IO access SP <= std_logic_vector(SP_i); IO_Addr <= IO_Addr_i; IO_Rd <= IO_Rd_i; IO_Wr <= IO_Wr_i; IO_WData <= IO_BMData when Inst(15 downto 11) = "10011" and Inst(8) = '0' else Rd_Data; IO_BTest <= Bit_Pattern and IO_RData; IOZ_Skip <= '1' when ((IO_BTest /= "00000000") and (Do_SBIS = '1')) or ((IO_BTest = "00000000") and (Do_SBIC = '1')) else '0'; process (Reset_n, Clk) begin if Reset_n = '0' then if BigISet then SP_i <= (others => '0'); end if; IO_Addr_i <= (others => '0'); IO_BMData <= (others => '0'); IO_Wr_i <= '0'; Do_SBIC <= '0'; Do_SBIS <= '0'; elsif Clk'event and Clk = '1' then Do_SBIC <= '0'; Do_SBIS <= '0'; if ROM_Data(15 downto 8) = "10011001" and PreDecode = '1' then Do_SBIC <= '1'; end if; if ROM_Data(15 downto 8) = "10011011" and PreDecode = '1' then Do_SBIS <= '1'; end if; if (Inst(15 downto 11) = "10011" and Inst(8) = '0' and DidPause(0) = '0') or (ROM_Data(15 downto 11) = "10111" and PreDecode = '1') or IO_IW = '1' then IO_Wr_i <= '1'; else IO_Wr_i <= '0'; end if; IO_BMData <= IO_RData; IO_BMData(to_integer(unsigned(Inst(2 downto 0)))) <= Inst(9); -- CBI, SBI if Inst(15 downto 10) /= "100110" or DidPause(0) = '1' then if ROM_Data(13) = '0' then IO_Addr_i <= "0" & ROM_Data(7 downto 3); else IO_Addr_i <= ROM_Data(10 downto 9) & ROM_Data(3 downto 0); end if; end if; if IO_IR = '1' then IO_Addr_i <= std_logic_vector(resize(unsigned(Rr_Addr) - 32, 6)); end if; if IO_IW = '1' then IO_Addr_i <= std_logic_vector(resize(unsigned(Rd_Addr) - 32, 6)); end if; if IO_Wr_i = '1' and BigISet then if IO_Addr_i = "111101" then --$3D ($5D) SPL Stack Pointer Low SP_i(7 downto 0) <= unsigned(Rd_Data); end if; if IO_Addr_i = "111110" then --$3E ($5E) SPH Stack Pointer High SP_i(15 downto 8) <= unsigned(Rd_Data); end if; end if; if Dec_SP = '1' and BigISet then SP_i <= SP_i - 1; end if; if Inc_SP = '1' and BigISet then SP_i <= SP_i + 1; end if; end if; end process; -- Instruction register Inst_Skip <= Z_Skip or RJmp or ZJmp or IOZ_Skip or Sleep or IPending or IPush; process (Reset_n, Clk) begin if Reset_n = '0' then Rst_r <= '1'; Inst <= (others => '0'); -- Force NOP at reset. DidPause <= "00"; Bit_Pattern <= "00000000"; elsif Clk'event and Clk = '1' then Rst_r <= '0'; if DidPause = "00" then DidPause <= Pause; else DidPause <= std_logic_vector(unsigned(DidPause) - 1); end if; if (Pause /= "00" and DidPause = "00") or DidPause(1) = '1' then -- Pause: instruction retained elsif Rst_r = '1' or Inst_Skip = '1' then -- Skip/flush: NOP insertion Inst <= (others => '0'); else Inst <= ROM_Data; end if; case ROM_Data(2 downto 0) is when "000" => Bit_Pattern <= "00000001"; when "001" => Bit_Pattern <= "00000010"; when "010" => Bit_Pattern <= "00000100"; when "011" => Bit_Pattern <= "00001000"; when "100" => Bit_Pattern <= "00010000"; when "101" => Bit_Pattern <= "00100000"; when "110" => Bit_Pattern <= "01000000"; when others => Bit_Pattern <= "10000000"; end case; end if; end process; -- Status register SREG <= SREG_i; process (Reset_n, Clk) begin if Reset_n = '0' then SREG_i <= "00000000"; elsif Clk'event and Clk = '1' then if IO_Wr_i = '1' and IO_Addr_i = "111111" then --$3F ($5F) SREG Status Register SREG_i <= Rd_Data; end if; if Inst(15 downto 8) = "10010100" and Inst(3 downto 0) = "1000" then SREG_i(to_integer(unsigned(Inst(6 downto 4)))) <= not Inst(7); -- BSET, BCLR end if; if Inst = "1001010100011000" then SREG_i(7) <= '1'; end if; if IPush = '1' then SREG_i(7) <= '0'; end if; if Status_Wr(6) = '1' then SREG_i(6) <= Status_D(6); end if; if Status_Wr(5) = '1' then SREG_i(5) <= Status_D(5); end if; if Status_Wr(4) = '1' then SREG_i(4) <= Status_D(4); end if; if Status_Wr(3) = '1' then SREG_i(3) <= Status_D(3); end if; if Status_Wr(2) = '1' then SREG_i(2) <= Status_D(2); end if; if Status_Wr(1) = '1' then SREG_i(1) <= Status_D(1); end if; if Status_Wr(0) = '1' then SREG_i(0) <= Status_D(0); end if; if Status_D_Wr = '1' and BigISet then SREG_i(4 downto 0) <= Status_D_R; end if; end if; end process; -- Registers process (Clk) begin if Clk'event and Clk = '1' then Add <= '0'; Sub <= '0'; if BigISet then Status_D_Wr <= '0'; if ROM_Data(15 downto 8) = "10010110" and PreDecode = '1' then Add <= '1'; end if; if ROM_Data(15 downto 8) = "10010111" and PreDecode = '1' then Sub <= '1'; end if; if Inst(15 downto 9) = "1001011" and DidPause = "00" then Status_D_Wr <= '1'; end if; end if; end if; end process; AS_Offset(5 downto 4) <= Inst(7 downto 6); AS_Offset(3 downto 0) <= Inst(3 downto 0); pr : AX_Reg generic map( BigISet => BigISet) port map ( Clk => Clk, Reset_n => Reset_n, Wr => Reg_Wr, Rd_Addr => Rd_Addr(4 downto 0), Rr_Addr => Rr_Addr(4 downto 0), Data_In => Wr_Data, Rd_Data => Rd_Data, Rr_Data => Rr_Data, Add => Add, Sub => Sub, AS_Offset => AS_Offset, AS_Reg => Inst(5 downto 4), Dec_X => Dec_X, Dec_Y => Dec_Y, Dec_Z => Dec_Z, Inc_X => Inc_X, Inc_Y => Inc_Y, Inc_Z => Inc_Z, X => X, Y => Y, Z => Z, Status_D => Status_D_R); -- RAM g1 : if BigISet generate dr : AX_RAM generic map( RAMAddressWidth => RAMAddressWidth) port map ( Clk => Clk, Rd_Addr => Rr_Addr(RAMAddressWidth downto 0), Wr_Addr => Rd_Addr(RAMAddressWidth downto 0), Wr => RAM_Wr_ID, Data_In => Wr_Data, Data_Out => RAM_Data); end generate; -- Program counter ROM_Addr <= "0" & std_logic_vector(Z(ROMAddressWidth - 1 downto 1)) when Inst = "1001010111001000" and DidPause = "00" else NPC(ROMAddressWidth - 1 downto 0); PCPause <= '1' when Rst_r = '1' or (IndSkip = '0' and ((Pause /= "00" and DidPause = "00") or DidPause(1) = '1')) or Sleep = '1' else '0'; RJmp <= '1' when Inst(15 downto 12) = "1100" or (Inst(15 downto 12) = "1101" and DidPause = "10") or (CBranch = '1' and Inst(10) = '0' and ((SREG_i and Bit_Pattern) /= "00000000")) or (CBranch = '1' and Inst(10) = '1' and ((SREG_i and Bit_Pattern) = "00000000")) else '0'; HRet <= '1' when DidPause = "11" and BigIset and (Inst = "1001010100001000" or Inst = "1001010100011000") else '0'; LRet <= '1' when DidPause = "10" and BigIset and (Inst = "1001010100001000" or Inst = "1001010100011000") else '0'; ZJmp <= '1' when (Inst = "1001010000001001" or (DidPause = "10" and Inst = "1001010100001001")) and BigIset else '0'; Push <= '1' when (Inst(15 downto 12) = "1101" or Inst = "1001010100001001") and DidPause = "00" and not BigIset else '0'; Pop <= '1' when Inst(15 downto 5) = "10010101000" and Inst(3 downto 0) = "1000" and DidPause = "00" and not BigIset else '0'; CBranch <= '1' when Inst(15 downto 11) = "11110" else '0'; -- Used for >=2 cycles instructions that are not skip, jump or branch Pause <= "01" when (Inst(15 downto 14) = "10" and Inst(12) = '0') or -- LDD/STD Inst(15 downto 10) = "100100" or -- LD/ST (Inst(15 downto 11) = "10011" and Inst(8) = '0') or -- CBI/SBI Inst(15 downto 9) = "1001011" else -- ADIW/SBIW "10" when Inst(15 downto 12) = "1101" or -- RCALL Inst = "1001010100001001" or -- ICALL Inst = "1001010110001000" or -- SLEEP Inst = "1001010111001000" else -- LPM "11" when Inst = "1001010100001000" or -- RET Inst = "1001010100011000" else "00"; -- RETI IndSkip <= '1' when (Inst(15 downto 10) = "100100" and Inst(3 downto 0) = "0000") else '0'; Offset <= Inst(11 downto 0) when CBranch = '0' else std_logic_vector(resize(signed(Inst(9 downto 3)),12)); pcnt : AX_PCS generic map( HW_Stack => not BigISet) port map ( Clk => Clk, Reset_n => Reset_n, Offs_In => Offset, Z => Z, Data_In => Wr_Data, Pause => PCPause, Push => Push, Pop => Pop, HRet => HRet, LRet => LRet, ZJmp => ZJmp, RJmp => RJmp, CInt => CInt, IPending => IPending, IPush => IPush, NPC => NPC, PC => PC); -- ALU PassB <= '1' when (Pause /= "00" and DidPause /= "01") or IPush = '1' else '0'; gNoTri : if not TriState generate Pass_Mux <= Inst(11 downto 8) & Inst(3 downto 0) when Imm_Op = '1' else RAM_Data when RAM_Rd = '1' else PCH when HPC_Rd = '1' and BigIset else PC(7 downto 0) when LPC_Rd = '1' and BigIset else Rr_Data when Reg_Rd = '1' else ROM_Data(15 downto 8) when PMH_Rd = '1' and BigIset else ROM_Data(7 downto 0) when PML_Rd = '1' and BigIset else IO_RData; end generate; gTri : if TriState generate Pass_Mux <= Inst(11 downto 8) & Inst(3 downto 0) when Imm_Op = '1' else "ZZZZZZZZ"; Pass_Mux <= IO_RData when IO_Rd_i = '1' else "ZZZZZZZZ"; Pass_Mux <= RAM_Data when RAM_Rd = '1' else "ZZZZZZZZ"; Pass_Mux <= PCH when HPC_Rd = '1' and BigIset else "ZZZZZZZZ"; Pass_Mux <= PC(7 downto 0) when LPC_Rd = '1' and BigIset else "ZZZZZZZZ"; Pass_Mux <= Rr_Data when Reg_Rd = '1' else "ZZZZZZZZ"; Pass_Mux <= ROM_Data(15 downto 8) when PMH_Rd = '1' and BigIset else "ZZZZZZZZ"; Pass_Mux <= ROM_Data(7 downto 0) when PML_Rd = '1' and BigIset else "ZZZZZZZZ"; end generate; Wr_Data <= Pass_Mux when Do_Other = '1' else Q; Op_Mux <= Inst(11 downto 8) & Inst(3 downto 0) when Imm_Op = '1' else Rr_Data; process (Clk) begin if Clk'event and Clk = '1' then PCH <= PC(15 downto 8); IO_Rd_i <= '0'; Imm_Op <= '0'; RAM_Rd <= '0'; Reg_Rd <= '0'; HPC_Rd <= '0'; LPC_Rd <= '0'; PMH_Rd <= '0'; PML_Rd <= '0'; if (ROM_Data(15 downto 12) = "0011" or ROM_Data(15 downto 14) = "01" or ROM_Data(15 downto 12) = "1110") and PreDecode = '1' then Imm_Op <= '1'; elsif RAM_IR = '1' then RAM_Rd <= '1'; elsif PMH_IR = '1' and BigIset then PMH_Rd <= '1'; elsif PML_IR = '1' and BigIset then PML_Rd <= '1'; elsif ((ROM_Data(15 downto 10) = "100110" or ROM_Data(15 downto 11) = "10110") and PreDecode = '1') or IO_IR = '1' then IO_Rd_i <= '1'; elsif ((DidPause = "10" and (Inst = "1001010100001001" or Inst(15 downto 12) = "1101")) or (IPush = '1' and IPending = '0')) and BigIset then HPC_Rd <= '1'; elsif ((DidPause = "00" and (Inst = "1001010100001001" or Inst(15 downto 12) = "1101")) or (IPush = '1' and IPending = '1')) and BigIset then LPC_Rd <= '1'; else Reg_Rd <= '1'; end if; end if; end process; alu : AX_ALU port map( Clk => Clk, ROM_Data => ROM_Data, A => Rd_Data, B => Op_Mux, Q => Q, SREG => SREG_i, PassB => PassB, Skip => Inst_Skip, Do_Other => Do_Other, Z_Skip => Z_Skip, Status_D => Status_D, Status_Wr => Status_Wr); -- Interrupts and stuff process (Reset_n, Clk) begin if Reset_n = '0' then WDR <= '1'; Sleep <= '0'; CInt <= "0000"; Int_Acc <= (others => '0'); IPending <= '0'; elsif Clk'event and Clk = '1' then if Inst = "1001010110101000" then WDR <= '1'; else WDR <= '0'; end if; if Inst = "1001010110001000" and Sleep_En = '1' then Sleep <= '1'; end if; if Int_Trig /= "000000000000000" and SREG_i(7) = '1' then Sleep <= '0'; IPending <= '1'; end if; Int_Acc <= (others => '0'); if IPending = '1' and IPush = '1' then IPending <= '0'; if Int_Trig(1) = '1' then CInt <= "0001"; Int_Acc(1) <= '1'; elsif Int_Trig(2) = '1' then CInt <= "0010"; Int_Acc(2) <= '1'; elsif Int_Trig(3) = '1' then CInt <= "0011"; Int_Acc(3) <= '1'; elsif Int_Trig(4) = '1' then CInt <= "0100"; Int_Acc(4) <= '1'; elsif Int_Trig(5) = '1' then CInt <= "0101"; Int_Acc(5) <= '1'; elsif Int_Trig(6) = '1' then CInt <= "0110"; Int_Acc(6) <= '1'; elsif Int_Trig(7) = '1' then CInt <= "0111"; Int_Acc(7) <= '1'; elsif Int_Trig(8) = '1' then CInt <= "1000"; Int_Acc(8) <= '1'; elsif Int_Trig(9) = '1' then CInt <= "1001"; Int_Acc(9) <= '1'; elsif Int_Trig(10) = '1' then CInt <= "1010"; Int_Acc(10) <= '1'; elsif Int_Trig(11) = '1' then CInt <= "1011"; Int_Acc(11) <= '1'; elsif Int_Trig(12) = '1' then CInt <= "1100"; Int_Acc(12) <= '1'; elsif Int_Trig(13) = '1' then CInt <= "1101"; Int_Acc(13) <= '1'; elsif Int_Trig(14) = '1' then CInt <= "1110"; Int_Acc(14) <= '1'; elsif Int_Trig(15) = '1' then CInt <= "1111"; Int_Acc(15) <= '1'; end if; end if; if Inst = "1001010100011000" then CInt <= "0000"; end if; end if; end process; end;