计算机组成原理实验单周期CPU的设计与实验
);
assign O = (Sel == 2'b00)? A : (Sel == 2'b01)? B : (Sel == 2'b10)? C : D; Endmodule
4.3 5位2选1选择器的设计与实现
5位2选1选择器的逻辑框图如图4-19所示。
Sel
Function:
A[4:0] B[4:0]
M U X O[4:0]
Sel = 0:O = A Sel = 1:O = B
图4-19 5位2选1逻辑框图
5位2选1选择器的模块设计步骤可参考32位2选1选择器的设计步骤,下面给出5位2选1选择器的模块代码。
module MUX5_2_1(
input [4:0] A, input [4:0] B, input Sel, output[4:0] O );
assign O = Sel? B :A; Endmodule
4.4 带有异步清零的32位D触发器的设计与实现
异步是指清零与时钟无关,只要有效就清零。其设计步骤可参考32位2选1选择器的设计步骤,下面给出其模块Verilog实现代码:
module dff32(
input [31:0] D, input Clock, input Reset,
output reg [31:0] Q );
always @(posedge Clock or negedge Reset) begin if(Reset == 0) Q <= 0; else Q <= D; end endmodule
计算机科学与工程学院 19
计算机组成原理实验单周期CPU的设计与实验
4.5移位器的设计
移位器的功能是将一个数进行逻辑左移、逻辑右移或算术右移。其设计步骤可参考32位2选1选择器的设计步骤,下面给出其模块Verilog实现代码:
module Shifter(
input [31:0] D, input [4:0] Sa, input Right, input Arith, output reg [31:0] O );
always @(*) begin
if (!Right) O = D << Sa ; else if (!Arith) O = D >> Sa;
else O = $signed(D) >>> Sa; end
endmodule
4.6 32位加/减法器的设计与实现
32位加/减法器的功能是完成32位的加法/减法运算。由于:
A?B?A?(?B)?A?B?1
故可以用加法器实现减法操作。下面给出其模块Verilog实现代码:
module addsub32(
input [31:0] A, input [31:0] B, input sub, output[31:0] Result );
cla32 as32(A , B^{32{sub}} , sub , Result);
endmodule
module cla32(
input [31:0] a, input [31:0] b, input c, output[31:0] s );
assign s = a + b + c; endmodule
计算机科学与工程学院 20
计算机组成原理实验单周期CPU的设计与实验
5.运算器(ALU)的设计与实现
运算器ALU是CPU组成的核心部件之一,其实现方法主要有2种:一种是以加法器为核心,通过改变进位函数实现;另一种是运算部件并行多路选择实现。本实验采用运算部件并行多路选择实现。综合表3-1的指令,ALU只需完成9种运算即可,具体完成的功能如表5-1所示。
表5-1:ALU功能真值表
ALU_Operation x000 x100 x001 x101 x010 x110 0011 0111 1111 功能描述 Add(加) Sub(减) And(与) Or(或) Xor(异或) Lui(设置高位) Sll(左移) Srl(右移) Sra(算术右移) ALU的逻辑框图如图5-1所示。在图5-1中各信号的功能:
ALU_Operation[3:0]
? A:操作数,32位,输入; ? B:操作数,32位,输入; ? ALU_Operation:4位操作码,输
Zero
Result[31:0]
A[31:0] 入;
? Result:运算结果,32位,输出; ? Zero:零标志,1位;当运算结果为0时,该位为1,否则为0;
B[31:0] 图5-1 ALU电路符号
在工程管理区任意位置单击鼠标右键,在弹出的菜单中选择New Source命令,选择Verilog Module输入,并输入Verilog文件名:ALU,单击Next按钮进入端口定义对话框。其中Module Name栏输入模块名:ALU,单击Next进入下一步,点击Finish完成创建。ALU模块的Verilog程序参考代码:
module ALU(
input [31:0] A, input [31:0] B,
计算机科学与工程学院
21
计算机组成原理实验单周期CPU的设计与实验
input [3:0] ALU_Operation, output [31:0] Result, output Zero );
wire [31:0] d_and = A & B; wire [31:0] d_or = A | B; wire [31:0] d_xor = A ^ B;
wire [31:0] d_lui = {B[15:0],16'h0};
wire [31:0] d_and_or = ALU_Operation[2]? d_or:d_and; wire [31:0] d_xor_lui = ALU_Operation[2]? d_lui:d_xor; wire [31:0] d_as , d_sh;
addsub32 as32 (A , B , ALU_Operation[2] , d_as); Shifter shift_1 ( B , A[4:0] , ALU_Operation[2] ,
ALU_Operation[3] , d_sh);
MUX32_4_1 sel ( d_as , d_and_or , d_xor_lui , d_sh ,
ALU_Operation[1:0] , Result);
assign Zero = ~|Result; endmodule
对ALU进行仿真。在工程管理区将View设置为Simulation,在任意位置单击鼠标右键,并在弹出的菜单中选择New Source,在类型中选择Verilog Test Fixture,输入测试文件名:ALU_tb,单击Next按钮,这时所有工程中的模块名都会显示出来,选择要进行测试的模块:ALU。点击Next ,再单击Finish按钮,ISE会在源代码编辑区自动生成测试模块的代码。我们看到,ISE已经自动生成了基本的信号并对被测模块做了实例化。
对ALU_tb模块,我们可以添加如下所示的测试激励代码。
// Add stimulus here A <= 32'h1234; B <= 32'h5678; ALU_Operation <= 4'b0000; //add
#100
A <= 32'h1234abcd; B <= 32'hf0f0f0f0; ALU_Operation <= 4'b001; //and
#100
A <= 32'h12345678; B <= 32'h78; ALU_Operation <= 4'b0010; //xor
#100
A <= 32'h4; B <= 32'habcd;
ALU_Operation <= 4'b0011; //sll #100
A <= 32'h1234;
B <= 32'h5678;
22
计算机科学与工程学院
计算机组成原理实验单周期CPU的设计与实验
ALU_Operation <= 4'b0100; //sub
#100
A <= 32'h1234; B <= 32'h0ff; ALU_Operation <= 4'b0101; //or
#100
A <= 32'h1234; B <= 32'habcd; ALU_Operation <= 4'b0110; //lui
#100
A <= 32'h4; B <= 32'hf2345678; ALU_Operation <= 4'b0111; //SRL
#100
ALU_Operation <= 4'b1111; //SRA
完成测试文件编辑后,确认工程管理区中View选项设置为Simulation,这时在过程管理区会显示与仿真有关的进程。右键单击其中的Simulate Behavioral Model项,选择弹出菜单中的Process Properties项,会弹出属性设置对话框,将其中Simulation Run Time设置为1000ns。
仿真参数设置完后,就可以进行仿真。首先在工程管理区选中测试模块ALU_tb,然后在过程管理区双击Simulate Behavioral Model,ISE将启动ISE Simulator,可以得到仿真结果,如图5-2所示。
图5-2 ALU仿真结果
计算机科学与工程学院 23