课程设计报告
名 称: 硬件设计与实践
题 目: 16位CPU设计
硬件设计与实践
任 务 书
一、 目的与要求
1.目的
1.1 培养学生在计算机硬件方面的动手实践能力;
1.2 熟悉VHDL硬件描述语言及开发环境,了解硬件系统开发的基本过程;
1.3 把前期学习阶段的知识和方法系统化,用以解决实际问题,为毕业设计做准备。
2.要求
2.1 运用所学的知识和方法采用最佳的解决问题思路,完成本次实践课程;
2.2 对要完成的内容进行详细的分析和设计,必要时画出指令的流程图;
2.3 编写简洁代码完成实验;
2.4 认真书写设计报告,包括设计实践过程中遇到的问题、解决办法,也包括课程体会及对本次实践的建议和意见。
二、 主要内容
内容:16位CPU设计
实现一个基于MIPS指令集的多周期CPU,数据总线16位,地址总线16位,具有8个16位的通用寄存器。指令格式包括R型指令,I型指令,B型指令和J型指令,具体指令见实验指导书P23-P32。
- 采用VHDL语言,完成至少7条指令,其中必须包括访存指令LW和SW,其余每类指令至少1条。
- 按照取指、译码、执行、访存和写回五个工作周期,分析指令的指令流程。
- 根据指令流程,设计每条指令的CPU数据通路,定义涉及的所有微操作控制信号。然后逐一合并数据通路,说明增加或减少处理器功能部件的理由。给出控制器的完整设计过程。
- 利用THINPAD教学计算机硬件平台,验证CPU运行的正确性。
备注:本次实验要求以小组为单位完成,*结组,每组3-4人。
三、 进度计划
序号 设计(实验)内容 完成时间 备注
1 接受课题并进行分析 第1周周一
2 根据任务书选题,查阅资料,设计方案 第1周周一~第1周周三
3 熟悉开发环境,学习开发工具 第1周周四
4 根据要实现的任务划分功能模块、模块功能实现、代码设计,在实验箱上调试 第1周周四~第2周周三
5 对照任务书检查、完善系统并完成验收 第2周周四
6 撰写并提交实验报告 第2周周五 下午4点前交
四、 设计(实验)成果要求
- 较完善的完成任务书所列主要内容,可查看实验结果并通过验收;
- 详细的写出实验报告,要求规范、认真,并及时提交实验报告;
- 杜绝报告抄袭行为,一经发现均判为不及格。
16位CPU设计
一、实验步骤
-
画出流程图
CPU结构图 -
设计指令编码方式
指令格式 -
根据相关指令查找不同控制信号在不同周期的显示方式
控制信号周期
4. 程序编写
5. 程序烧入电路板,进行实验结果观察和验证
与预期结果相同。
二、实验分析
- 流程图、指令方式、指令的周期的数据流通方式在实验指导书上都可以查到相关的资料,可以直接用于实验之中,加快我们对实验的理解;在实验指导书之中也有直接的程序代码,也可以进行修改。
- 实验的主要要求我们理解计算机系统的各种组成部件的功能和各种数据如何在内存和CPU之间流通,各种部件是怎样的各司其职,对相关数据进行处理。
- 在对整个流程有了初步的讨论之后,了解了相应的原理和工作流程之后就进行了相应的实验,在实验的信号现实等方面有了一些改进,使得在输入指令后可以更加简单的查看运行的结果,同时也增加了一些其他功能,如查看当前制定寄存器的内容,运行周期的查看等。
三、实验总结
首先在于对CPU的工作原理的理解上,我们进行了热烈的讨论。本次设计实验让我十分透彻的了解到了CPU的构造、工作原理,并且再一次加深了对VHDL的理解。CPU的设计非常复杂,但是通过指导书上的示例代码,以及网上的各种资料,我们最终实现了一个较为简单的CPU。
对于我们来说,刚开始完成确实存在了许多困难,而且因为我们对这门课程本身的了解不够深入而且对相关知识都有了一些遗忘,导致我们最后用了很长的时间对这个实验进行研究,不过还好最终我们有了一些成果,虽然还有很多不足,不过我们会不断学习加以完善。而且这次的实验本身也很有趣,从中我也收获了很多,又一次复习到了有关于CPU的知识。
四、参考文献
[1] 刘卫东,李山山,宋佳兴.计算机硬件系统实验教程.清华大学出版社.2013
[2] 程晓荣,王晓霞,李梅,翟学明,赵慧兰,徐伟峰.计算机组成与结构(第二版).中国电力出版社.2012
[3] https://github.com/
[4] https://www.csdn.net/
五、附录 - 代码
(1)约束
NET "CLK" LOC = U9; # CLK KEY
NET "RST" LOC = U11; # reset from RST KEY
NET "clk0" LOC = B8;
# handled switch ,dip totaly 16 bits.
NET "INPUT[0]" LOC = J6; #SW0
NET "INPUT[1]" LOC = J7;
NET "INPUT[2]" LOC = K2;
NET "INPUT[3]" LOC = K7;
NET "INPUT[4]" LOC = M1;
NET "INPUT[5]" LOC = N1;
NET "INPUT[6]" LOC = N2;
NET "INPUT[7]" LOC = R1;
NET "INPUT[8]" LOC = R4;
NET "INPUT[9]" LOC = U1;
NET "INPUT[10]" LOC = V2;
NET "INPUT[11]" LOC = V3;
NET "INPUT[12]" LOC = V4;
NET "INPUT[13]" LOC = U8;
NET "INPUT[14]" LOC = R7;
NET "INPUT[15]" LOC = T7; # SW15
# led lights ,on the TOP of the board.
# 7-seg digit display
NET "stateCnt_L[6]" LOC = F8;
NET "stateCnt_L[5]" LOC = E8;
NET "stateCnt_L[4]" LOC = A8;
NET "stateCnt_L[3]" LOC = F7;
NET "stateCnt_L[2]" LOC = E7;
NET "stateCnt_L[1]" LOC = D7;
NET "stateCnt_L[0]" LOC = C7;
NET "stateCnt_R[6]" LOC = B10;
NET "stateCnt_R[5]" LOC = A10;
NET "stateCnt_R[4]" LOC = G9;
NET "stateCnt_R[3]" LOC = F9;
NET "stateCnt_R[2]" LOC = E9;
NET "stateCnt_R[1]" LOC = D9;
NET "stateCnt_R[0]" LOC = C9;
# PlanAhead Generated IO constraints
NET "ADDR[0]" LOC = C17;
NET "ADDR[1]" LOC = C18;
NET "ADDR[2]" LOC = D16;
NET "ADDR[3]" LOC = D17;
NET "ADDR[4]" LOC = E15;
NET "ADDR[5]" LOC = E16;
NET "ADDR[6]" LOC = F14;
NET "ADDR[7]" LOC = F15;
NET "ADDR[8]" LOC = F17;
NET "ADDR[9]" LOC = F18;
NET "ADDR[10]" LOC = G13;
NET "ADDR[11]" LOC = G14;
NET "ADDR[12]" LOC = G15;
NET "ADDR[13]" LOC = G16;
NET "ADDR[14]" LOC = H14;
NET "ADDR[15]" LOC = H15;
NET "DATA[0]" LOC = J12;
NET "DATA[1]" LOC = J13;
NET "DATA[2]" LOC = J14;
NET "DATA[3]" LOC = J15;
NET "DATA[4]" LOC = J16;
NET "DATA[5]" LOC = J17;
NET "DATA[6]" LOC = K12;
NET "DATA[7]" LOC = K13;
NET "DATA[8]" LOC = K14;
NET "DATA[9]" LOC = K15;
NET "DATA[10]" LOC = L15;
NET "DATA[11]" LOC = L16;
NET "DATA[12]" LOC = L17;
NET "DATA[13]" LOC = L18;
NET "DATA[14]" LOC = M13;
NET "DATA[15]" LOC = M14;
NET "RAM1_EN" LOC = M15;
NET "RAM1_OE" LOC = M16;
NET "RAM1_WE" LOC = M18;
#PlanAhead Generated physical constraints
NET "DBC" LOC = C14;
NET "showCtrl" CLOCK_DEDICATED_ROUTE = "FALSE";
NET "showCtrl" LOC = U10;#在复位键
NET "bZero_ctrl" CLOCK_DEDICATED_ROUTE = "FALSE";
NET "bZero_ctrl" LOC = V16;
NET "CONTROL" CLOCK_DEDICATED_ROUTE = "FALSE";
NET "CONTROL" LOC = U14;
NET "clk_rw" LOC = V14;
(2)CPU(以LW、SW指令为例)
entity CPU is
Port ( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
clk0 : in STD_LOGIC;
showCtrl : in STD_LOGIC;
bZero_ctrl : in STD_LOGIC;
ADDR : inout STD_LOGIC_VECTOR (15 downto 0);--RAM地址
DATA : inout STD_LOGIC_VECTOR (15 downto 0);--RAM数据
INPUT : in STD_LOGIC_VECTOR (15 downto 0);--拨码开关输入
OUTPUT : out STD_LOGIC_VECTOR (15 downto 0);--LED
CONTROL : in STD_LOGIC;--RW状态转换
clk_rw : in STD_LOGIC; --控制读写进程
RAM1_EN : out STD_LOGIC; --RAM使能
RAM1_OE : out STD_LOGIC; --RAM读使能
RAM1_WE : out STD_LOGIC; --RAM写使能
stateCnt_L : out STD_LOGIC_VECTOR (6 downto 0);--左数码管,显示四种状态
stateCnt_R : out STD_LOGIC_VECTOR (6 downto 0);--右数码管,显示当前周期
dbc : out STD_LOGIC
);
end CPU;
architecture Behavioral of CPU is
type state is (instruction_fetch,decode,execute,mem_control,write_reg);
signal CU_state: state;
type show is (PC,ALU,M,REG);
signal State_show: show;
signal instruction : std_logic_vector(15 downto 0);--SW输入
signal RegDst : std_logic_vector(1 downto 0);--选择目的寄存器
signal RegWrite : std_logic_vector(2 downto 0);--写寄存器控制
signal MemtoReg : std_logic_vector(1 downto 0);--写入寄存器堆的数据来源选择
signal ALUSrcA : std_logic;--ALU源操作数A的选择
signal ALUSrcB : std_logic_vector(1 downto 0);--ALU源操作数B的选择
signal ALUOp : std_logic_vector(1 downto 0);--ALU运算功能的选择
signal MemRead : std_logic;--读寄存器
signal MemWrite : std_logic;--写寄存器
signal IorD : std_logic;--寄存器地址来源
signal IRWrite : std_logic;--写入IR
signal PcWrite : std_logic;--写入PC
signal PCSource : std_logic;--新的PC来源选择
signal PcWriteCond : std_logic;--转移指令的条件
begin
process(RST,showCtrl)
begin
if RST = '0' then
State_show <= PC;
stateCnt_L <= "0111111";--左显示管为0
elsif showCtrl'event and showCtrl = '1' then
case ADDR(2 downto 0) is--通过点击时钟来获取寄存器地址并将在七段数码显示管上显示出来
when "000" =>
stateCnt_L <= "0111111";--左显示管为0
when "001" =>
stateCnt_L <= "0000110";--左显示管为1
when "010" =>
stateCnt_L <= "1011011";--左显示管为2
when "011" =>
stateCnt_L <= "1001111";--左显示管为3
when "100" =>
stateCnt_L <= "1100110";--左显示管为4
when "101" =>
stateCnt_L <= "1101101";--左显示管为5
when "110" =>
stateCnt_L <= "1111101";--左显示管为6
when "111" =>
stateCnt_L <= "0000111";--左显示管为7
when others => null;
end case;
end if;
end process;
process(RST, CLK,CONTROL)
begin
if RST = '0' then
CU_state <= instruction_fetch;
stateCnt_R <= "0111111";--右显示管为0
instruction <= "0000000000000000";
RegDst <= "00";
RegWrite <= "000";
MemtoReg <= "00";
ALUSrcA <= '0';
ALUSrcB <= "00";
ALUOp <= "00";
MemRead <= '0';
MemWrite <= '0';
IorD <= '0';
IRWrite <= '0';
PcWrite <= '0';
PCSource <= '0';
instruction_fetch_state <= 0;
tmp_data <=x"0000";
tmp_read_addr <="0000000000000000";
tmp_addr <="0000000000000000";
control_state <= 0;
RAM1_EN <= '1'; --RAM1的片选信号
RAM1_OE <= '0'; --读信号
RAM1_WE <= '0'; --写信号
elsif CLK'event and CLK = '1' then
case CU_state is
when instruction_fetch =>
instruction <= INPUT;--获取输入
stateCnt_R <= "0000110";--右显示管为1
RegDst <= "00";
RegWrite <= "000";
MemtoReg <= "00";
ALUSrcA <= '0';
ALUSrcB <= "01";
ALUOp <= "00";
MemRead <= '1';
MemWrite <= '0';
IorD <= '0';
IRWrite <= '1';
PcWrite <= '1';
PCSource <= '0';
instruction_fetch_state <= 0;
CU_state <= decode;
when decode =>
stateCnt_R <= "1011011";--右显示管为2
AluSrcA <= '0';
ALUSrcB <= "10";
ALUOp <= "00";
MemRead <= '0';
IRWrite <= '0';
PcWrite <= '0';
CU_state <= execute;
case instruction(15 downto 11) is
when "10011" => --LW
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
im <= instruction(4 downto 0);
when "11011" => --SW
rx <= instruction(10 downto 8);
ry <= instruction(7 downto 5);
im <= instruction(4 downto 0);
when others =>null;
end case;
when execute =>
stateCnt_R <= "1001111";--右显示管为3
control_state <= 0;
case instruction(15 downto 11) is
when "11100" =>
if instruction(1 downto 0) = "01" then --ADDU
ALUSrcA <= '1';
ALUSrcB <= "00";
ALUOp <= "00";
elsif instruction(1 downto 0) = "11" then --SUBU
ALUSrcA <= '1';
ALUSrcB <= "00";
ALUOp <= "01";
end if;
CU_state <= write_reg;
when others =>null;
end case;
when "10011" => --LW
ALUSrcA <= '1';
ALUSrcB <= "10";
ALUOp <= "00";
CU_state <= write_reg;
when "11011" => --SW
ALUSrcA <= '1';
ALUSrcB <= "10";
ALUOp <= "00";
CU_state <= write_reg;
when others =>
null;
end case;
when mem_control =>
stateCnt_R <= "1100110";--右显示管为4
case instruction(15 downto 11) is
when "10011" => --LW
RegWrite <= "000";
MemRead <= '1';
IorD <= '1';
PcWrite <= '0';
case control_state is
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
DATA(4 downto 0) <= DATA(4 downto 0) + im;
tmp_read_addr <= DATA;
CU_state <= mem_control;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 4;
when others => null;
end case;
when "11011" => --SW
RegWrite <= "000";
MemWrite <= '1';
IorD <= '1';
PcWrite <= '0';
case control_state is
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
DATA(4 downto 0) <= DATA(4 downto 0) + im;
tmp_addr <= DATA;
CU_state <= mem_control;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <= write_reg;
control_state <= 0;
when others =>null;
end case;
when others =>null;
end case;
when write_reg =>
stateCnt_R <= "1101101";--右显示管为5
case instruction(15 downto 11) is
when "11100" =>
case instruction(1 downto 0) is
when "10011" => --LW
RegDst <= "10";
RegWrite <= "001";
MemtoReg <= "01";
MemRead <= '0';
MemWrite <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr <= "0000000000000000";
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= mem_control;
control_state <= 2;
when 4 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 5;
when 5 =>
ADDR <= tmp_addr;
DATA <= tmp_data;
RAM1_WE<='0';
RAM1_OE<='1';
CU_state <= instruction_fetch;
control_state <= 0;
when others =>null;
end case;
when "11011" => --SW
MemRead <= '0';
MemWrite <= '0';
IorD <= '0';
case control_state is
when 0 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_addr <= "0000000000000000";
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= ry;
CU_state <= write_reg;
control_state <= 1;
when 1 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= write_reg;
control_state <= 2;
when 2 =>
RAM1_EN <= '0';
RAM1_OE <= '1';
RAM1_WE <= '1';
tmp_data <= DATA;
tmp_read_addr <="0000000000000000";
tmp_read_addr(2 downto 0) <= rx;
CU_state <= write_reg;
control_state <= 3;
when 3 =>
ADDR <= tmp_read_addr;
DATA <= (others=>'Z');
RAM1_OE<='0';
RAM1_WE<='1';
CU_state <= mem_control;
control_state <= 4;
when others =>null;
end case;
when others => null;
end case;
end case;
end if;
end process;
- 实验截图