基于VHDL仿真实现x86版CPU(数字逻辑)

在这里插入图片描述

代码联系二维码免费获取。

1 x86的划时代意义(可跳过)

  早期的IBM凭借大型机技术成为计算机市场的领头羊,直到后来个人计算机兴起,苹果公司诞生。但是,那个时候,无论是大型机还是个人计算机,每家的CPU架构都不一样。如果一直是这样,个人电脑、平板电脑、手机等等,都没办法形成统一的体系,就不会有我们现在通用的计算机了,更别提什么云计算、大数据这些统一的大平台了。

  好在历史将x86平台推到了开放、统一、兼容的位置。我们继续来看IBM和x86的故事。

  IBM开始做IBM PC时,一开始并没有让最牛的华生实验室去研发,而是交给另一个团队。一年时间,软硬件全部自研根本不可能完成,于是他们采用了英特尔的8088芯片作为CPU,使用微软的MS-DOS做操作系统。

  谁能想到IBM PC卖的超级好,好到因为垄断市场而被起诉。IBM就在被逼的情况下公开了一些技术,使得后来无数IBM-PC兼容机公司的出现,也就有了后来占据市场的惠普、戴尔等等。

在这里插入图片描述

  能够开放自己的技术是一件了不起的事。从技术和发展的层面来讲,它会使得一项技术大面积铺开,形成行业标准。就比如现在常用的Android手机,如果没有开放的Android系统,我们也没办法享受到这么多不同类型的手机。

  对于当年的PC机来说,其实也是这样。英特尔的技术因此成为了行业的开放事实标准。由于这个系列开端于8086,因此称为x86架构。

  后来英特尔的CPU数据总线和地址总线越来越宽,处理能力越来越强。但是一直不能忘记三点,一是标准,二是开放,三是兼容。因为如此大的一个软硬件生态都要基于这个架构,如果是封闭或者不兼容的,那谁都不答应。

在这里插入图片描述

2 自己设计简易版CPU原理

2.1 指令集设计

在这里插入图片描述

2.2 数据通路

在这里插入图片描述

3 VHDL代码实现

3.1 设计的整体架构

在这里插入图片描述
图片有点模糊,只要观察到整体的设计感即可。

3.2 各模块的具体实现

3.2.1 计数器模块PC

在这里插入图片描述
时钟上升沿控制,从00000000开始计数,当LD_PC有效时计数加一,当Lod_PC有效时输出当前计数值。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity PC is
	PORT (
		reset,clk:in std_logic;
		PC_in: in std_logic_vector(7 downto 0);PC_out: out std_logic_vector(7 downto 0);
		Lod_PC,LD_PC:in std_logic
		);end PC;
architecture PC_ar of PC is  
        signal data:std_logic_vector(7 downto 0):="00000000";            
begin
  process (clk,Lod_PC,LD_PC,reset)
    begin	
	if reset='1' then
		PC_out<="10000000";
	else
			if (clk'event and clk='1' and Lod_PC='1')then
						data<=PC_in;					
					end if; 
			if(clk'event and clk='1' and LD_PC='1') then
				data<=data+1;				
			end if;	
	end if;
		PC_out<=data;							
  end process;
  end PC_ar;

3.2.2 通用寄存器组模块common_reg

在这里插入图片描述

  • 输入:RE为读控制信号,WE为写控制信号,WA[1…0]为寄存器编号00代表A,01代表B,10和11代表C,reg_in[7…0]为寄存器输入信号;
  • 输出:reg_out[7…0]代表通用寄存器输出信号;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity common_reg is
	port(RE,WE,clk:in std_logic;
		WA:in std_logic_vector(1 downto 0);
		RA:in std_logic_vector(1 downto 0);
		reg_out:out std_logic_vector(7 downto 0);
		reg_in:in std_logic_vector(7 downto 0);
		reset:in std_logic
		);
		
end common_reg;

architecture reg_ar of common_reg is
signal A:std_logic_vector(7 downto 0):="00000011";
signal B:std_logic_vector(7 downto 0):="10110100";
signal C:std_logic_vector(7 downto 0):="00000111";
begin
	process(clk,WE,RE,reset)
	begin
	if reset='1' then
		if(clk'event and clk='1') then
			if(WE='1') then
				if(WA="00") then
					A<=reg_in;
					reg_out<=A;
				elsif(WA="01") then
					B<=reg_in;
					reg_out<=B;
				elsif(WA="10" or WA="11") then
					C<=reg_in;
					reg_out<=C;
				end if;
			elsif (RE='1') then	
				if(RA="00") then
					reg_out<=A;
				elsif(RA="01") then
					reg_out<=B;
				elsif(RA="10" or RA="11") then
					reg_out<=C;	
				end if;
				end if;
		end if;
	else
		reg_out<="00000000";	
	end if;	
	end process;	
end reg_ar;

3.2.3 选择器模块xuanzeqi

在这里插入图片描述
lod为选择控制信号,lod=0时输出B,lod=1时输出A;

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity xuanzeqi is
	port(lod:in std_logic;
		A,B: in std_logic_vector(7 downto 0);
		data_out: out std_logic_vector(7 downto 0));
end xuanzeqi;

architecture xuanzeqi_ar of xuanzeqi is
signal temp:std_logic_vector(7 downto 0);
begin
	process(lod,A)
	begin
			if(lod='1') then
				temp<=A;
				data_out<=temp;	
			else 
				temp<=B;
				data_out<=temp;	
			end if;
	end process;		
end xuanzeqi_ar;

3.2.4 暂存器/指令寄存器IR模块:jicunqi

在这里插入图片描述
lod为选择控制信号,lod=1时输出jicun_in[7…0],lod=0时输出之前的值;

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;
entity jicunqi is
	port(lod,clk:in std_logic;
		jicun_in: in std_logic_vector(7 downto 0);
		jicun_out: out std_logic_vector(7 downto 0));
end jicunqi;

architecture jicunqi_ar of jicunqi is
signal temp: std_logic_vector(7 downto 0);
begin
	process(clk,lod,jicun_in)
	begin	
		if(clk'event and clk='1') then
			if(lod='1') then	
				temp <= jicun_in;
				jicun_out <= temp;	
			else
				temp<=temp;
				jicun_out <= temp;
			end if;
		end if;
	end process;	
end jicunqi_ar;

3.2.5 地址寄存器寄存器模块:MAR

在这里插入图片描述
Lod_MAR为选择控制信号,Lod_MAR=1时输出MAR_in[7…0],Lod_MAR=0时输出之前的值;

library ieee;
use ieee.std_logic_1164.all;
entity MAR is
port(
    lod_MAR:in std_logic;
    clk,reset:in std_logic; 
    MARin:in std_logic_vector
  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
CPU寄存器组是CPU中的一个重要组成部分,它用于存储CPU中的数据和指令。在VHDL语言中实现CPU寄存器组的设计,需要按照以下步骤进行: 1. 定义寄存器组的输入输出端口,包括数据输入端口、地址输入端口、读写控制端口和数据输出端口等。 2. 建立寄存器组的存储单元,每个存储单元可以用一个D触发器来实现。在VHDL中可以使用“process”语句来实现存储单元的逻辑功能。 3. 编写读写控制逻辑,根据读写控制信号的不同,将数据写入到指定的存储单元中或从指定的存储单元中读取数据。在VHDL中可以使用“if-else”语句或“case”语句来实现读写控制逻辑。 4. 将所有的存储单元按照地址进行编址,形成一个寄存器组。在VHDL中可以使用数组来实现寄存器组的编址。 5. 对寄存器组进行仿真测试,验证其功能是否正确。 下面是一个使用VHDL语言实现CPU寄存器组的示例代码: ``` entity register_file is port ( clk : in std_logic; reset : in std_logic; reg_wen : in std_logic; reg_addr: in std_logic_vector(4 downto 0); reg_data_in : in std_logic_vector(31 downto 0); reg_data_out: out std_logic_vector(31 downto 0) ); end entity register_file; architecture rtl of register_file is type register_array is array(0 to 31) of std_logic_vector(31 downto 0); signal registers : register_array; begin process(clk, reset) begin if reset = '1' then for i in 0 to 31 loop registers(i) <= (others => '0'); end loop; elsif rising_edge(clk) then if reg_wen = '1' then registers(to_integer(unsigned(reg_addr))) <= reg_data_in; end if; end if; end process; reg_data_out <= registers(to_integer(unsigned(reg_addr))); end architecture rtl; ``` 在上面的示例代码中,我们使用了一个数组来实现寄存器组的编址,每个存储单元使用了一个32位的向量来实现。在process语句中,我们实现了存储单元的逻辑功能,当reg_wen为1时,将reg_data_in写入到指定的存储单元中;当reg_wen为0时,则从指定的存储单元中读取数据,并将其输出到reg_data_out端口中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王曾是少年

如果对你有帮助,欢迎支持我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值