计算机CPU工作原理的实验

来源:互联网 发布:淘宝怎么延长付款时间 编辑:程序博客网 时间:2024/05/21 07:48

(一)实验类型:验证性+设计性

(二)实验类别:综合性专业基础实验

(三)实验学时数:8学时

(四)实验目的

理解和验证参考代码,并在其基础上,通过适当改造,尝试设计一个简单的CPU,并测试其结果。

(五)实验内容

设计一个能验证计算机CPU工作原理的实验系统,包括取指部分、指令译码部分、执行部分、通用寄存器组以及存储器,并测试其结果。

(六)实验要求

    根本目标:缩小到8位的数据通路,也即是4OP4位的地址码。(参考代码是16位数据通路,也即8位OP和8位的地址码)

(参见实践报告.doc中的9-11页的指令系统总体说明)

学生按照实验要求,在实验平台上实现具有存储与运算功能的计算机系统,并能通过测试,以验证其正确性。具体要求如下:

(1)取指及调试(组长兼任)

熟悉指令取指过程,并把16位的部分改为8位。使用DebugController和系统中的调试模块(reg_testa.vhd,reg_test.vhd)。

(2)熟悉电原理图的连接,以通用寄存器组部分为例。

实现上,用实验4所用的简单通用寄存器组(4个寄存器+1个2-4译码器+2个4选1多路开关)设计方法,替代参考代码中的通用寄存器组部分。

(3)学习和掌握控制逻辑。

设计一套指令集(可在原参考代码指令集的基础上做删减,从中选取16条基本的指令),并修改控制器中指令集的译码部分。

(4)执行部件,ALU的改造。

可在原参考代码的基础上,改变某些运算功能的实现方式,比如加、减、增1、减1等算术运算。

实现上,原参考代码采用了最少编码量的“+”、“-”号实现。可以改用通过port map语句调用系统自带的加法器,也可以进一步自己编写加法器,然后用port map语句调用。

(5)存储器部分的加入。

原参考代码采用的带外部存储器的模式。实现上,可以在实验3的基础上,设计一个适合加到本CPU系统的存储器部分,通过与原参考代码系统连接外带存储器的数据线、控制线和地址线相连接。

此部分设计中,存储器的指令置入是一个难点。可以考虑简单点的作为只读模式把指令写死在存储器中(可用于验证指令的执行);或者考虑在reset的那一拍里,实现存储器中待指令的置入。

存储器模块单独调试可行后再加到系统上。

(七)实验设备

TEC-CA组成原理实验箱。

(八)实验课承担单位:信息学院

(九)总结构图(组长负责组织填写)

 

 

(十)指令集(组长负责组织填写)

(参考实验大纲中的示例,结合各小组自己的设计),撰写内容可参照参考材料的 实践报告.doc中的指令系统总体说明 (p9-11页)

(1)  指令格式分类(按指令字长和操作数不同):

① 单字单操作数指令

 

7              4

3                2

1              0

        OPCODE           DEST_REG             00

        OPCODE                      OFFSET

   包括:DEC,INC, JR,JRC,JRNC,JRZ,JRNZ

 

② 单字双操作数指令

 

7              4

3               2

1              0

        OPCODE           DEST_REG           SOUR_REG

  包括:ADD,SUB,AND,CMP, OR, LDRR,STRR

③双字单操作数指令

 

7              4

3               2

1               0

        OPCODE              00               00

                           ADR

   包括:JMPA

④双字双操作数指令

 

7              4

3                2

1                0

        OPCODE           DEST_REG             00

                           DATA

   包括:MVRD

 

 

(2)  指令的分组及节拍:

 

读取指令:地址寄存器<-指令地址,修改PC内容使其指向下一条将要执行的指令;

          读内存,指令寄存器<-读出的内容。

 

执行指令:通用寄存器之间的运算或传送,可1步完成;

          读写内存,通常要两步完成。

根据指令的执行步骤不同,可以把全部指令分为A、B两组。其中A组指令完成的是通用寄存器之间的数据运算或传送,或其他一些特殊操作,在取指之后可一步完成,包括:ADD,SUB,AND,CMP,OR,DEC,INC ,JR,JRC,JRNC,JRZ,JRNZ;B组指令完成的是一次内存读写操作,在取指之后可两步完成,包括:JMPA,LDRR,STRR,MVRD。

