⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu01.vhd

📁 一个简单的cpu的VHDL源码描述
💻 VHD
📖 第 1 页 / 共 5 页
字号:
--===========================================================================--
--
--  S Y N T H E Z I A B L E    CPU01   C O R E
--
--  www.OpenCores.Org - December 2002
--  This core adheres to the GNU public license  
--
-- File name      : cpu01.vhd
--
-- Purpose        : Implements a 6801 compatible CPU core
--                  
-- Dependencies   : ieee.Std_Logic_1164
--                  ieee.std_logic_unsigned
--
-- Author         : John E. Kent      
--
--===========================================================================----
--
-- Revision History:
--
-- Date:          Revision         Author
-- 22 Sep 2002    0.1              John Kent
--
-- 30 Oct 2002    0.2              John Kent
-- made NMI edge triggered
--
-- 30 Oct 2002    0.3              John Kent
-- more corrections to NMI
-- added wai_wait_state to prevent stack overflow on wai.
--
--  1 Nov 2002    0.4              John Kent
-- removed WAI states and integrated WAI with the interrupt service routine
-- replace Data out (do) and Data in (di) register with a single Memory Data (md) reg.
-- Added Multiply instruction states.
-- run ALU and CC out of CPU module for timing measurements.
-- 
--  3 Nov 2002    0.5              John Kent
-- Memory Data Register was not loaded on Store instructions
-- SEV and CLV were not defined in the ALU
-- Overflow Flag on NEG was incorrect
--
-- 16th Feb 2003  0.6              John Kent
-- Rearranged the execution cycle for dual operand instructions
-- so that occurs during the following fetch cycle.
-- This allows the reduction of one clock cycle from dual operand
-- instruction. Note that this also necessitated re-arranging the
-- program counter so that it is no longer incremented in the ALU.
-- The effective address has also been re-arranged to include a 
-- separate added. The STD (store accd) now sets the condition codes.
--
-- 28th Jun 2003 0.7               John Kent
-- Added Hold and Halt signals. Hold is used to steal cycles from the
-- CPU or add wait states. Halt puts the CPU in the inactive state
-- and is only honoured in the fetch cycle. Both signals are active high.
--
-- 24 Aug 2003 1.0                John Kent
-- Converted 6800 core to 6801 by removing alu_cpx
-- Also added 4 extra interrupt inputs
--
-- 16 January 2004 1.1            John Kent (by Michael Hasenfratz)
-- Failure to clear carry bit during CLR instructions
-- Corrected CLR instructions to set alu_ctrl to alu_clr instead of alu_ld8.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity cpu01 is
	port (	
		clk:	    in  std_logic;
		rst:	    in  std_logic;
		rw:	    out std_logic;
		vma:	    out std_logic;
		address:	 out std_logic_vector(15 downto 0);
		data_in:	 in  std_logic_vector(7 downto 0);
		data_out: out std_logic_vector(7 downto 0);
		hold:     in  std_logic;
		halt:     in  std_logic;
		irq:      in  std_logic;
		nmi:      in  std_logic;
		irq_icf:  in  std_logic;
		irq_ocf:  in  std_logic;
		irq_tof:  in  std_logic;
		irq_sci:  in  std_logic;
		test_alu: out std_logic_vector(15 downto 0);
		test_cc:  out std_logic_vector(7 downto 0)
		);
end;

