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

📄 cpu01.vhd

📁 一个简单的cpu的VHDL源码描述
💻 VHD
📖 第 1 页 / 共 5 页
字号:
-- X Index register
--
--------------------------------
ix_mux : process( clk, ix_ctrl, out_alu, xreg, data_in, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   xreg <= xreg;
	 else
    case ix_ctrl is
    when reset_ix =>
	   xreg <= "0000000000000000";
	 when load_ix =>
	   xreg <= out_alu(15 downto 0);
	 when pull_hi_ix =>
	   xreg(15 downto 8) <= data_in;
	 when pull_lo_ix =>
	   xreg(7 downto 0) <= data_in;
	 when others =>
--	 when latch_ix =>
	   xreg <= xreg;
    end case;
	 end if;
  end if;
end process;

--------------------------------
--
-- stack pointer
--
--------------------------------
sp_mux : process( clk, sp_ctrl, out_alu, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   sp <= sp;
	 else
    case sp_ctrl is
    when reset_sp =>
	   sp <= "0000000000000000";
	 when load_sp =>
	   sp <= out_alu(15 downto 0);
	 when others =>
--	 when latch_sp =>
	   sp <= sp;
    end case;
	 end if;
  end if;
end process;

--------------------------------
--
-- Memory Data
--
--------------------------------
md_mux : process( clk, md_ctrl, out_alu, data_in, md, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   md <= md;
	 else
    case md_ctrl is
    when reset_md =>
	   md <= "0000000000000000";
	 when load_md =>
	   md <= out_alu(15 downto 0);
	 when fetch_first_md =>
	   md(15 downto 8) <= "00000000";
	   md(7 downto 0) <= data_in;
	 when fetch_next_md =>
	   md(15 downto 8) <= md(7 downto 0);
		md(7 downto 0) <= data_in;
	 when shiftl_md =>
	   md(15 downto 1) <= md(14 downto 0);
		md(0) <= '0';
	 when others =>
--	 when latch_md =>
	   md <= md;
    end case;
	 end if;
  end if;
end process;


----------------------------------
--
-- Condition Codes
--
----------------------------------

cc_mux: process( clk, cc_ctrl, cc_out, cc, data_in, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   cc <= cc;
	 else
    case cc_ctrl is
	 when reset_cc =>
	   cc <= "11000000";
	 when load_cc =>
	   cc <= cc_out;
  	 when pull_cc =>
      cc <= data_in;
	 when others =>
--  when latch_cc =>
      cc <= cc;
    end case;
	 end if;
  end if;
end process;

----------------------------------
--
-- interrupt vector
--
----------------------------------

iv_mux: process( clk, iv_ctrl, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   iv <= iv;
	 else
    case iv_ctrl is
	 when reset_iv =>
	   iv <= "111";
	 when nmi_iv =>
      iv <= "110";
  	 when swi_iv =>
      iv <= "101";
	 when irq_iv =>
      iv <= "100";
	 when icf_iv =>
	   iv <= "011";
	 when ocf_iv =>
      iv <= "010";
  	 when tof_iv =>
      iv <= "001";
	 when sci_iv =>
      iv <= "000";
	 when others =>
	   iv <= iv;
    end case;
	 end if;
  end if;
end process;

----------------------------------
--
-- op code fetch
--
----------------------------------

op_fetch: process( clk, data_in, op_ctrl, op_code, hold )
begin
  if clk'event and clk = '0' then
    if hold = '1' then
	   op_code <= op_code;
	 else
    case op_ctrl is
	 when reset_op =>
	   op_code <= "00000001"; -- nop
  	 when fetch_op =>
      op_code <= data_in;
	 when others =>
--	 when latch_op =>
	   op_code <= op_code;
    end case;
	 end if;
  end if;
end process;

----------------------------------
--
-- Left Mux
--
----------------------------------

left_mux: process( left_ctrl, acca, accb, xreg, sp, pc, ea, md )
begin
  case left_ctrl is
	 when acca_left =>
	   left(15 downto 8) <= "00000000";
		left(7 downto 0)  <= acca;
	 when accb_left =>
	   left(15 downto 8) <= "00000000";
		left(7 downto 0)  <= accb;
	 when accd_left =>
	   left(15 downto 8) <= acca;
		left(7 downto 0)  <= accb;
	 when ix_left =>
	   left <= xreg;
	 when sp_left =>
	   left <= sp;
	 when others =>
--	 when md_left =>
	   left <= md;
    end case;
end process;
----------------------------------
--
-- Right Mux
--
----------------------------------

right_mux: process( right_ctrl, data_in, md, accb, ea )
begin
  case right_ctrl is
	 when zero_right =>
	   right <= "0000000000000000";
	 when plus_one_right =>
	   right <= "0000000000000001";
	 when accb_right =>
	   right <= "00000000" & accb;
	 when others =>
--	 when md_right =>
	   right <= md;
    end case;
end process;

----------------------------------
--
-- Arithmetic Logic Unit
--
----------------------------------

mux_alu: process( alu_ctrl, cc, left, right, out_alu, cc_out )
variable valid_lo, valid_hi : boolean;
variable carry_in : std_logic;
variable daa_reg : std_logic_vector(7 downto 0);
begin

  case alu_ctrl is
  	 when alu_adc | alu_sbc |
  	      alu_rol8 | alu_ror8 =>
	   carry_in := cc(CBIT);
  	 when others =>
	   carry_in := '0';
  end case;

  valid_lo := left(3 downto 0) <= 9;
  valid_hi := left(7 downto 4) <= 9;

  if (cc(CBIT) = '0') then
    if( cc(HBIT) = '1' ) then
		if valid_hi then
		  daa_reg := "00000110";
		else
		  daa_reg := "01100110";
	   end if;
    else
		if valid_lo then
		  if valid_hi then
		    daa_reg := "00000000";
		  else
		    daa_reg := "01100000";
		  end if;
		else
	     if( left(7 downto 4) <= 8 ) then
		    daa_reg := "00000110";
		  else
			 daa_reg := "01100110";
		  end if;
		end if;
	 end if;
  else
    if ( cc(HBIT) = '1' )then
		daa_reg := "01100110";
 	 else
		if valid_lo then
		  daa_reg := "01100000";
	   else
		  daa_reg := "01100110";
		end if;
	 end if;
  end if;

  case alu_ctrl is
  	 when alu_add8 | alu_inc |
  	      alu_add16 | alu_inx |
  	      alu_adc =>
		out_alu <= left + right + ("000000000000000" & carry_in);
  	 when alu_sub8 | alu_dec |
  	      alu_sub16 | alu_dex |
  	      alu_sbc =>
	   out_alu <= left - right - ("000000000000000" & carry_in);
  	 when alu_and =>
	   out_alu   <= left and right; 	-- and/bit
  	 when alu_ora =>
	   out_alu   <= left or right; 	-- or
  	 when alu_eor =>
	   out_alu   <= left xor right; 	-- eor/xor
  	 when alu_lsl16 | alu_asl8 | alu_rol8 =>
	   out_alu   <= left(14 downto 0) & carry_in; 	-- rol8/asl8/lsl16
  	 when alu_lsr16 | alu_lsr8 =>
	   out_alu   <= carry_in & left(15 downto 1); 	-- lsr
  	 when alu_ror8 =>
	   out_alu   <= "00000000" & carry_in & left(7 downto 1); 	-- ror
  	 when alu_asr8 =>
	   out_alu   <= "00000000" & left(7) & left(7 downto 1); 	-- asr
  	 when alu_neg =>
	   out_alu   <= right - left; 	-- neg (right=0)
  	 when alu_com =>
	   out_alu   <= not left;
  	 when alu_clr | alu_ld8 | alu_ld16 =>
	   out_alu   <= right; 	         -- clr, ld
	 when alu_st8 | alu_st16 =>
	   out_alu   <= left;
	 when alu_daa =>
	   out_alu   <= left + ("00000000" & daa_reg);
	 when alu_tpa =>
	   out_alu <= "00000000" & cc;
  	 when others =>
	   out_alu   <= left; -- nop
    end case;

	 --
	 -- carry bit
	 --
    case alu_ctrl is
  	 when alu_add8 | alu_adc  =>
      cc_out(CBIT) <= (left(7) and right(7)) or
		                (left(7) and not out_alu(7)) or
						   (right(7) and not out_alu(7));
  	 when alu_sub8 | alu_sbc =>
      cc_out(CBIT) <= ((not left(7)) and right(7)) or
		                ((not left(7)) and out_alu(7)) or
						         (right(7) and out_alu(7));
  	 when alu_add16  =>
      cc_out(CBIT) <= (left(15) and right(15)) or
		                (left(15) and not out_alu(15)) or
						   (right(15) and not out_alu(15));
  	 when alu_sub16 =>
      cc_out(CBIT) <= ((not left(15)) and right(15)) or
		                ((not left(15)) and out_alu(15)) or
						         (right(15) and out_alu(15));
	 when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 =>
	   cc_out(CBIT) <= left(0);
	 when alu_rol8 | alu_asl8 =>
	   cc_out(CBIT) <= left(7);
	 when alu_lsl16 =>
	   cc_out(CBIT) <= left(15);
	 when alu_com =>
	   cc_out(CBIT) <= '1';
	 when alu_neg | alu_clr =>
	   cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
		                out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0); 
    when alu_daa =>
	   if ( daa_reg(7 downto 4) = "0110" ) then
		  cc_out(CBIT) <= '1';
		else
		  cc_out(CBIT) <= '0';
	   end if;
  	 when alu_sec =>
      cc_out(CBIT) <= '1';
  	 when alu_clc =>
      cc_out(CBIT) <= '0';
    when alu_tap =>
      cc_out(CBIT) <= left(CBIT);
  	 when others =>
      cc_out(CBIT) <= cc(CBIT);
    end case;
	 --
	 -- Zero flag
	 --
    case alu_ctrl is
  	 when alu_add8 | alu_sub8 |
	      alu_adc | alu_sbc |
  	      alu_and | alu_ora | alu_eor |
  	      alu_inc | alu_dec | 
			alu_neg | alu_com | alu_clr |
			alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
		   alu_ld8  | alu_st8 =>
      cc_out(ZBIT) <= not( out_alu(7)  or out_alu(6)  or out_alu(5)  or out_alu(4)  or
	                        out_alu(3)  or out_alu(2)  or out_alu(1)  or out_alu(0) );
  	 when alu_add16 | alu_sub16 |
  	      alu_lsl16 | alu_lsr16 |
  	      alu_inx | alu_dex |
		   alu_ld16  | alu_st16 =>
      cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or
	                        out_alu(11) or out_alu(10) or out_alu(9)  or out_alu(8)  or
  	                        out_alu(7)  or out_alu(6)  or out_alu(5)  or out_alu(4)  or
	                        out_alu(3)  or out_alu(2)  or out_alu(1)  or out_alu(0) );
    when alu_tap =>
      cc_out(ZBIT) <= left(ZBIT);
  	 when others =>
      cc_out(ZBIT) <= cc(ZBIT);
    end case;

    --
	 -- negative flag
	 --
    case alu_ctrl is
  	 when alu_add8 | alu_sub8 |
	      alu_adc | alu_sbc |
	      alu_and | alu_ora | alu_eor |
  	      alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
  	      alu_inc | alu_dec | alu_neg | alu_com | alu_clr |
			alu_ld8  | alu_st8 =>
      cc_out(NBIT) <= out_alu(7);
	 when alu_add16 | alu_sub16 |
	      alu_lsl16 | alu_lsr16 |
			alu_ld16 | alu_st16 =>
		cc_out(NBIT) <= out_alu(15);
    when alu_tap =>
      cc_out(NBIT) <= left(NBIT);
  	 when others =>
      cc_out(NBIT) <= cc(NBIT);
    end case;

    --
	 -- Interrupt mask flag

⌨️ 快捷键说明

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