在控制器方面我们选用了组合逻辑控制器方案。使用节拍来标记每条指令的执行步骤。由指令而定,在我们的系统中不同的执行步骤只有5个,故使用3位节拍就足够了。

 

 


000

 

 

 

 


001

读写内存

 

传送地址

AR<-地址

 

读内存,

IR<-读出内容

 

                  B组指令

 


                   101                      111

 


A组指令

011

 

 

 

 

 


(3)  指令汇总表:

指令格式

汇编语句

操作数个数

CZVS

指令类型 

功能说明

0000DRSR

ADD DR,SR

2

****

 

DR<-DR+SR

0001DRSR

SUB DR,SR

2

****

 

DR<-DR-SR

0010DRSR

AND DR,SR

2

****

A 

DR<-DR and SR

0011DRSR

CMP DR,SR

2

****

 

DR-SR

0100DRSR

OR DR,SR

2

****

组 

DR<-DR or SR

0101DR0000

DEC DR

1

****

 

DR<-DR-1

0110DR0000

INC DR

1

****

指 

DR<-DR+1

0111OFFSET

JR ADR

1

….

 

无条件跳转 

1000OFFSET

JRC ADR

1

….

令 

C=1时跳转

1001OFFSET

JRNC ADR

1

….

 

C=0时跳转

1010OFFSET

JRZ ADR

1

….

 

Z=1时跳转

1011OFFSET

JRNZ ADR

1

….

 

Z=0时跳转

1100ADR

JMPA ADR

1

….

B

无条件跳转到ADR

1101DRSR

LDRR DR,[SR]

2

….

DR<-[SR]

1110DRSR

STRR [DR],SR

2

….

[DR]<-SR

1111DR0000

MVRD DR,DATA

2

….

DR<-DATA

 

 

 

(十一)各部分设计(组内同学各写各自部分)

注意把所有能体现修改的都做注释,记住一开始我和大家说的,修改越多在某种程度上代表着对该模块更深刻的理解,因此得分也会越高。

0.整体描述(组长填写)

(8-10句话描述你们小组的工作,包括5个部分的改动,在最后的系统中,多少个整合后能通过编译,多少个整合后可以运行)。

各组员先是一起讨论商量好实验的分工。选定了以分工分配的任务修改各自的十六位的VHD代码,并在参考代码中编译,修改,最后改成八位并全部合成为一个完整系统。

小组的工作中,各个组员的修改部分:

通用寄存器主要是修改十六位的通用寄存器为八位,将原来的十六个改为四个,并加上一个四选一数据选择器。并改动bdf图;

ALU利用port map语句修改“+”和“—”等来实现数据的运算;

存储器通过存取指令,写死程序来表示程序的运行顺序;

控制逻辑通过定义所选指令的OP码,来识别存储器中的汇编指令。

通过几周的共同努力,最终都通过了编译,并都可以运行。

1. 取指及调试

(0)是否加到最后整组的系统中

     是 

 

(1)修改后是否编译通过(指加到整个小组的系统里)

 

 

(2)修改后是否可运行(指加到整个小组的系统里)

       是

 

(3)概要描述

与组员一起讨论,选定十六条指令。对于编译成功的代码写进机箱中,进行调试验证代码是否正确。

 

 

2. 控制逻辑

(0)是否加到最后整组的系统中

    如果回答为否,可跳过第(1)和(2)问。

 

(1)修改后是否编译通过(指加到整个小组的系统里)

 

 

 

(2)修改后是否可运行(指加到整个小组的系统里)

 

 

(3)概要描述

(2-3句话描述你的工作)

 

 

(4)相关的源代码、电原理图和其它说明表格。

 

有改动过的或者新增的.bsf图、vhd文件内容,以及相关电原理图截图、用于说明的表格、用于说明的示意图等。(加注释,特别是在参考材料的源代码基础上改动之处,用蓝色标出)。可以部分参照参考材料的文档写法。特别注意:如果没被抽中去演示,则主要根据分工所对应的这部分设计的撰写的内容评分,因此要尽量详细地介绍你的工作。

 