architecture CPU_ARCH of cpu01 is

  constant SBIT : integer := 7;
  constant XBIT : integer := 6;
  constant HBIT : integer := 5;
  constant IBIT : integer := 4;
  constant NBIT : integer := 3;
  constant ZBIT : integer := 2;
  constant VBIT : integer := 1;
  constant CBIT : integer := 0;

	type state_type is (reset_state, fetch_state, decode_state,
                       extended_state, indexed_state, read8_state, read16_state, immediate16_state,
	                    write8_state, write16_state,
						     execute_state, halt_state, error_state,
						     mul_state, mulea_state, muld_state,
						     mul0_state, mul1_state, mul2_state, mul3_state,
						     mul4_state, mul5_state, mul6_state, mul7_state,
							  jmp_state, jsr_state, jsr1_state,
						     branch_state, bsr_state, bsr1_state, 
							  rts_hi_state, rts_lo_state,
							  int_pcl_state, int_pch_state,
						     int_ixl_state, int_ixh_state,
						     int_cc_state, int_acca_state, int_accb_state,
						     int_wai_state, int_mask_state,
						     rti_state, rti_cc_state, rti_acca_state, rti_accb_state,
						     rti_ixl_state, rti_ixh_state,
						     rti_pcl_state, rti_pch_state,
							  pula_state, psha_state, pulb_state, pshb_state,
						     pulx_lo_state, pulx_hi_state, pshx_lo_state, pshx_hi_state,
							  vect_lo_state, vect_hi_state );
	type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, push_ad, pull_ad, int_hi_ad, int_lo_ad );
	type dout_type is (md_lo_dout, md_hi_dout, acca_dout, accb_dout, ix_lo_dout, ix_hi_dout, cc_dout, pc_lo_dout, pc_hi_dout );
   type op_type is (reset_op, fetch_op, latch_op );
   type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca );
   type accb_type is (reset_accb, load_accb, pull_accb, latch_accb );
   type cc_type is (reset_cc, load_cc, pull_cc, latch_cc );
	type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix );
	type sp_type is (reset_sp, latch_sp, load_sp );
	type pc_type is (reset_pc, latch_pc, load_ea_pc, add_ea_pc, pull_lo_pc, pull_hi_pc, inc_pc );
   type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md );
   type ea_type is (reset_ea, latch_ea, add_ix_ea, load_accb_ea, inc_ea, fetch_first_ea, fetch_next_ea );
	type iv_type is (reset_iv, latch_iv, swi_iv, nmi_iv, irq_iv, icf_iv, ocf_iv, tof_iv, sci_iv );
	type nmi_type is (reset_nmi, set_nmi, latch_nmi );
	type left_type is (acca_left, accb_left, accd_left, md_left, ix_left, sp_left );
	type right_type is (md_right, zero_right, plus_one_right, accb_right );
   type alu_type   is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc, 
                       alu_and, alu_ora, alu_eor,
                       alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com,
							  alu_inx, alu_dex,
						     alu_lsr16, alu_lsl16,
						     alu_ror8, alu_rol8,
						     alu_asr8, alu_asl8, alu_lsr8,
						     alu_sei, alu_cli, alu_sec, alu_clc, alu_sev, alu_clv, alu_tpa, alu_tap,
						     alu_ld8, alu_st8, alu_ld16, alu_st16, alu_nop, alu_daa );

	signal op_code:     std_logic_vector(7 downto 0);
  	signal acca:        std_logic_vector(7 downto 0);
  	signal accb:        std_logic_vector(7 downto 0);
   signal cc:          std_logic_vector(7 downto 0);
	signal cc_out:      std_logic_vector(7 downto 0);
	signal xreg:        std_logic_vector(15 downto 0);
	signal sp:          std_logic_vector(15 downto 0);
	signal ea:          std_logic_vector(15 downto 0);
	signal pc:	        std_logic_vector(15 downto 0);
	signal md:          std_logic_vector(15 downto 0);
   signal left:        std_logic_vector(15 downto 0);
   signal right:       std_logic_vector(15 downto 0);
	signal out_alu:     std_logic_vector(15 downto 0);
	signal iv:          std_logic_vector(2 downto 0);
	signal nmi_req:     std_logic;
	signal nmi_ack:     std_logic;

	signal state:       state_type;
	signal next_state:  state_type;
   signal pc_ctrl:     pc_type;
   signal ea_ctrl:     ea_type; 
   signal op_ctrl:     op_type;
	signal md_ctrl:     md_type;
	signal acca_ctrl:   acca_type;
	signal accb_ctrl:   accb_type;
	signal ix_ctrl:     ix_type;
	signal cc_ctrl:     cc_type;
	signal sp_ctrl:     sp_type;
	signal iv_ctrl:     iv_type;
	signal left_ctrl:   left_type;
	signal right_ctrl:  right_type;
   signal alu_ctrl:    alu_type;
   signal addr_ctrl:   addr_type;
   signal dout_ctrl:   dout_type;
   signal nmi_ctrl:    nmi_type;


begin

----------------------------------
--
-- Address bus multiplexer
--
----------------------------------

addr_mux: process( clk, addr_ctrl, pc, ea, sp, iv )
begin
  case addr_ctrl is
    when idle_ad =>
	   address <= "1111111111111111";
		vma     <= '0';
		rw      <= '1';
    when fetch_ad =>
	   address <= pc;
		vma     <= '1';
		rw      <= '1';
	 when read_ad =>
	   address <= ea;
		vma     <= '1';
		rw      <= '1';
    when write_ad =>
	   address <= ea;
		vma     <= '1';
		rw      <= '0';
	 when push_ad =>
	   address <= sp;
		vma     <= '1';
		rw      <= '0';
    when pull_ad =>
	   address <= sp;
		vma     <= '1';
		rw      <= '1';
	 when int_hi_ad =>
	   address <= "111111111111" & iv & "0";
		vma     <= '1';
		rw      <= '1';
    when int_lo_ad =>
	   address <= "111111111111" & iv & "1";
		vma     <= '1';
		rw      <= '1';
	 when others =>
	   address <= "1111111111111111";
		vma     <= '0';
		rw      <= '1';
  end case;
