华北电力大学计算机组成原理实验报告

实验一 运算器设计实验

  • 目的与要求

1.目的

        (1)熟悉硬件描述语言及开发环境,了解硬件系统开发的基本过程

        (2)掌握ALU基本设计方法和简单运算器的数据传输通路

        (3)验证ALU的功能

        2.要求

(1)运用所学的知识和方法采用最佳方案完成实验设计。

(2)编写简洁代码完成实验要求内容。

(3)认真书写实验报告,包括实验目的、实验内容、实验设计方案、实验仿真结果等。

二、实验正文

1.实验内容

(1)用VHDL语言实现一个简易的16位ALU。

(2)通过设计一个状态机,根据状态机状态的变化输入操作数和操作码,来实现不同运算。

(3)实验中ALU要求实现基本的算术运算、逻辑运算、移位运算等,具体功能如下表所示。合理设置每条指令的标志位,包括进位标志、溢出标志、最高位和全零标志。

ALU功能表:

操作码

功能

描述

ADD

A + B

加法

SUB

A – B

减法

AND

A and B

OR

A or B

XOR

A xor B

异或

NOT

not A

取非

SLL

A sll B

逻辑左移B位

SLR

A srl B

逻辑右移B位

SAL

A sal B

算数左移B位

SAR

A sar B

算数右移B位

ROL

A rol B

循环左移B位

ROR

A ror B

循环右移B位

要求:ALU 的数据输入 A、B 的长度为 16 位,操作码 op 为 4 位,算术运算时数据用补码表示。

(4)将实验过程中进行的操作与结果数据记录在下表中。

输入数据

实际输出

与预期一致性

操作码

操作数A

操作数B

运算结果

标志位

0000

00000001

00000010

00000011

0000

一致

(5)在教学计算机上验证实现的ALU功能。

2.实验步骤

(1)先设置输入输出,设置clk和rst信号,设置In_temp为16位拨码输入,Out_Y为16位LED输出,Flags为标志位,stateCnt为7段数目管显示当前状态。

(2)定义signal,其中3位信号State记录当前状态。

(3)在程序主体设置状态转换,State为000时读取拨码输入的A操作数,为001时读取拨码输入的B操作数,为010时读取拨码输入的低4位操作数,为011时进行运算。在011状态下用when选择4位操作码定义的操作,并分别用读取的操作数进行运算。

(4)添加管脚约束。

(5)运行代码无误后烧录进板子进行验证。

3.代码部分

entity alu is

    Port ( clk : in STD_LOGIC;--时钟

           rst : in STD_LOGIC;--复位

           In_temp : in STD_LOGIC_VECTOR (15 downto 0); --操作数

           Out_Y : out STD_LOGIC_VECTOR (15 downto 0);--输出

           Flags :out STD_LOGIC_VECTOR(3 DOWNTO 0);--标志位为 OF 溢出标志位/CF carry flag/ZF 零标志位/SF 正负标志位 0 正 1 负

           stateCnt :out STD_LOGIC_VECTOR(6 DOWNTO 0));

end alu;

architecture Behavioral of alu is

    signal State : STD_LOGIC_VECTOR (2 downto 0):= "000";--记录当前的状态,来判断该进行什么操作

    signal int_A, int_B,int_Y : INTEGER RANGE -32768 TO 32767:=0;

    signal temp_A, temp_B, temp_y: STD_LOGIC_VECTOR (15 downto 0);--定义临时操作数

    signal OP : STD_LOGIC_VECTOR(3 downto 0);--操作码

    signal Flag_OF : STD_LOGIC:= '0';--溢出标志

    signal Flag_CF : STD_LOGIC:= '0';--进位标志

    signal Flag_ZF : STD_LOGIC:= '0';--0 标志位

    signal Flag_SF : STD_LOGIC:= '0';--正负标志

    signal M: STD_LOGIC:='0';--扩展:对于带符号运算 ADC/SBB