3. 执行(ALU相关)

(0)是否加到最后整组的系统中

    是

 

(1)修改后是否编译通过(指加到整个小组的系统里)

       是

 

 

(2)修改后是否可运行(指加到整个小组的系统里)

       是

 

(3)概要描述

我的工作是负责修改ALU模块的代码,修改原代码中有关加减的语句。首先根据实验一,编写8位加法器adder8bit代码,然后使用port map语句调用adder8bit,实现原代码中“+”、“-”的功能。

 

(4)相关的源代码、电原理图和其它说明表格。

1、.bsf图:

   

    (此为8位加法器的.bsf图)

  

(此为alu的.bsf图)

 

 

2、vhd文件内容(自己的内容用蓝色字体):

------------此为自己编写的fa代码,用于被adder8bit调用-------------------------------

library ieee;

use ieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entity fa is

port(a,b,ci : instd_logic;

       s,co : out std_logic);

end fa;

 

architecture b_faof fa is

begin

  s<=a xor b xor ci;

  co<=((a xor b) and ci) or (a and b);

end b_fa;

 

 

 

----------------此为8adder代码,用于alu利用portmap语句调用------------------

 

library ieee;

useieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

entity adder8bitis

       port( a,b : in std_logic_vector(7 downto 0);

            s : out std_logic_vector(7 downto 0);

               ci : in std_logic;

               c1 : out std_logic;    --最高位进位c1   

               z1 : out std_logic;    --结果为零z1 

            v1 : out std_logic;    --结果溢出v1  

            n1 : out std_logic);   --结果为负数n1

end adder8bit;

 

architecturestructure of adder8bit is

 

component fa

       port(a,b,ci : in std_logic;

                s,co : out std_logic);

end component;

 

signals_temp,c_temp : std_logic_vector(7 downto 0); --结果F  进位C 过程变量 

signaloverflow_temp : std_logic;              --溢出V  过程变量 

 

begin

 

       f0:  fa port map( a(0),b(0),ci,s_temp(0),c_temp(0) );    --最低位位相加  

      

       f1_7: for i in 1 to 7 generate                     --其他7位用循环体相加         

                 fm: fa port map( a(i),b(i),c_temp(i-1),s_temp(i),c_temp(i) );

       end generate f1_7;

        s <=s_temp;

 

----------------------------------------PSW判断--------------------------------------

       c1<=c_temp(7);                                        --进位c1

                                               

       z1 <= '1' WHENs_temp="0000000000000000" ELSE     --零z1

              '0';

                    

       overflow_temp <= c_temp(7) xorc_temp(6);

       v1 <= '1' WHEN overflow_temp = '1'ELSE   --溢出v1

                   '0';

      

       n1 <= '1' WHEN s_temp(7) = '1'ELSE        --负数n1

                   '0';  

end structure;

 

 

------------此为经过修改的alu代码--------------

library ieee;

use ieee.std_logic_1164.all;

useieee.std_logic_arith.all;

useieee.std_logic_unsigned.all;

 

entityalu is

port(cin:instd_logic;

     alu_a,alu_b:in std_logic_vector(7 downto0);------将原代码改为8--------

     alu_func:in std_logic_vector(2 downto 0);

     alu_out:out std_logic_vector(7 downto 0);

     c,z,v,s:out std_logic);

endalu;

 

----------alu调用adder8bit------------------------

 

architecturebehave of alu is

 

signaltemp1,alu_a_temp,alu_b_temp,temp1_temp,zero_0,max : std_logic_vector(7 downto0) ;

signalresult,result1,result2,result3,result4,result5:std_logic_vector(7 downto 0);

signalc2,z2,v2,s2,c3,z3,v3,s3,c4,z4,v4,s4,c5,z5,v5,s5,c6,z6,v6,s6:std_logic;

signalc_in_0,c_in_1 : std_logic;

 

componentadder8bit is

       port( a,b : in std_logic_vector(7 downto 0);

                s : out std_logic_vector(7 downto 0);

                 ci : in std_logic;

                 c1 : out std_logic;   

                 z1 : out std_logic;   

                   v1 : out std_logic;   

                    n1 : out std_logic); 