end process;

--------------------------------
--
-- Data Bus output
--
--------------------------------
dout_mux : process( clk, dout_ctrl, md, acca, accb, xreg, pc, cc )
begin
    case dout_ctrl is
	 when md_hi_dout => -- alu output
	   data_out <= md(15 downto 8);
	 when md_lo_dout =>
	   data_out <= md(7 downto 0);
	 when acca_dout => -- accumulator a
	   data_out <= acca;
	 when accb_dout => -- accumulator b
	   data_out <= accb;
	 when ix_lo_dout => -- index reg
	   data_out <= xreg(7 downto 0);
	 when ix_hi_dout => -- index reg
	   data_out <= xreg(15 downto 8);
	 when cc_dout => -- condition codes
	   data_out <= cc;
	 when pc_lo_dout => -- low order pc
	   data_out <= pc(7 downto 0);
	 when pc_hi_dout => -- high order pc
	   data_out <= pc(15 downto 8);
	 when others =>
	   data_out <= "00000000";
    end case;
end process;


----------------------------------
--
-- Program Counter Control
--
----------------------------------

pc_mux: process( clk, pc_ctrl, pc, out_alu, data_in, ea, hold )
variable tempof : std_logic_vector(15 downto 0);
variable temppc : std_logic_vector(15 downto 0);
begin
  case pc_ctrl is
  when add_ea_pc =>
	 if ea(7) = '0' then
	   tempof := "00000000" & ea(7 downto 0);
    else
		tempof := "11111111" & ea(7 downto 0);
    end if;
  when inc_pc =>
	 tempof := "0000000000000001";
  when others =>
    tempof := "0000000000000000";
  end case;

  case pc_ctrl is
  when reset_pc =>
	 temppc := "1111111111111110";
  when load_ea_pc =>
	 temppc := ea;
  when pull_lo_pc =>
	 temppc(7 downto 0) := data_in;
	 temppc(15 downto 8) := pc(15 downto 8);
  when pull_hi_pc =>
	 temppc(7 downto 0) := pc(7 downto 0);
	 temppc(15 downto 8) := data_in;
  when others =>
    temppc := pc;
  end case;

  if clk'event and clk = '0' then
    if hold = '1' then
      pc <= pc;
    else
      pc <= temppc + tempof;
	 end if;
  end if;
end process;

----------------------------------
--
-- Effective Address  Control
--
----------------------------------

ea_mux: process( clk, ea_ctrl, ea, out_alu, data_in, accb, xreg, hold )
variable tempind : std_logic_vector(15 downto 0);
variable tempea  : std_logic_vector(15 downto 0);
begin
  case ea_ctrl is
  when add_ix_ea =>
	 tempind := "00000000" & ea(7 downto 0);
  when inc_ea =>
	 tempind := "0000000000000001";
  when others =>
    tempind := "0000000000000000";
  end case;

  case ea_ctrl is
  when reset_ea =>
	 tempea := "0000000000000000";
  when load_accb_ea =>
	 tempea := "00000000" & accb(7 downto 0);
  when add_ix_ea =>
	 tempea := xreg;
  when fetch_first_ea =>
	 tempea(7 downto 0) := data_in;
	 tempea(15 downto 8) := "00000000";
  when fetch_next_ea =>
	 tempea(7 downto 0) := data_in;
	 tempea(15 downto 8) := ea(7 downto 0);
  when others =>
    tempea := ea;
  end case;

  if clk'event and clk = '0' then
    if hold = '1' then
      ea <= ea;
    else
      ea <= tempea + tempind;
	 end if;
  end if;
end process;

--------------------------------
--
-- Accumulator A
--
--------------------------------
acca_mux : process( clk, acca_ctrl, out_alu, acca, data_in, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   acca <= acca;
	 else
    case acca_ctrl is
    when reset_acca =>
	   acca <= "00000000";
	 when load_acca =>
	   acca <= out_alu(7 downto 0);
	 when load_hi_acca =>
	   acca <= out_alu(15 downto 8);
	 when pull_acca =>
	   acca <= data_in;
	 when others =>
--	 when latch_acca =>
	   acca <= acca;
    end case;
	 end if;
  end if;
end process;

--------------------------------
--
-- Accumulator B
--
--------------------------------
accb_mux : process( clk, accb_ctrl, out_alu, accb, data_in, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   accb <= accb;
	 else
    case accb_ctrl is
    when reset_accb =>
	   accb <= "00000000";
	 when load_accb =>
	   accb <= out_alu(7 downto 0);
	 when pull_accb =>
	   accb <= data_in;
	 when others =>
--	 when latch_accb =>
	   accb <= accb;
    end case;
	 end if;
  end if;
end process;

--------------------------------
--

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -