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

本文阅读 11 分钟
首页 代码,Java 正文

img

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

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

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

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

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

img

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

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

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

img

2.1 指令集设计

img

2.2 数据通路

img

3.1 设计的整体架构

img 图片有点模糊,只要观察到整体的设计感即可。

3.2 各模块的具体实现

3.2.1 计数器模块PC

img 时钟上升沿控制,从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

img

  • 输入: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

img 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

img 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

img 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(7 downto 0);
    MARout:out std_logic_vector(7 downto 0)
    );
end MAR;
architecture one of MAR is
signal MARsout:std_logic_vector(7 downto 0);
begin
   process (clk)
   begin 
  if reset='1' then MARout<="00000000";
  else
     if (clk'event and clk='1' and lod_MAR='1') then
        MARout<=MARin;
     end if;
  end if; 
   end process;
end one;

3.2.6 内存模块:RAM

img

  • cs为使能信号,cs=0输出高阻态
  • dl,xl为读写控制信号,当xl为1时,将RAM_in[7…0]写入对应内存;当dl为1是,输出对应内存。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity RAM is
port(dl,xl,cs,clk:in std_logic;
    RAM_in:in std_logic_vector(7 downto 0);
    RAM_out:out std_logic_vector(7 downto 0)
    );
end RAM;

architecture RAM_ar of RAM is
type ram is array(0 to 11) of std_logic_vector(7 downto 0);        --12*8 ram  

signal temp:std_logic_vector(7 downto 0);
begin
process(dl,xl,cs,clk)
    variable r:ram;
    begin
    r(0):="00110001";r(1):="10010001";r(2):="01100001";r(3):="11100010";r(4):="0101000 r(5):="10100000";r(6):="10100011";r(7):="00010000";r(8):="00010001";r(9):="00010010";
    r(10):="01110000";r(11):="10000000";
        if(clk'event and clk='1' and cs='0') then
                if(xl='1' and dl='0') then
                    r(conv_integer(RAM_in(7 downto 0))):=RAM_in    ;
                    
                elsif(dl='1' and xl='0') then
                    temp <= r(conv_integer(RAM_in(7 downto 0))+7);
                end if;
        elsif (clk'event and clk='1' and cs='1') then
            temp<="ZZZZZZZZ";
        end if;
end process;
RAM_out <= temp;
end RAM_ar;

3.2.7 控制输入模块:putin

img in_en为选择信号,当in_en=1时输出外部输入信号cin[7…0],当in_en=0时输出总线数据

library ieee;
use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;
entity putin is
    port(in_en:in std_logic;
         cin:in std_logic_vector(7 downto 0);aluin:in std_logic_vector(7 downto 0);
         clk:in std_logic;cout:out std_logic_vector(7 downto 0));     
end putin;
architecture putin_ar of putin is            
begin
  process(clk,in_en,cin)
  begin
    if(clk'event and clk='1') then
        if in_en='1' then
            cout<="00000111";
        else
            cout<=aluin;
        end if;
    end if;
  end process;
  end putin_ar;

3.2.8 运算模块:ALU

img 输入:

  • M为使能信号,M=1时执行相应运算将结果输出,否则不执行运算
  • S[3…0]为功能段,0011(MOV)直接输出A[7…0];
  • 1001(ADD)计算A[7…0]+B[7…0];
  • 0110(SUB)计算A[7…0]-B[7…0];
  • 1110(AND)计算A[7…0] and B[7…0];
  • 0101(NOT)计算not A[7…0];
  • 1010(SH),0100(out)直接输出A[7…0];

输出:

  • cout为加法运算进位;
  • ALU_out[7…0]为运算器结果;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ALU is
    port(M:in std_logic;
        S:in std_logic_vector(3 downto 0);
        A,B:in std_logic_vector(7 downto 0);
        ALU_out:out std_logic_vector(7 downto 0);
        cout:out std_logic);
end ALU;

architecture ALU_ar of ALU is
signal temp:std_logic_vector(8 downto 0);
begin
    process(S,A,B)
    begin
        if(M='1') then
        case S is
            when "0011"=>
                ALU_out<=A;
            when "1001"=>
                ALU_out<= A+B;
                temp<=('0'&A)+('0'&B);
                cout<=temp(8);
            when "0110"=>
                ALU_out<= A-B;    
            when "1110"=>
                ALU_out<= A and B;
            when "0101"=>
                ALU_out<= not A;
            when "1010"=>
                ALU_out<= A;    
            when "0100"=>
                ALU_out<= A;    
            when others =>NULL;
        end case;
        end if;
    end process;
end ALU_ar;

3.2.9 移位运算模块:yiweiqi

img

  • 输入:ywen为使能端,当ywen=0时,输出高阻;lod_yw为运算开关,lod_yw=1时进行移位运算,ywR2[1…0]为移位模式,ywR2[1…0]=00时右移,ywR2[1…0]=11时左移,其他情况时不进行移位操作直接输出;
  • 输出:ywout[7…0]为移位运算结果。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ALU is
    port(M:in std_logic;
        S:in std_logic_vector(3 downto 0);
        A,B:in std_logic_vector(7 downto 0);
        ALU_out:out std_logic_vector(7 downto 0);
        cout:out std_logic);
end ALU;

architecture ALU_ar of ALU is
signal temp:std_logic_vector(8 downto 0);
begin
    process(S,A,B)
    begin
        if(M='1') then
        case S is
            when "0011"=>
                ALU_out<=A;
            when "1001"=>
                ALU_out<= A+B;
                temp<=('0'&A)+('0'&B);
                cout<=temp(8);
            when "0110"=>
                ALU_out<= A-B;    
            when "1110"=>
                ALU_out<= A and B;
            when "0101"=>
                ALU_out<= not A;
            when "1010"=>
                ALU_out<= A;    
            when "0100"=>
                ALU_out<= A;    
            when others =>NULL;
        end case;
        end if;
    end process;
end ALU_ar;

3.2.10 跳转控制模块:jump

img

  • 输入:JMP、JZ、JC为移位控制信号,JMP=1时执行JMP指令,JZ=1时执行JZ指令,JC=1时执行JC指令; cout为运算结果,当JZ,JC有效时起作用; RAM_in[7…0]和address[7…0]分别为总线数据和目标地址;
  • 输出:ywout[7…0]为移位运算结果。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity jump is
    port(reset:in std_logic;
         JMP,JZ,JC:in std_logic;
         cout:in std_logic;
         RAM_in:in std_logic_vector(7 downto 0);
         address:in std_logic_vector(7 downto 0);
         jump_O:out std_logic_vector(7 downto 0));
end jump;

architecture jump_ar of jump is         
begin
  process (JMP,JZ,JC,reset)
  begin
        if reset='1' then
            jump_O<="00000000";
        else
            if JMP='1' then
                jump_O<=address;
            elsif JZ='1' then
                if cout='0' then
                    jump_O<=address;
                end if;
            elsif JC='1' then
                if cout='1' then
                    jump_O<=address;
                end if;
            else
                jump_O<=RAM_in;
            end if;
        end if;
  end process;
  end jump_ar;

3.2.11 译码控制模块:yimaqi

img

  • 输入:yimaqi_in[7…0]为输入的指令,address_i[7…0]为地址,跳转时有用,contclk为时钟控制信号。
  • 输出:Lod_IR、DL、XL、CS、M、Lod_MAR、Lod_SA、Lod_SB、Lod_xa、Lod_xb、LD_PC、Lod_PC、RE、WE、S[3…0]、RA[1…0]、WA[1…0]、contR2、contlod_yw、contywen、address_o、NOP、reset、in_en、JMP、JZ、JC均为上述提到的控制信号。

控制信号的产生:

  当我们从存储器中取指令到IR后,先对其进行译码操作,译码后可以对不同指令进行不同的执行方法,以调用相应的执行周期。如下为各指令的执行过程:

MOV R1,R2 ①SA<-R2 ②R1<-SA

MOV M,R2 ①SA<-R2 ②AR<-C ③M<-AR ④M<-SA

MOV R1,M ①AR<-C ②M<-AR ③R1<-M

ADD R1,R2和SUB R1,R2和AND R1,R2 ①SA<-R1 ②SB<-R2 ③R1<-SA+SB

NOT R1 ①SA<-R1 ②R1<-SA

SHR R1和SHL R1 ①SA<-R1 ②R1<-SH SA

JMP add ①AR<-PC ②M<-AR ③PC<-M

JZ add和JC add ①AR<-PC ②M<-AR ③PC<-M

IN R1 ①R1<-IN

OUT R1 ①SA<-R1

NOP ①PC<-PC+1

HALT ①HALT

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity yimaqi is
    port(
    contclk:in std_logic;
    yimaqi_in:in std_logic_vector(7 downto 0);
    address_i:in std_logic_vector(7 downto 0);
    Lod_IR,DL,XL,CS,M,Lod_MAR,Lod_SA,Lod_SB,Lod_xa,Lod_xb,LD_PC,Lod_PC,RE,WE:out std_logic;
    S:out std_logic_vector(3 downto 0);
    RA,WA:out std_logic_vector(1 downto 0);
    contR2:out std_logic_vector(1 downto 0);
    contlod_yw:out std_logic;
    contywen:out std_logic;
    address_o:out std_logic_vector(7 downto 0);
    NOP:out std_logic;
    reset:out std_logic;
    in_en:out std_logic;
    JMP:out std_logic;
    JZ:out std_logic;
    JC:out std_logic);
end yimaqi;

architecture yimaqi_ar of yimaqi is
signal num:std_logic_vector(4 downto 0);
signal order:std_logic_vector(3 downto 0); 
signal Rstart:std_logic_vector(1 downto 0);
signal Rend:std_logic_vector(1 downto 0);
begin
    order<=yimaqi_in(7 downto 4);
    Rstart<=yimaqi_in(3 downto 2);
    Rend<=yimaqi_in(1 downto 0);
    process(num,yimaqi_in,contclk)
    begin
    if(contclk'event and contclk='1') then 
        address_o<=address_i;
        contywen<='0';
        if (order="1000") then    --关机
                    reset<='1';
        else
            if num="00000" then        
                     Lod_PC<='1';
                     LD_PC<='0';
                     Lod_MAR<='1';
                     Lod_IR<='1';
                     Lod_xa<='1';
                     WE<='0';
                     RE<='0';
                     XL<='0';
                     DL<='1';
                     CS<='0';
                     JMP<='0';
                     JZ<='0';
                     JC<='0';                     
            else
                case num is
                    when "00110"=>    --first step                        
                        if(order="0011") then    --MOV第一步
                             if(Rstart="11" or Rend="11") then                     
 WE<='0';                                         RE<='1';                             
                         RA<=Rend;--寄存器和内存之间需要读出通用寄存器C的值
                             WA<=Rend;
                            Lod_xb<='0';                   --selects1
                            Lod_SB<='0';                   --zcqb                                             
                            Lod_SA<='0';                             --zcqa                                 M<='0';                                  --ALU
                              S<=order;                    
                            Lod_xa<='0';                              --selects2
                               Lod_MAR<='1';                            --MAR                              DL<='0';                                  --SRAM
                              xl<='0';
                            cs<='0';
                            contlod_yw<='0';
                            contR2<="00"; 
                            else                                                                             WE<='0';  --第一步读出Rend中数据
                            RE<='1';
                            RA<=Rend;
                            WA<=Rstart;
                            Lod_xb<='0';        --selects1                                                      Lod_SB<='0';           --zcqb
    Lod_SA<='1';        --zcqa从选择器A过
                            M<='0';             --ALU不计算
                            S<=order;                             
                            Lod_PC<='0';                                                                    Ld_PC<='1';                                                                    Lod_xa<='0';          --selects2
                              Lod_MAR<='0';       --MAR                                                   DL<='0';                                   --SRAM
                            XL<='0';
                            CS<='0';
                            contlod_yw<='0';
                            contR2<="00";
                            end if;     
                         elsif(order="0101") then    --NOT第一步把R1拿出来
                         Lod_PC<='0';        --PC
                         Ld_PC<='0';
                         DL<='0';        --RAM
                         XL<='0';
                         CS<='0';
                         M<='1';        --ALU进行计算
                         S<=order;
                         RA<=Rstart;        --tyjcqz
                         WA<="00";
                         RE<='1';
                         WE<='0';
                         
                         Lod_SA<='1';        --zcq从选择器A过
                         Lod_SB<='0';
                         Lod_IR<='0';        --IR
                         Lod_MAR<='0';        --MAR
                         Lod_SB<='0';        --selector
                         Lod_xa<='0';
                         contlod_yw<='0';
                         contR2<="00";                         
                         elsif(order="1001" or order="0110" or order="1110") then    
--AND SUB ADD 第一步取数
                         Lod_PC<='0';        --PC
                         Ld_PC<='0';
                         DL<='0';        --RAM
                         XL<='0';
                         CS<='0';                         
                         M<='0';        --ALU不计算
                         S<=order;                         
                         RA<=Rstart;        --tyjcqz 
                         WA<="00";
                         in_en<='0';                         
                         RE<='1';
                         WE<='0';                         
                         Lod_SA<='1';        --zcq                            
                         Lod_IR<='0';        --IR
                         Lod_MAR<='0';        --MAR
                         Lod_SB<='0';        --selector
                         Lod_xa<='0';
                         Lod_xb<='0';
                         contlod_yw<='0';
                         contR2<="00";  
                        elsif(order="1010") then    --SHL SHR
                         Lod_PC<='0';        --PC
                         Ld_PC<='0';    
                         DL<='0';        --RAM
                         XL<='0';
                         CS<='0';
                         M<='1';        --ALU
                         S<=order;
                         RA<=Rstart;        --tyjcqz
                         WA<="00";
                         RE<='1';
                         WE<='0';
                         Lod_SA<='1';        --zcq从选择器A过
                         Lod_SB<='0'; 
                         Lod_IR<='0';        --IR
                         Lod_MAR<='0';        --MAR
                         Lod_SB<='0';        --selector
                         Lod_xa<='0';
                         contlod_yw<='1';
                         contR2<=Rend;    --00右移 11左移
                         contywen<='1';
                         elsif(order="0111") then    --计数加一
                            NOP<='1';
                            Lod_PC<='0';
                            Ld_PC<='1';
                         elsif(order="0010") then    --输入R1
                            in_en<='1';
                            WE<='1';
                            RE<='0';
                            WA<=Rstart;
                            RE<='0';
                         elsif(order="0100") then --输出寄存器R1
                            RE<='1';
                            WE<='0';
                            RA<=Rstart;
                            Lod_SA<='1';
                            M<='1';                            
                        elsif(order="0001") then --跳转
                            Lod_MAR<='1';
                            if Rend="00" then
                                JMP<='1';
                            elsif Rend="01" then
                                JZ<='1';
                            elsif Rend="10" then
                                JC<='1';
                            end if;            
                            Lod_PC<='1';
                            Ld_PC<='0';                        
                        end if;
                    when "01000"=>    --second step
                         if(order="0011") then    --MOV第二步
                             if(Rstart="11" or Rend="11") then                 
--寄存器与内存之间 写回RAM
                             WE<='0';        --yujcqz                                
                             RE<='1';
                             RA<=Rend;    --后两位所表示的寄存器的值送到RAM里
                             WA<=Rend;    --tyjcq中的值,是后两位                                             Lod_xb<='0'; --selects1
Lod_SB<='0';          --zcqb
                            Lod_SA<='1';          --zcqa
M<='1';               --ALU
                            S<=order;                     
                            Lod_PC<='1';
                            Ld_PC<='0';
                            Lod_xa<='1';           --selects2
                              Lod_MAR<='1';        --MAR                         
                            DL<='1';              --SRAM
                              XL<='0';
                            CS<='0';
                            contlod_yw<='0';
                            contR2<="00";                     
                             else
                            WE<='1';              --yujcqz
                              RE<='0';
                            RA<=Rstart;
                            WA<=Rstart;
                            in_en<='0';
Lod_xb<='0';                 --selects1
                             Lod_SB<='0';                --zcqb
                            Lod_SA<='0';                --zcqa     
                            M<='1';                     --ALU
                             S<=order;
                            Lod_PC<='0';                                                                    Ld_PC<='0';                    
                            Lod_xa<='0';                 --selects2
                            Lod_MAR<='1';              --MAR
                            DL<='1';                    --SRAM
                            XL<='0';
                             CS<='0';
                             contlod_yw<='0';
                             contR2<="00";
                             end if;                         
                         elsif(order="0101") then    --NOT结果写入R1
                         Lod_PC<='0';        --PC
                         Ld_PC<='0';
                         DL<='0';        --RAM
                         XL<='0';
                         CS<='0';
                         M<='0';        --ALU进行计算
                         S<=order;
                         RA<="00";        --tyjcqz
                         WA<=Rstart;
                         RE<='0';
                         WE<='1'; 
                         in_en<='0'; 
                         Lod_SA<='0';        --zcq从选择器A过
                         Lod_SB<='0';
                         Lod_IR<='0';        --IR
                         Lod_MAR<='0';        --MAR
                         Lod_SB<='0';        --selector
                         Lod_xa<='0';
                         contlod_yw<='0';
                         contR2<="00";     
                         elsif(order="1010") then    --SHR SHL最后一步
                             DL<='0';        --RAM
                             XL<='0';
                             CS<='0'; 
                             M<='1';        --ALU
                             S<=order;
                             RA<="00";        --tyjcqz
                             WA<=Rstart;
                             RE<='0';
                             WE<='1';        
                             Lod_SA<='0';        --zcq
                             Lod_SB<='0';
                             Lod_IR<='0';        --IR
                             Lod_MAR<='0';        --MAR
                             Lod_xb<='0';        --selector
                             Lod_xa<='0';
                             contlod_yw<='1';
                             contR2<=Rend;
                        elsif(order="1001" or order="0110" or order="1110") then    
--AND SUB ADD 第二步取第二个数
                             DL<='0';        --RAM
                             XL<='0';
                             CS<='0'; 
                             M<='0';        --ALU
                             S<=order; 
                             RA<=Rend;        --tyjcqz
                             WA<="01";
                             RE<='1';
                             WE<='0';
                             Lod_SA<='0';        --zcq从SB过
                             Lod_SB<='1'; 
                             Lod_IR<='0';        --IR
                             Lod_MAR<='0';        --MAR 
                             Lod_xb<='1';        --selector
                             Lod_xa<='0';
                             contlod_yw<='0';
                             contR2<="00";
                             end if;                    
                        when "01100"=>    --third step
                            if(order="0011") then    --MOV第3步
                                 if(Rstart="11" or Rend="11") then                 
--寄存器与内存之间 写回RAM
                                WE<='1';       --yujcqz
RE<='0';
                                RA<=Rend;--后两位所表示的寄存器的值送到RAM                                 WA<=Rstart;    --tyjcq中的值,是后两位                                            Lod_xb<='0';                --selects1
                                Lod_SB<='0';             --zcqb
                                Lod_SA<='0';             --zcqa         
                                 Ld_PC<='0';
                                 Lod_PC<='1';
                                M<='0';                  --ALU
                                S<=order;                         
                                Lod_xa<='0';              --selects2
                                   Lod_MAR<='0';           --MAR         
                                DL<='0';                  --SRAM
                                   XL<='0';
                                 CS<='0';
                                 contlod_yw<='0';
                                 contR2<="00";
                                end if;
                             elsif(order="1001" or order="0110" or order="1110") then                                                    --AND SUB ADD 第三步计算写回
                                 DL<='0';        --RAM
                                 XL<='0';
                                 CS<='0';     
                                 M<='1';        --ALU
                                 S<=order;
                                 RA<="00";        --tyjcqz 
                                 WA<=Rstart;
                                 RE<='0';
                                 WE<='1'; 
                                 Lod_SA<='0';        --zcq
                                 Lod_SB<='0';
                                 Lod_IR<='0';        --IR
                                 Lod_MAR<='0';        --MAR
                                 Lod_xb<='0';        --selector
                                 Lod_xa<='0';
                                 contlod_yw<='0';
                                 contR2<="00";
                            else
                                 Lod_xa<='1';  
                                 DL<='1';
                             end if; 
                        when "01111"=>    --fourth step
                         Lod_MAR<='1'; 
                         Lod_xa<='1';                        --MAR
                         if(order="1010") then
                             contywen<='1';
                         end if;
                         when "10010"=>
                         if(order="1010") then
                             contywen<='0';
                         end if;
                         Lod_MAR<='1';
                         Ld_PC<='1';
                         Lod_PC<='0';
                         Lod_xa<='1';
                         DL<='1';
                         XL<='0';
                         CS<='0';
                         Lod_IR<='1';
                         num<="00000";
                    when others=> NOP<='0';reset<='0';
                end case;    
                    
            end if;
                num<=num+"00001";
        end if;
    end if;
    end process;
end yimaqi_ar;

4.1 测试环境

Quantus

4.2 测试结果

img RAM中输出00110001对应MOV指令,将暂存器A中10110100数据存入寄存器B中,之后PC加一RAM输出10010001对应ADD指令,将暂存器A、B中数据10110100 10110100通过ALU计算的出结果01101000

img RAM输出01100001,对应指令SUB,将暂存器A、B中的值00000011 10110100通过ALU计算并存入通用寄存器A中;之后PC加一,RAM输出11100010对应AND指令,将将暂存器A、B中的值01001111 00000111通过ALU进行and运算并存入通用寄存器A中。

img RAM输出01010001对应NOT指令,将通用寄存器A读入暂存器A中,再将暂存器中数据00000011通过ALU取反存进通用寄存器A中;之后PC加一RAM输出10100000对应指令SHR,将通用寄存器A读入暂存器A中,再将暂存器中数据11111100通过yiwei_ALU右移输出01111110,存入寄存器A中

img RAM输出10100011对应SHL指令,将通用寄存器A读入暂存器A中,再将暂存器中数据00000011通过yiwei_ALU左移存进通用寄存器A中;

img RAM输出10100011对应SHL指令,将通用寄存器A读入暂存器A中,再将暂存器中数据00000011通过yiwei_ALU左移存进通用寄存器A中;

RAM输出00010000对应JMP指令,将地址寄存器中的地址00001110取出作为跳转的目标地址,使PC跳转。同理00010001对应JZ指令,当ALU结果为0时PC跳转到address;00010010对应JC指令,当ALU运算结果有进位时PC跳转到address。

img RAM输出00100000对应IN指令,将拨码开关输入(cin=“00000000”)送入通用寄存器A中。

img RAM输出01000000对应OUT指令,通用寄存器A中数据00000011输出。

img RAM输出01110000对应NOP指令,PC+1进入下一条指令;之后RAM输出10000000进入关机状态,所有的器件输出都一直保持在初始状态不动。

  1. CPU的设计主要由控制器模块、选择器模块、存储器模块组成,其中控制器模块和数据通路模块是关键。在实现译码的过程时,要分清每一条指令的执行步骤,在不同的步骤里将相应的器件导通或者关闭。
  2. 想要实现条件跳转,必须得有信号量,只得再次改运算模块,使之有进位,并判断是否为0,最后连接到大模块中实现跳转。
  3. 当有多个期间的输出要连接到总线中时,需要将这些器件在控制信号无效时输出高阻,否则编译会报错。
  4. 由于每一个时序逻辑器件都需要一个时钟周期来执行,所以在每一个步骤之间要有分配有足够的时钟周期以便使数据能够正确的传输到相应的位置。
  5. 调试每一条指令时一定要有耐心,将中间控制信号输出可以有效的帮助我们进行调试。 同一个信号不能够在不同的进程中进行赋值。
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://wangjiawei.blog.csdn.net/article/details/118120551
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复