endcomponent;

 

 

begin

       c_in_0<='0';

       c_in_1<='1';

       zero_0<="00000000";

       max<="11111111";

       alu_a_temp <=not alu_a;----------将操作数alu_a取反

       alu_b_temp <=not alu_b;----------将操作数alu_b取反

    temp1 <="0000000"&cin;--------cin扩展为8

    temp1_temp <=not temp1;---------将扩展后的cin取反

   --------以下是计算结果,用于下面process语句赋值。我的做法是将process语句需要用                                   

   --------到的每一个数都直接计算,然后process语句需要用到哪一个就将那个算好的值

   --------赋值过去。

f_add1:adder8bit portmap(alu_b,alu_a,result,cin,c2,z2,v2,s2);

-----原语句为

-----temp2 :=alu_b+alu_a+temp1;

 

       f_sub1:adder8bit port map(alu_b,alu_a_temp,result2,c_in_1,c3,z3,v3,s3);

f_sub2:adder8bit portmap(result2,temp1_temp,result3,c_in_1,c4,z4,v4,s4);

-----原语句为

-----temp2 :=alu_b-alu_a-temp1;

 

f_sub3:adder8bit portmap(max,alu_b_temp,result4,c_in_1,c5,z5,v5,s5);

f_sub4:adder8bit portmap(result4,temp1_temp,result5,c_in_1,c6,z6,v6,s6);

-----原语句为

-----temp3 :="1111111111111111"-alu_b-temp1;

 

      

       process(alu_a,alu_b,cin,alu_func)

       variable temp2,temp3 : std_logic_vector(7downto 0) ;

       begin

              case alu_func is

                     when "000"=>

                     temp2:= result;----(原语句为temp2 := alu_b+alu_a+temp1;

 

                    

                    

                     when "001"=>

                     temp2:= result3;----(原语句为temp2 := alu_b-alu_a-temp1;

            when "010"=>

                     temp2 := alu_a and alu_b;

                     when "011"=>

                     temp2 := alu_a or alu_b;

                     when "100"=>

                     temp2 := alu_a xor alu_b;

                     when "101"=>

                     temp2(0) := '0';

                     for I in 7 downto 1 loop

                     temp2(I) := alu_b(I-1);

                     end loop;

                     when "110"=>

                     temp2(7) := '0';

                     for I in 6 downto 0 loop

                     temp2(I) := alu_b(I+1);

                     end loop;

                     when others=>

                     temp2 :="00000000";

              end case;

              alu_out <= temp2;

              if temp2 = "00000000"then z<='1';

              else z<='0';

              end if;

              if temp2(7) = '1' then s<='1';

              else s<='0';

              end if;

              case alu_func is

                     when "000" |"001"=>

                     if (alu_a(7)= '1' andalu_b(7)= '1' and temp2(7) = '0') or

                        (alu_a(7)= '0' and alu_b(7)= '0' andtemp2(7) = '1') then

                     v<='1';

                     else v<='0';

                     end if;

                     when others=>

                     v<='0';

              end case;

              case alu_func is

                     when "000"=>

                     temp3:= result5;------temp3 := 原语句为("1111111111111111"-alu_b-temp1;

                     if temp3<alu_a then

                     c<='1';

                     else c<='0';

                     end if;

                     when "001"=>

                     if alu_b<alu_a then

                     c<='1';

                     else c<='0';

                     end if;

                     when "101"=>

                     c <= alu_b(7);

                     when "110"=>

                     c <= alu_b(0);

                     when others=>

                     c<='0';

              end case;

       end process;

end behave;

4. 通用寄存器组

(0)是否加到最后整组的系统中

    是

 

(1)修改后是否编译通过(指加到整个小组的系统里)

       是

 

 

(2)修改后是否可运行(指加到整个小组的系统里)

       是

 

(3)概要描述

(2-3句话描述你的工作)

修改部分:通用寄存器十六位改八位,原来的十六个寄存器改用四个,多用一个四选一数据选择器来选择寄存器数据的读出

 

 

(4)   相关的源代码、电原理图和其它说明表格。

bsf图:

VHD码:

library ieee;

use ieee.std_logic_1164.all;

 

entity regfile is

port( DR        : in std_logic_vector(1downto 0);

      SR        : in std_logic_vector(1downto 0);

      reset     : in std_logic;

      write     : in std_logic;

      clk       : in std_logic;

      d_input   : in std_logic_vector(7downto 0);

      reg_sel: in std_logic_vector(1 downto 0); 

      output_DR : out std_logic_vector(7 downto 0);

      output_SR : out std_logic_vector(7 downto 0);

      reg_out   : out std_logic_vector(7downto 0)

);

end regfile;

 

architecture struct of regfile is

 

component reg is port

         (reset    : in std_logic;

          d_input  : in std_logic_vector(7downto 0);

          clk      : in std_logic;

          write    : in std_logic;

          sel      : in std_logic;

          q_output : out std_logic_vector(7 downto 0)

          );

 endcomponent;

 

 component mux_4_to_1 is port

        (input0,

         input1,

         input2,

         input3 : in std_logic_vector(7 downto 0);

         sel    : in std_logic_vector(1 downto 0);

         out_put : out std_logic_vector(7 downto 0));

 endcomponent;

 

 component decoder_2_to_4 is port

       (sel     : in std_logic_vector(1downto 0);

        sel00  : out std_logic;

        sel01  : out std_logic;

        sel02  : out std_logic;

        sel03  : out std_logic

       );

 endcomponent;

 

 

signalreg00,reg01,reg02,reg03:std_logic_vector(7 downto 0);

signal sel00,sel01,sel02,sel03:std_logic;

 

begin

 Areg00: reg port map(             --寄存器R0

         reset    =>reset,

         d_input  =>d_input,

         clk      =>clk,

         write    =>write,

         sel      =>sel00,

         q_output =>reg00

         );

 

 Areg01: reg port map(             --寄存器R1

         reset    =>reset,

         d_input  =>d_input,

         clk      =>clk,

         write    =>write,

         sel      =>sel01,

         q_output =>reg01

         );

 

 Areg02: reg port map(             --寄存器R2

         reset    =>reset,

         d_input  =>d_input,

         clk      =>clk,

         write    =>write,

         sel      =>sel02,

         q_output =>reg02

         );

 

 Areg03: reg port map(             --寄存器R3

         reset    =>reset,

         d_input  =>d_input,

         clk      =>clk,

         write    =>write,

         sel      =>sel03,

         q_output =>reg03

          );

 

 des_decoder: decoder_2_to_4 port map(             --2-4译码器

         sel      =>DR,

         

         sel00    =>sel00,

         sel01    =>sel01,

         sel02    =>sel02,

         sel03    =>sel03

         );

 

 muxA: mux_4_to_1 port map(      -- 41选择器,用于选择目的寄存器读出

         input0    =>reg00,

         input1    =>reg01,

         input2    =>reg02,

         input3    =>reg03,

         sel       =>DR,

       

         out_put   =>output_DR

  

         );

 

 muxB: mux_4_to_1 port map(       -- 41选择器,用于选择目的寄存器读出

         input0    =>reg00,

         input1    =>reg01,

         input2    =>reg02,

         input3    =>reg03,

         sel       =>SR,

     

         out_put   =>output_SR

      

         );

 muxC:

      mux_4_to_1 port map(        -- 41选择器,用于选择目的寄存器读出

         input0    =>reg00,

         input1    =>reg01,

         input2    =>reg02,

         input3    =>reg03,

         sel       =>reg_sel,

     

         out_put   =>reg_out

      

         );

     

end struct;

 

5. 存储器

(0)是否加到最后整组的系统中

      是

 

(1)修改后是否编译通过(指加到整个小组的系统里)

 

 

(2)修改后是否可运行(指加到整个小组的系统里)

 

(3)概要描述

我的工作是设计一个外部存储器,编写一个汇编小程序,然后将指令置入存储器后加入到整个系统中。

(4)相关的源代码、电原理图和其它说明表格。

 

 

 

 

 

--实验 men存储器

 

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

 

ENTITY MEM IS

GENERIC(men_width: POSITIVE :=8;

       adr_width : POSITIVE :=8); --2**4 ×6位的men

--GENERIC(men_width: POSITIVE :=16;

--       adr_width : POSITIVE :=16); --2**4 ×6位的men

PORT (  din  : IN STD_LOGIC_VECTOR((men_width-1) DOWNTO 0);

       dout : OUTSTD_LOGIC_VECTOR((men_width-1) DOWNTO 0);

       adr  : IN STD_LOGIC_VECTOR((adr_width -1) DOWNTO 0);

       wr   : IN STD_LOGIC

);

END MEM;

 

ARCHITECTURE MEM_architecture OF MEM IS

SUBTYPE men_word IS STD_LOGIC_VECTOR(0 TO (men_width-1) );

TYPE men_type IS ARRAY (0 TO (2**3 -1)) OF men_word;

SIGNAL men:men_type;

BEGIN

  

   PROCESS(adr,wr,men)

   BEGIN

   men(0) <="11110000";                     --MVRD  DR,SR

   men(1) <="00000001";                     --ADD    DR,SR

   men(2) <="11110100";                     --MVRD  DR,SR

   men(3) <="00000001";                     --ADD    DR,SR

   men(4) <="00010001";                     --SUB    DR,SR

   men(5) <="11000000";                     --JMPA   ADDR

       IF wr='0' THEN

              men(conv_integer(adr))<= din;

       ELSIFwr='1' THEN

          dout<= men(conv_integer(adr));

       END IF;

   END PROCESS;

END MEM_architecture;

 

有改动过的或者新增的.bsf图、vhd文件内容,以及相关电原理图截图、用于说明的表格、用于说明的示意图等。(加注释,特别是在参考材料的源代码基础上改动之处,用蓝色标出)。可以部分参照参考材料的文档写法。特别注意:如果没被抽中去演示,则主要根据分工所对应的这部分设计的撰写的内容评分,因此要尽量详细地介绍你的工作。

 

 

 

(十二)实验小结(所有组员都要写)

通用寄存器的设计比较简单,与原来的实验资料相比,只是在使用八个还是四个寄存器时有过争议,经过与其他同学的讨论和向老师询问后,选择使用四个寄存器和再加一个四选一数据选择器以用于寄存器的数据读取,并最终完成了通用寄存器的vhd码,和bdf图。在取指和调试方面,我们是取了12条A指令,和4条B指令。在实验过程中也是遇到了许多困惑,比如一开始选定指令后,没有约定好op码,结果在调试时候出现了很多问题。最后通过大家的共同努力,完整的实现了16位改八位的目的。整个过程中,更深刻了了解了CPU的工作原理,对组成原理的知识也有了进一步的认识。同时也认识到了团队合作中分工合理及相互督促等的重要性。

 

在一开始设计存储器的时候无从下手,后来经过了解,讨论,询问。逐步了解到存储器所起到的作用和所需实现的功能。一开始要从指令中挑选出合适的16条指令然后进行选择,规划。调试阶段先随便用指令先行写入,然后进行调试。整合阶段则将指令编为8位2进制码,然后编写一个汇编小程序,将其指令写入存储器中。在做实验的过程中,一开始不知道代码的规划和如何写,经过报告的参考和了解后,才懂得如何将指令置入内存。

 

后来我重新去看了实验一和实验二的内容,发现实验二的ALU是利用port map语句来调用实验一的加法器adder以实现功能的。这与老师给的原代码是不一样的,原代码在做加减时是直接利用“+”、“-”来计算的。因此,ALU部分的修改是要利用port map语句来实现加减功能。总的来说还是比较简单的,只要了解了port map语句,对代码的修改就十分轻松了。但是我的代码有一个很大的缺点,那就是过于冗杂。像在计算那里,我是直接将alu所有有可能计算的地方全部计算了(3处),然后赋值给process语句中相应的地方。还有就是我的加法器是参考实验一的,因此我的代码有一些标志位,而那些标志位在process语句中是重新计算的。也就是说我代码中的标志位是多余的,我有尝试删除,但是编译错误,考虑到并不影响结果,我就将它们保留了。总的来说经过这次综合性实验,我学会的东西是是能够较为熟练地利用port map语句调用组件。

0 0
原创粉丝点击