begin

    process(rst,clk)

    VARIABLE int_T: INTEGER RANGE -32768 TO 32767:=0;

   VARIABLE TEMP_Y : STD_LOGIC_VECTOR(15 DOWNTO 0);

    begin

        IF (rising_edge(clk)) then

           if (State = "000") then --状态 1,读取 A 数字转换;

               temp_A <= In_temp;

               stateCnt <= not "1000000"   ;

               Flag_OF <='0';

               Flag_CF <='0';

               Flag_ZF <='0';

               Flag_SF <='0';

               int_A <= CONV_INTEGER(In_temp); --将 A 输入转化为整形

               State <= "001";

           elsif (State = "001") then --状态 2,读取 B 数字转换;

               temp_B <= In_temp;

               stateCnt <= not "1111001"   ;      

               int_B <= CONV_INTEGER(In_temp); --将 B 输入转化为整形

               State <= "010";

           elsif (State = "010") then --状态 3,读 OP

               OP <= In_temp(3 downto 0);

               stateCnt <= not "0100100"   ;      

               State <= "011";

           elsif (State = "011") then--状态 4,进行运算;

               stateCnt <= not "0110000"   ;      

               CASE OP IS

                   WHEN "0000" => --ADD 加

                       M <= '1';

                       int_T := int_A + int_B;

                       int_Y <= int_T;

                       TEMP_Y := TEMP_A + TEMP_B;

                       Out_Y <= CONV_STD_LOGIC_VECTOR(int_T,16);

                       if(temp_A(15) = '0' and temp_B(15) = '0' and temp_Y(15) = '1') then--进行溢出和是否进位判断

                           Flag_OF <= '1';

                       end if;

                       if(temp_A(15)='1' and temp_B(15)='1' and temp_Y(15)='0') then --进行溢出和是否进位判断

                           Flag_OF <= '1';

                           Flag_CF <='1';

                       end if;

                       if(CONV_STD_LOGIC_VECTOR(int_T,16) = "0000000000000000") then --0 标志位与 0 进行比较

                           Flag_ZF <= '1';

                       end if;

                       if(INT_T < 0) then --通过符号位来判断正负标志位

                           Flag_SF <= '1';

                       end if;

                       State <= "100";

                   WHEN "0001" => --SUB 减

                       int_T := int_A - int_B;

                       if(int_T = 0) then

                           Flag_ZF <= '1';

                       end if;

                       if(int_T < 0) then

                           Flag_SF <= '1';

                       end if;

                       Out_Y <= CONV_STD_LOGIC_VECTOR(int_T,16);

                       State <= "100";

                   WHEN "0010" => --AND 逻辑与

                       Out_Y <= (temp_A AND temp_B);

                       temp_Y := (temp_A AND temp_B);

                       if(CONV_INTEGER(temp_Y) = 0) then

                           Flag_ZF <= '1';

                       end if;

                       if(CONV_INTEGER(temp_Y) < 0) then

                           Flag_SF <= '1';

                       end if;

                       State <= "100";

                   WHEN "0011" => --OR 逻辑或

                       Out_Y <= temp_A OR temp_B;

                       State <= "100";

                   WHEN "0100" => --XOR 逻辑异或

                       Out_Y <= temp_A XOR temp_B;

                       State <= "100";

                   WHEN "0101" => --NOT 逻辑非

                       Out_Y <= NOT temp_A;

                       State <= "100";

                   WHEN "0110" => --SLL 逻辑左移

                       if(temp_B(3 downto 0) /= "0000") then

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SLL CONV_INTEGER(temp_B(3 downto 0)));

                       else

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SLL 1);

                       end if;

                       State <= "100";

                   WHEN "0111" => --SLA 算术左移

                       if(temp_B(3 downto 0) /= "0000") then

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SLA CONV_INTEGER(temp_B(3 downto 0)));

                       else

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SLA 1);

                       end if;

                       State <= "100";

                   WHEN "1000" => --SRL 逻辑右移

                       if(temp_B(3 downto 0) /= "0000") then

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SRL CONV_INTEGER(temp_B));

                       else

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SRL 1);

                       end if;

                       State <= "100";

                   WHEN "1001" => --SRA 算术右移

                       if(temp_B(3 downto 0) /= "0000") then

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SRA CONV_INTEGER(temp_B(3 downto 0)));

                       else

                       Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) SRA 1);

                       end if;

                       State <= "100";

                   WHEN "1010" => --ROL 循环逻辑左移

                       if(temp_B(3 downto 0) = "0000") then

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) ROL CONV_INTEGER(temp_B(3 downto 0)));

                       else

                           Out_Y <= TO_STDLOGICVECTOR(To_bitvector(temp_A) ROL 1);

                       end if;

                       State <= "100";

                   WHEN OTHERS =>

                       Out_Y <= "1111111111111111"; --默认报错用-1

                       State <= "100";

               end case;

           elsif (State = "100") then--状态 5,输出 FLAGS;

              stateCnt <=  not "0011001"   ;      

               Flags(3) <= Flag_OF;

               Flags(2) <= Flag_CF;

               Flags(1) <= Flag_ZF;

               Flags(0) <= Flag_SF;

               State <= "000";

           end if;

        end if;

        if (rst='0') then

           State <= "000";

           Flags(3) <= '0';

           Flags(2) <= '0';

           Flags(1) <= '0';

           Flags(0) <= '0';

           Out_Y <= "0000000000000000";

        END if;

    end process;

end Behavioral;

4.思考题

(1)ALU 进行算术逻辑运算所使用的电路是组合逻辑电路还是时序逻辑电路?

解:组合逻辑电路。

(2)如果给定了 A 和 B 的初值,且每次运算完后结果都写入到 B 中,再进行下次运算。这样一个带暂存功能的 ALU 要增加一些什么电路来实现?

解:增加暂存器 TMP 和累加器 AC。

三、综合实验总结

  1. 实验难点
  1. 第一次实验时对硬件操作不熟练,不知道如何定义管脚,经学长演示后明白了管脚操作。
  2. 程序烧进板子后,数据输入总是出问题,经排查后发现数据输入比状态转换慢了一个节拍,改变输入时间后可以正常操作。
  1. 心得体会

在本次实验中,我学到了很多知识,通过程序的编写,对计算机组成也有了更深刻的认识。实验小组内合作完成,讨论中交流了自己的想法,并把程序不断改进。

实验二 存储器实验

  • 目的与要求

1.完成 SRAM 写,给定地址,写入相应数据。

2.完成 SRAM 读,给定地址,读出对应数据。

3.LED 和数码管正确显示数据及状态的变化。

4.掌握内存(RAM)的访问时序和方法。

5.理解总线数据传输的基本原理。

二、实验正文

1.实验内容

使用教学计算机上的FPGA芯片,设计一个状态机和内存读写逻辑,完成对存储器RAM的访问。

2.实验步骤

(1)先定义输入输出,定义时钟,置0和状态控制信号ctrl_r,定义16位拨码输入,16位地址输出和16位数据输出,绑定地址线和数据线。定义左右两个数码管显示状态变化。16位led灯输出地址低8位和数据低8位。

(2)定义signal,定义状态机,控制运行状态,地址输入状态,写入状态和读取状态。

(3)3个运行状态分别进行写地址,写数据,读地址和数据的操作,每个操作中又分为小状态。

(4)添加管脚约束。

(5)运行代码无误后烧录进板子进行验证。

3.代码部分

    entity SRAM is

    Port ( CLK : in STD_LOGIC;  --时钟

            RST : in STD_LOGIC;  --置0

            ctrl_r : in STD_LOGIC; 

            input : in STD_LOGIC_VECTOR (15 downto 0);  --输入

            --light

            LIGHT: out STD_LOGIC_VECTOR (15 downto 0);  --LED灯

            SEG:out std_logic_vector(6 DOWNTO 0):=not "1111001";  --数码管

            SEG_LGHET:out std_logic_vector(6 DOWNTO 0):=not "1111001";  --数码管

            DBC : inout STD_LOGIC; --interconn3

            --RAM

            ADDR : out STD_LOGIC_VECTOR (15 downto 0);  --地址线

            DATA : inout STD_LOGIC_VECTOR (15 downto 0);  --数据线

            OE : out STD_LOGIC;  --输出使能端

            WE : out STD_LOGIC;  --允许写入

            EN : out STD_LOGIC);  --片选信号

            

end SRAM;

architecture Behavioral of SRAM is

    --signal State : STD_LOGIC_VECTOR(1 downto 0);

    signal tmp_write_addr:std_logic_vector(15 downto 0);  --写入地址

    signal tmp_write_data:std_logic_vector(15 downto 0):=x"0000";  --写入数据

    signal tmp_read_addr:std_logic_vector(15 downto 0);  --读地址

    signal tmp_read_data:std_logic_vector(15 downto 0):=x"0000";  --读数据

    signal tmp_light:std_logic_vector(15 downto 0):=x"0000";  --LED灯

    type prj_state is (N,W,R); --运行状态

    signal ctrl_state:prj_state;

    type adram_state is (waiting); --地址输入状态

    signal address_state:adram_state; 

    type sram_state is (waiting,start,over); --写入状态

    signal write_state:sram_state; 

    type rram_state is (waiting,start,read,over);--读取状态

    signal read_state:rram_state;

begin

    process(tmp_light,tmp_read_addr)

    begin

        light(7 downto 0) <= tmp_light(7 DOWNTO 0); 

        light(15 downto 8) <= tmp_read_addr(7 DOWNTO 0);  --地址低8位和数据低8位

    end process;

    process(RST,ctrl_r)

    begin

        if RST='0' then

           ctrl_state<=N;

           SEG_LGHET <= not"1000000";

        elsif rising_edge(ctrl_r) then

           case ctrl_state is

               when N=>

                   SEG_LGHET <= "0000110"; --1,数码管显示数字

                   ctrl_state<=W;

               when W=>

                   SEG_LGHET <= "1011011";--2

                   ctrl_state<=R;

               when R=>

                   SEG_LGHET <= not"1000000";

                   ctrl_state<=N;

           end case;

        end if;

    end process;

    process(RST,CLK,ctrl_state)

    begin

        if RST='0' then  --置0

           SEG <= "1000000";

           tmp_write_data<=x"0000";

           tmp_read_addr<=x"0000";

           tmp_write_addr<=x"0000";

           tmp_light<=x"0000";

           OE<='0';

           WE<='0';

           address_state<=waiting;

           write_state<=waiting;

           read_state<=waiting;

        elsif rising_edge(CLK) then

           case ctrl_state is    --运行状态

               when N=>

                   ADDR <= input;  --写入地址单元的地址

                   SEG <= not"1000000"; --0

                   tmp_write_addr <= input;

                   tmp_read_addr <= input;

               when W=>

                   case write_state is

                       when waiting =>

                           address_state <= waiting;

                           write_state <= start;

                           read_state <= waiting;

                           SEG <= "0000110"; --1

                       when start =>

                           tmp_write_data<=input;

                           ADDR <= tmp_write_addr;

                           DATA <= input;

                           EN <= '0';

                           OE <= '1';

                           WE <= '0';

                           SEG <= "1011011"; --2

                           write_state <= over;

                       when over =>

                           write_state <= waiting;

                           tmp_write_addr <= tmp_write_addr + 1;

                           SEG <= "1001111"; --3

                   end case;

               when R=>

                   case read_state is

                       when waiting =>

                           address_state <= waiting;

                           read_state <= start;

                           write_state <= waiting;

                           SEG <= "1100110"; --4

                       when start=>

                           ADDR <= tmp_read_addr;

                           DATA<=(others=>'Z');

                           read_state<=read;

                           SEG <= "1101101"; --5

                           EN <= '0';

                           OE <= '1';

                           WE <= '1';

                       when read =>

                           EN <= '0';

                           OE<='0';

                           We<='1';

                           tmp_light <= DATA;

                           SEG <="1111101"; --6

                           read_state<=over;

                       when over=>

                           SEG <= "0000111"; --7

                           read_state<=waiting;

                           tmp_read_addr<=tmp_read_addr + 1;

                   end case;

           end case;

        end if;

        DBC <= '1';

    end process;

end Behavioral;

4.思考题

静态存储器的读、写时序各有什么特点?

解:速度快,存储密度低,单位面积存储容量小,数据入/出共用管脚,能耗高,成本高。

三、综合实验总结

  1. 实验难点
  1. 一开始不明白为什么地址和数据能联系在一起,通过查阅资料,了解了地址线和数据线的绑定原理。
  2. 刚开始用数组存储,发现不能实现自由存储。明白内存的使用方法后,直接将数据存入内存相应地址中。
  1. 心得体会

通过本次实验,我对计算机内存有了更深刻的认识,明白了内存的存取原理和使用方法。掌握了如何存取数据和读出数据。

实验三 控制器实验

一、目的与要求

        1.实验目的

        (1)进一步理解和掌握计算机指令系统,包括指令功能,指令格式等。

        (2)了解控制器的基本组成和控制方法

        2.实验要求

  1. 编写VHDL程序,实现具有七条MIPS指令功能的控制器。
  2. 七条指令分别为:ADDU SUBU BNEZ JR OR LW SW。
  3. 7条指令格式及功能详见实验指导书。

二、实验正文

1.实验内容

编写一个简单的多周期控制器,并观察它的运行过程。

2.实验步骤

  1. 先定义输入输出,定义时钟,置0,刷新信号。定义16位拨码输入,16位LED输出控制信号。左右两侧数码管输出当前状态。
  2. 定义signal,其中定义状态机,来控制操作状态和输出状态。

3.代码部分

代码同实验四控制器部分

三、综合实验总结

  1. 实验难点

(1)定义状态机时不熟练,led灯不亮,经修改代码后成功运行。

  1. 心得体会

通过控制器实验,我对计算机控制器部分有了更深刻的认识,能够编写并使用控制器,知识也理解得更透彻。

实验四 16位CPU设计实验

一、目的与要求

        1.实验目的

       实现一个基于MIPS指令集的CPU,数据总线16位,地址总线16位,具有8个16位的通用寄存器。指令包括访存指令(如LW,SW),传送指令(如LI,MOVE),算术运算指令(如ADDU,SUBU),逻辑运算指令(NOT,OR),移位运算指令(如SLL),具体指令见实验指导书P23-P32。

        2.实验要求

  1. 完成7条指令,必须包括访存指令LW和SW,其余每类指令最多2条。
  2. 按照取指、译码、执行、访存和写回五个工作周期,分析每条指令的指令流程。
  3. 根据指令流程,设计每条指令的CPU数据通路,定义涉及的所有微操作控制信号。然后逐一合并数据通路,说明增加或减少处理器功能部件的理由。给出控制器的完整设计过程。
  4. 编写VHDL程序实现CPU,并通过实验板验证。

二、实验正文

1.实验内容

实现一个7条指令多周期CPU,数据总线16位,地址总线18位,具有8个16位的通用寄存器。

2.实验步骤

(1)定义输入输出,时钟信号,置0信号和刷新信号。定义16位拨码输入,16位LED输出,绑定地址线和数据线。定义状态切换信号showctrl,和左右两个数码管显示当前状态。

(2)定义signal,其中定义8个16位寄存器,寄存器地址000~111。定义不同部分的控制信号。定义PC,IR。定义状态机,控制操作状态,输出状态,和转移状态。

(3)在主程序中,先定义输出状态,前4个状态同实验三输出不同部分的控制信号。5~7状态输出x,y,z寄存器的值,令高三位显示寄存器地址,便于确认。8,9状态分别输出PC和IR寄存器中的值。

(4)控制操作状态机中,在指令读取状态(1)读取指令值存入IR中,在写x寄存器地址状态(2)写入x寄存器地址,在写x寄存器数据(3)中写x寄存器数据。在写y寄存器地址状态(4)写y寄存器地址,在写y寄存器数据状态(5)写y寄存器数据。这4个写寄存器地址数据的状态可控制寄存器数据的手动存入。在译码状态(6)中译码,指令的高5位位操作码,根据不同的操作码进行不同的操作。在执行状态(7)中执行不同操作。在是否进入访存状态(8)和写回状态(9)由执行状态确定。

(5)其中在进行转移指令时,需要定义一个转移状态机来实现数据更新。

(6)简易CPU实现了访存指令(LW和SW),传送指令(BEQZ和JR),算数运算指令(ADD和SUB),逻辑运算指令(XOR),移位指令(SLLV),共8条。使用了8个16位寄存器R0~R7,地址位000~111.

3.代码部分

entity CPU is

    Port ( rst : in  STD_LOGIC;  --复位信号

           clk : in  STD_LOGIC;  --时钟信号

           clk0 : in  STD_LOGIC;  --11.0592时钟信号

           SW_IN : in  STD_LOGIC_VECTOR (15 downto 0);  --输入

           light : out  STD_LOGIC_VECTOR (15 downto 0);  --LED输出

           SHOW_STATE_RIGHT : out  STD_LOGIC_VECTOR (6 downto 0):="1110110";  --输出当前状态 重置、取值、译码、执行、访存、写回 启动时显示H

           SHow_STATE_LEFT : out  STD_LOGIC_VECTOR (6 downto 0):="1110110";  --输出显示状态,同上

           ADDR : inout  STD_LOGIC_VECTOR (15 downto 0);  --RAM地址

           DATA : inout  STD_LOGIC_VECTOR (15 downto 0);  --RAM数据

           RAM1_EN : out  STD_LOGIC;  --RAM使能

           RAM1_OE : out  STD_LOGIC;  --RAM读使能

           RAM1_WE : out  STD_LOGIC;  --RAM写使能

           DBC : inout  STD_LOGIC;  --interconn3 SRAM 读锁存

           showctrl : in  STD_LOGIC;  --切换输出

           bzero_ctrl : in  STD_LOGIC);  -- 控 制PcWriteCond 用于判断是否满足转移条件

end CPU;

architecture Behavioral of CPU is

        --寄存器

        TYPE ARRAY_REG IS ARRAY(0 TO 7) OF STD_LOGIC_VECTOR(15 DOWNTO 0);    --定义的寄存器

        SIGNAL REGS:ARRAY_REG;

        signal rex:std_logic_vector(2 downto 0) := "000"; --寄存器 x 地址,通过地址找到对应寄存器

        signal rey:std_logic_vector(2 downto 0) := "000"; --寄存器 y 地址

        signal rez:std_logic_vector(2 downto 0) := "000"; --寄存器 z 地址

        signal memtoreg:std_logic_vector(1 downto 0); --写入寄存器堆的数据来源选择 (00-ALUout 01-主存中)

        signal regwrite:std_logic_vector(2 downto 0); --写寄存器控制 (000-无 001-将数据写入指定通用寄存器 010-写 SP 011-写 T)

        signal regdst:std_logic_vector(1 downto 0); --选择目的寄存器 (rx rz ry)

        signal iord:std_logic; --寄存器地址来源(0-指令 1-ALUout)

       

        signal taddr:std_logic_vector(15 downto 0);

       

        --SP 堆栈指针

        signal SP:std_logic_vector(15 downto 0) := x"0000";

       type shower_state is (pc,alu,mem,reg,regx,regy,regz,pc_show,ir_show); -- 显示状态 pc - alu - 储存 - 寄存器 -regxx -regy -regy

        signal shower:shower_state;

        type controler_state is (instruction_fetch,wxaddr,wxdata,wyaddr,wydata,decode,execute,mem_control,write_reg); --控制周期(取指、写x地址、写x数据、写y地址、写y数据、译码、执行、访存、写回)

        signal state:controler_state;

       

        type BEQZstate is(updateaddr,updatedata);

        signal beqz_state:BEQZstate;

       

        --PC

        signal pc_mem:std_logic_vector(15 downto 0) := x"0000"; --指令地址寄存器

        signal pcwrite:std_logic; --写入 PC(1-写入 PC)

        signal pcwritecond:std_logic; --转移指令的条件 (改写 PC)

        signal pcsource:std_logic; -- 新 的 PC 来 源 选 择 (0-ALUout 1- 存 有ALUout 的寄存器)

       

        --ALU

        signal aluop:std_logic_vector(1 downto 0); --ALU 操作码 OP(00-加 01-减 10-指令功能字段决定)

        signal alusrca:std_logic; --ALU 源操作数 A 的选择(1 寄存器 A 0 PC)

        signal alusrcb:std_logic_vector(1 downto 0); --ALU 源操作数 B 的选择(00 寄存器 B 01 常数 1 10-IR)

       

        --RAM

        signal memread:std_logic; --RAM 读

        signal memwrite:std_logic; --RAM 写

        --signal tmp_write_addr:std_logic_vector(15 downto 0); --临时读

        --signal tmp_read_addr:std_logic_vector(15 downto 0); --临时写

        --signal tmp_data:std_logic_vector(15 downto 0); --数据

       

        --IR

        signal instructions:std_logic_vector(15 downto 0); --指令寄存器 IR

        signal IR:std_logic_vector(15 downto 0) := x"0000";

        signal irwrite:std_logic; --写入 IR

        signal bzero:std_logic;

        signal tmpb_zero:std_logic;

        signal tmp_light:std_logic_vector(15 downto 0); --十六位输出

begin

--RAM_CTR:process(memread,memwrite)

--begin

-- RAM1_EN <= '0';

-- RAM1_OE <= NOT memread;

-- RAM1_WE <= NOT memwrite;f

--end process RAM_CTR;

        --输出切换

        Show_Switch_ctrl : process(clk,rst,showctrl)

        begin

                 if rst='0' then

                         SHow_STATE_LEFT <= "1110110"; --H

                         shower<=PC;

                 elsif rising_edge(showctrl) then

                         case shower is        --输出不同信号

                                  when pc =>

                                          shower<=alu;                                       --输出状态

                                          SHow_STATE_LEFT <= "0000110"; --1

                                  when alu =>

                                          shower<=mem;

                                          SHow_STATE_LEFT <= "1011011"; --2

                                  when mem =>

                                          shower<=reg;

                                          SHow_STATE_LEFT <= "1001111"; --3

                                  when reg =>

                                          shower<=regx;

                                          SHow_STATE_LEFT <= "1100110"; --4

                                  when regx =>

                                          shower<=regy;

                                          SHow_STATE_LEFT <= "1101101"; --5

                                  when regy =>

                                          shower<=regz;

                                          SHow_STATE_LEFT <="1111101"; --6

                                  when regz =>

                                          shower <= pc_show;

                                          SHow_STATE_LEFT <= "0000111"; --7

                                  when pc_show =>

                                          shower<= IR_show;

                                          SHow_STATE_LEFT <= "1111111"; --8

                                  when IR_show =>

                                          shower<=pc;

                                          SHow_STATE_LEFT <= "1110110"; --H

                         end case;

                 end if;

        end process Show_Switch_ctrl;

       

        --输出(先放入 temp signal)

        SHOW_SINGNAL:process(clk0,rst,state)

        begin                                            --输出状态

                 if rst='0' then

                         tmp_light <= "0000000000000000";

                 elsif rising_edge(clk0) then

                         case shower is

                                  when pc => --H

                                          tmp_light(15 downto 0)<=x"0000";

                                          tmp_light(15)<=pcwrite;

                                          tmp_light(11)<=pcsource;

                                          tmp_light(7)<=pcwritecond;

                                  when alu => --1

                                          tmp_light(15 downto 0)<=x"0000";

                                          tmp_light(15 downto 14)<=aluop;

                                          tmp_light(11)<=alusrca;

                                          tmp_light(7 downto 6)<=alusrcb;

                                  when mem => --2

                                          tmp_light(15 downto 0)<=x"0000";

                                          tmp_light(15)<=memread;

                                          tmp_light(11)<=memwrite;

                                          tmp_light(7)<=irwrite;

                                          tmp_light(3 downto 2)<=memtoreg;

                                  when reg => --3

                                          tmp_light(15 downto 0)<=x"0000";

                                          tmp_light(15 downto 13)<=regwrite;

                                          tmp_light(11 downto 10)<=regdst;

                                          tmp_light(7)<=iord;

                                  when regx => --4

                                          tmp_light(12 downto 0) <= REGS(conv_integer(rex))(12 downto 0);

                                          tmp_light(15 downto 13) <= rex;

                                  when regy => --5

                                     tmp_light(12 downto 0) <= REGS(conv_integer(rey))(12 downto 0);

                                          tmp_light(15 downto 13) <= rey;

                                  when regz => --6

                                     tmp_light(12 downto 0) <= REGS(conv_integer(rez))(12 downto 0);

                                          tmp_light(15 downto 13) <= rez;

                                  when PC_show => --7

                                          tmp_light <= pc_mem;

                                  when IR_show => --8

                                          tmp_light <= instructions;

                         end case;

                 end if;

        end process SHOW_SINGNAL;

       

        process(rst,bzero_ctrl)  --控制移位

        begin

                 if rst='0' then

                         bzero<='0';

                 elsif rising_edge(bzero_ctrl) then

                         if bzero = '0' then

                                  bzero<='1';

                                  tmpb_zero<='0';

                         elsif bzero='1' then

                                  tmpb_zero<='1';

                                  bzero<='0';

                         end if;

                 end if;

        end process;

       

        process(bzero)  --控制移位

        begin

                 if bzero='1' then

                         pcwritecond<='1';

                 elsif bzero='0' then

                         pcwritecond<='0';

                 end if;

        end process;

       

        process(rst,clk)

        begin                                             --控制状态

                 if(rst='0') then

                         RAM1_EN <= '1'; --RAM1 的片选信号

                         RAM1_OE <= '0'; --读信号

                         RAM1_WE <= '0'; --写信号

                         state<=instruction_fetch;

                         beqz_state<=updateaddr;    --BEQZ

                         SHOW_STATE_RIGHT <= "1110110"; --H

                         instructions <= X"0000";

                         iord<='0';

                         irwrite<='0';

                         memread<='0';

                         memwrite<='0';

                         memtoreg<="00";

                         aluop<="00";

                         alusrca<='0';

                         alusrcb<="00";

                         pcwrite<='0';

                         pcsource<='0';

                         regdst<="00";

                         regwrite<="000";

                 elsif rising_edge(clk)then

                         case state is

                                  when instruction_fetch => --取指令值

                                          SHOW_STATE_RIGHT <= "0000110"; --1-取值

                                          instructions <= SW_IN; --SW 使用拨片传入地址                   --将指令写入IR

                                          MemRead<='1';  --从存储器中读数据

                                          Memwrite <= '0';  --不写入存储器

                                          ALUSrcA<='0';  --来自PC

                                          IorD<='0';  --来源于PC

                                          beqz_state<=updateaddr;    --BEQZ

                                          ALUSrcB<="01";

                                          ALUOp<="00";

                                          PCWrite<='1';

                                          PCSource<='0';

                                          IRWrite<='1';

                                          RegWrite<="000";

                                          state<=wxaddr;

                                          rex <= instructions(10 downto 8);

                                         

                                  when wxaddr =>  --写x地址-----2

                                          SHOW_STATE_RIGHT<="1011011";

                         --              taddr <= SW_IN;

                                          rex<=SW_IN(2 downto 0);

                                          state<=wxdata;

                                                 

                                  when wxdata =>  --写x数据------3

                                          SHOW_STATE_RIGHT<="1001111";

                                          REGS(conv_integer(rex))<=SW_IN;

                                          state<=wyaddr;

                                                 

                                  when wyaddr =>  --写y地址------4

                                          SHOW_STATE_RIGHT<="1100110";

                         --              taddr<=SW_IN;

                                          rey<=SW_IN(2 downto 0);

                                          state<=wydata;

                                                 

                                  when wydata =>  --写y数据------5

                                     SHOW_STATE_RIGHT<="1101101";

                                          REGS(conv_integer(rey))<=SW_IN;

                                          state<=decode;

                                         

                                  when decode => --译码

                                          SHOW_STATE_RIGHT <= "1111101"; --6-译码

                                          IRWrite<='0';

                                          MemRead<='0';

                                          PCWrite<='0';

                                          ALUSrcA<='0';

                                          ALUSrcB<="10";

                                          ALUOp<="00";

                                          case instructions(15 downto 11) is

                                                  when "11100" => -- ADDU SUBU

                                                           rex <= instructions(10 downto 8);

                                                           rey <= instructions(7 downto 5);

                                                           rez <= instructions(4 downto 2);

                                                  when "00100" => --BEQZ

                                                           rex <= instructions(10 downto 8);

                                                  when "11101" =>

                                                           if (instructions(2 downto 0) = "000") then --JR

                                                                   rex <= instructions(10 downto 8);

                                                           elsif (instructions(2 downto 0) = "110") then --XOR

                                                                   rex <= instructions(10 downto 8);

                                                                   rey <= instructions(7 downto 5);

                                                           elsif (instructions(2 downto 0) = "100") then --SLLV

                                                                   rex <= instructions(10 downto 8);

                                                                   rey <= instructions(7 downto 5);

                                                           end if;

                                                  when "10011" => --LW

                                                           rex <= instructions(10 downto 8);

                                                           rey <= instructions(7 downto 5);

                                                  when "11011" => --SW

                                                           rex <= instructions(10 downto 8);

                                                           rey <= instructions(7 downto 5);

                                                  when others =>

                                                           null;

                                          end case;

                                          state<=execute;

                                  when execute=> --执行

                                          SHOW_STATE_RIGHT <= "0000111"; --7

                                          case instructions(15 downto 11)is

                                                  when "00100"=> --执行 BEQZ 如果x寄存器值为0,则跳转到目的地址执行

                                                           ALUSrcA<='1';

                                                           ALUOp<="10";

                                                           PCSource<='1';

                                                           rex <= instructions(10 downto 8);

                                                           state<=write_reg;

                                                  when "10011"=> --LW

                                                           ALUSrcA<='1';

                                                           ALUSrcB<="10";

                                                           ALUOp<="00";

                                                           state<=mem_control;

                                                           RAM1_EN <= '0';

                                                           RAM1_OE <= '0';

                                                           RAM1_WE <= '1';

                                                           rex <= instructions(10 downto 8);

                                                           rey <= instructions(7 downto 5);

                                                           ADDR <= REGS(conv_integer(rex)) + instructions(4 downto 0);

                                                  when "11011"=> --SW

                                                           RAM1_EN <= '0';

                                                           RAM1_OE <= '1';

                                                           RAM1_WE <= '0';

                                                           rex <= instructions(10 downto 8);

                                                           rey <= instructions(7 downto 5);

                                                           ADDR <= REGS(conv_integer(rex)) + instructions(4 downto 0);

                                                           ALUSrcA<='1';

                                                           ALUSrcB<="10";

                                                           ALUOp<="00";

                                                           state<=mem_control;

                                                  when "11100"=>

                                                           case instructions(1 downto 0) is

                                                                   when "01" => --ADDU

                                                                            ALUSrcA<='1';

                                                                            ALUSrcB<="00";

                                                                            ALUOp<="00";

                                                                            rex <= instructions(10 downto 8);

                                                                            rey <= instructions(7 downto 5);

                                                                            rez <= instructions(4 downto 2);

                                                                   when "11" => --SUBU

                                                                            ALUSrcA<='1';

                                                                            ALUSrcB<="00";

                                                                            ALUOp<="01";

                                                                            rex <= instructions(10 downto 8);

                                                                            rey <= instructions(7 downto 5);

                                                                            rez <= instructions(4 downto 2);

                                                                   when others=>

                                                                            null;

                                                           end case;

                                                           state<=write_reg;

                                                  when "11101"=>

                                                           case instructions(4 downto 0)is

                                                                   when "01110"=> --XOR

                                                                            ALUSrcA<='1';

                                                                            ALUSrcB<="00";

                                                                            ALUOp<="10";

                                                                            rex <= instructions(10 downto 8);

                                                                            rey <= instructions(7 downto 5);

                                                                            state<=write_reg;

                                                                   when "00000"=> --JR

                                                                            rex <= instructions(10 downto 8);

                                                                            --case instructions(7 downto 5)is

                                                                            --when "000"=>

                                                                            --ALUSrcA<='1';

                                                                            --ALUOp<="10";

                                                                            --PCWrite<='1';

                                                                            --PCSource<='0';

                                                                            --state<=instruction_fetch;

                                                                            --when others=>

                                                                            --null;

                                                                            state<=write_reg;

                                                                            --end case;

                                                                   when "00100"=>  --SLLV移位

                                                                            rex <= instructions(10 downto 8);

                                                                            rey <= instructions(7 downto 5);

                                                                            state<=write_reg;

                                                                   when others=>

                                                                            null;

                                                           end case;

                                                  when others=>

                                                           null;

                                          end case;

                                  when mem_control=> --访存

                                          SHOW_STATE_RIGHT <= "1111111"; --8

                                          PCWrite<='0';

                                          RegWrite<="000";

                                          case instructions(15 downto 11)is

                                                  when "10011"=> --LW

                                                           MemRead<='1';

                                                           IorD<='1';

                                                           state<=write_reg;

                                                           REGS(conv_integer(rey)) <= DATA;

                                                  when "11011"=> --SW

                                                           RAM1_EN <= '0';

                                                           RAM1_OE <= '0';

                                                           RAM1_WE <= '1';

                                                           MemWrite<='1';

                                                           IorD<='1';

                                                           state<=instruction_fetch;

                                                           DATA <= REGS(conv_integer(rey));

                                                  when others=>

                                                           null;

                                          end case;

                                  when write_reg=> --写回

                                          SHOW_STATE_RIGHT <= "1101111"; --9

                                          MemWrite<='0';

                                          MemRead<='0';

                                          case instructions(15 downto 11)is

                                                  when "10011"=> --LW

                                                           RegDst<="10";

                                                           RegWrite<="001";

                                                           MemtoReg<="01";

                                                           state<=instruction_fetch;

                                                  when "11011"=> --SW

                                                           MemWrite<='0';

                                                           IorD<='0';

                                                           state<=instruction_fetch;

                                                  when "11100"=> --SUBU ADDU

                                                           case instructions(1 downto 0)is

                                                                   when "11" => --SUBU

                                                                            REGS(conv_integer(rez)) <= REGS(conv_integer(rex)) - REGS(conv_integer(rey));

                                                                            RegDst<="01";

                                                                            RegWrite<="001";

                                                                            MemtoReg<="00";

                                                                   when "01" => --ADDU

                                                                            REGS(conv_integer(rez)) <= REGS(conv_integer(rex)) + REGS(conv_integer(rey));

                                                                            RegDst<="01";

                                                                            RegWrite<="001";

                                                                            MemtoReg<="00";

                                                                   when others=>

                                                                            null;

                                                           end case;

                                                           state<=instruction_fetch;

                                                  when "11101"=> --JR XOR

                                                           case instructions(4 downto 0)is

                                                                   when "00000"=> --JR

                                                                            pc_mem <= REGS(conv_integer(rex));

                                                                            RegDst<="00";

                                                                            RegWrite<="001";

                                                                            MemtoReg<="00";

                                                                            case beqz_state is

                                                                                    when updateaddr=>

                                                                                  ADDR<=pc_mem;

                                                                                  beqz_state<=updatedata;

                                                                     when updatedata=>

                                                                             instructions<=DATA;

                                                                            rex <= DATA(10 downto 8);

                                                                                            beqz_state<=updateaddr;

                                                                            state<=wxaddr;

                                                                            end case;

                                                                   when "01110"=> --XOR

                                                                            REGS(conv_integer(rex)) <= REGS(conv_integer(rex)) XOR REGS(conv_integer(rey));

                                                                            RegDst<="00";

                                                                            RegWrite<="001";

                                                                            MemtoReg<="00";

                                                                            state<=instruction_fetch;

                                                                   when "00100"=>   --SLLV

                                                                   REGS(conv_integer(rey))<=TO_STDLOGICVECTOR(To_bitvector(REGS(conv_integer(rey))) SLL CONV_INTEGER(REGS(conv_integer(rex))));

                                                                            state<=instruction_fetch;

                                                                   when others=>

                                                                            null;

                                                           end case;

                                                  when "00100" => --BEQZ

                                                           if (REGS(conv_integer(rex)) = 0) then

                                                                   pc_mem <= pc_mem + instructions(7 downto 0);

                                                                   case beqz_state is

                                                                when updateaddr=>

                                                                         ADDR<=pc_mem;

                                                                         beqz_state<=updatedata;

                                                                when updatedata=>

                                                                         instructions<=DATA;

                                                                   rex <= DATA(10 downto 8);

                                                                        beqz_state<=updateaddr;

                                                                         state<=wxaddr;

                                                       end case;

                                                           else

                                                                   pc_mem<= pc_mem + "0000000000000001";

                                                                   state<=instruction_fetch;

                                                           end if;                                                        

                                                  when others=>

                                                           null;

                                          end case;

--                                       state<=instruction_fetch;

                         end case;

                 end if;

                 dbc <= '1';

        end process;

        light<=tmp_light; --输出结果                                                                          

end Behavioral;

  1. 指令的数据通路图

三、综合实验总结

  1. 实验难点
  1. 刚开始做时不知道如何自由输入输入到寄存器中,思考后增加了寄存器地址数据输入的状态,来实现寄存器数据的手动写入。
  2. 此次实验的难点在于要将每条指令都设计出来,并进行验证。
  3. 在进行转移指令的编写时,一开始无法实现指令的传递,后来发现需要使用PC寄存器,定义了两个转移状态后实现了指令的正确转移。
  4. 在验证时发现存在数据刷新不及时的问题,经排查后发现是手动数据输入比状态转换慢了一拍,调整输入和切换状态时间后能正确验证,
  1. 心得体会

本次实验是一个综合性实验,刚看到题目是会有一些无从下手,但慢慢发现CPU的设计就是前面ALU,存储器,控制器设计的综合。将CPU的设计划分为几部分写,并把它们联系起来就可以实现。

组内分工:

负责代码编写,管脚约束,实验板调试。

申请优。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值