指令,SLTU无符 号判断大 A
J指令,向本身跳转,不断循环 通过顶层仿真分析,证明流水线寄存器与各模块之间的链接正确。
至此,流水线MIPS微处理器设计全部符合要求。
七、 综合约束实现
打开PipelineCPU_VGA中的工程文件,将已完成的代码添加到工程文件中,对工
程进行综合、约束、实现,下载到XUP Virtex-Ⅱ Pro开发实验板中。接入SVGA显示器,复位,每按一下UP键,MIPS CPU运行一步。观察显示器显示的结果,结果正确。具体操作步骤不再赘述。
八、 实验心得
本次实验代码编写部分较为简单,实验指导中已经很明确的给出了各个模块中的
工作原理与信号之间的逻辑关系,但由于连接信号众多,信号名称相近,很容易由于录入粗心而产生错误,这也是本次实验最主要的错误来源。
我认为本次实验的难点在于对流水线CPU多种工作状态的整体把握,以及顶层仿真中的纠错工作。流水线CPU速度更快,多条指令同时运行,这就要求我们对不同指令的运行以及数据的传递有一定的认识。在理论课程中已经对流水线CPU有了一定的了解学习,通过实验可以更直观更透彻的学习其具体流程和实现方式。
由于各子模块的结构清晰、原理明确,仿真中出现的错误也很容易纠正,但在顶层模块中存在各级数据转发,同一指令各级运行时间不同,错误的排查有一定困难。实验中我出现的错误也主要在顶层仿真中。出现错误时我一般会先观察错误波形所对应的输入波形是否正确,若正确再顺着输入信号向前一级排查直至信号源。如果输入信号全部正常,则问题在于错误波形所在模块,仔细检查模块的各个输入输出信号之间的逻辑关系是否正确,再具体排查一遍代码中是否存在问题,基本就可以发现错误
31
所在。我在顶层仿真时EX级与MEM级的输出信号存在红线,将其展开发现信号部分错误,检查输入信号也是同样问题。继续向前一级检查发现ID/EX寄存器与EX/MEM寄存器的输出信号位数不对,查看顶层设计代码发现编写寄存器时个别D触发器的输入输出信号位数没有定义,改正后顶层仿真就正确了。
在ISE工程文件中同样要注意信号参数的传递,工程中时钟信号有一定变化,模块连接过程中也要注意传递信号的名称是否与工程定义的一致。
回顾整个实验过程,最重要的是严谨细致的态度。笔误这种错误最容易避免,也最容易发生,排查起来却相当费力。只要再细心一点,实验就能更轻松一点。对于仿真软件的应用也更为熟练,学习到很多新的方便的小功能,对于分析波形很有帮助。
实验中的不足之处在于对ISE软件的应用还是很生涩,很多功能仍未学习到,一些错误提示也不理解,还需要进一步学习。
32
附录一:流水线MIPS微处理器的原理框图
33
附录二:部分代码
1. Decode中ALUCode状态机
reg [4:0] ALUCode; always @(*) begin
if(op==R_type_op) begin case(funct)
ADD_funct: ALUCode<=alu_add; ADDU_funct: ALUCode<=alu_add; AND_funct: ALUCode<=alu_and; XOR_funct: ALUCode<=alu_xor; OR_funct: ALUCode<=alu_or; NOR_funct: ALUCode<=alu_nor; SUB_funct: ALUCode<=alu_sub;
SUBU_funct: ALUCode<=alu_sub; SLT_funct : ALUCode<=alu_slt; SLTU_funct : ALUCode<=alu_sltu; SLL_funct: ALUCode<=alu_sll;
SLLV_funct: ALUCode<=alu_sll; SRL_funct: ALUCode<=alu_srl; SRLV_funct: ALUCode<=alu_srl; SRA_funct: ALUCode<=alu_sra; default: ALUCode<=alu_sra; endcase end else begin case(op)
BEQ_op: ALUCode<=alu_beq; BNE_op: ALUCode<=alu_bne;
BGEZ_op: begin if(rt==BGEZ_rt) ALUCode<=alu_bgez;
BGTZ_op: begin if(rt==BGTZ_rt) ALUCode<=alu_bgtz; BLEZ_op: begin if(rt==BLEZ_rt) ALUCode<=alu_blez; BLTZ_op: begin if(rt==BLTZ_rt) ALUCode<=alu_bltz; ADDI_op: ALUCode<=alu_add; ADDIU_op: ALUCode<=alu_add; ANDI_op: ALUCode<=alu_andi; XORI_op: ALUCode<=alu_xori;
ORI_op: ALUCode<=alu_ori;
SLTI_op: ALUCode<=alu_slt; SLTIU_op: ALUCode<=alu_sltu; SW_op: ALUCode<=alu_add;
end end
end end 34
LW_op: ALUCode<=alu_add; default: ALUCode<=alu_add;
endcase end end
2. ALU
module ALU ( Result,ALUCode, A, B); input [4:0] ALUCode;
// Operation select
input [31:0] A, B; output [31:0]
Result;
reg [31:0] Result;
//***************************************************************************** // Shift operation: \// must be reg signed
//***************************************************************************** reg signed [31:0] B_reg;
always @(B) begin
B_reg = B; end
// Decoded ALU operation select (ALUsel) signals
//略
//***************************************************************************** // ALU Result datapath
//**************************************************************************** wire [31:0] sum,B1; wire Binvert;
assign Binvert=~(ALUCode==alu_add); assign B1=B^{32{Binvert}};
adder_32bits add( .a(A), .b(B1), .ci(Binvert), .s(sum), .co());
always @(*) begin
case(ALUCode) alu_add: Result<=sum; alu_and: Result<=A&B; alu_xor: Result<=A^B; alu_or: Result<=A|B; alu_nor: Result<=~(A|B); alu_sub: Result<=sum;
alu_andi: Result<=A&{16'd0,B[15:0]}; alu_xori: Result<=A^{16'd0,B[15:0]}; alu_ori: Result<=A|{16'd0,B[15:0]}; alu_sll: Result<=B<>A; alu_sra: Result<=B_reg>>>A;
35