系列文章目录
【计算机组织与体系结构】实验一:算术逻辑单元的实现
【计算机组织与体系结构】实验二:给定指令系统的处理器设计
【计算机组织与体系结构】实验三:流水线处理器
【计算机组织与体系结构】实验四:指令 CACHE 的设计与实现
文章目录
一、实验目的
- 掌握 Vivado 集成开发环境
- 掌握 Verilog 语言基本知识
- 掌握 Verilog 语言设计并实现组合逻辑电路
二、实验环境
Vivado 集成开发环境
三、实验内容
1、ALU 操作要求
完成一个简单的、具有执行 16 种算术逻辑运算操作的电路,要求的 16 种操作如下表所示
Note:/
是逻辑非操作, ⊙
是逻辑同或操作, ⊕
是逻辑异或操作。
2、模块接口设计
信号说明如下:
1) 定义四个输入信号 A、 B、 Cin、 Card。其中, A、 B 为 32 位运算数, Card 为 5 位运算操作码, Cin 为进位。
2) 定义三个输出信号 F, Cout, Zero,其中 F 为运算结果, Cout 为结果进位, Zero 为零标志。
要求根据 16 种运算操作对运算操作码 Card 进行编码,并实现这 16 种运算操作。
四、实验设计
1、写出ALU(算术逻辑单元)的16种运算的编码
2、设计文件 alu.v
//alu.v
`timescale 1ns / 1ps //仿真时间单位/仿真时间精度
//定义16种运算的编码
`define A_ADD_B 5'b00001 //A+B---1号
`define A_ADD_B_Cin 5'b00010 //A+B+Cin
`define A_SUB_B 5'b00011 //A-B
`define A_SUB_B_Cin 5'b00100 //A-B-Cin
`define B_SUB_A 5'b00101 //B-A
`define B_SUB_A_Cin 5'b00110 //B-A-Cin
`define Value_A 5'b00111 //A
`define Value_B 5'b01000 //B
`define NOT_A 5'b01001 //A非----9号
`define NOT_B 5'b01010 //B非
`define A_OR_B 5'b01011 //或
`define A_AND_B 5'b01100 //与
`define A_XNOR_B 5'b01101 //同或
`define A_XOR_B 5'b01110 //异或
`define A_NAND_B 5'b01111 //与非
`define ZERO 5'b01000 //零
module alu(
input [31:0] A, //A为32位运算数
input [31:0] B, //B为32位运算数
input Cin, //Cin为进位,0或者1
input [4:0] Card, //Card为5位运算操作码
output [31:0] F, //F为运算结果
output Cout, //Cout为进位结果
output Zero //Zero为零标志
);
wire [31:0] a_add_b_result; //1
wire [31:0] a_add_b_cin_result;
wire [31:0] a_sub_b_result;
wire [31:0] a_sub_b_cin_result;
wire [31:0] b_sub_a_result;
wire [31:0] b_sub_a_cin_result;
wire [31:0] value_a_result;
wire [31:0] value_b_result;
wire [31:0] not_a_result; //9
wire [31:0] not_b_result;
wire [31:0] a_or_b_result;
wire [31:0] a_and_b_result;
wire [31:0] a_xnor_b_result;//同或
wire [31:0] a_xor_b_result; //异或
wire [31:0] a_nand_b_result;
wire [31:0] zero_result;
//前六种运算有进位,需要用Cout1-6记录下来
wire cout_1;
wire cout_2;
wire cout_3;
wire cout_4;
wire cout_5;
wire cout_6;
//计算十六种运算
assign {cout_1,a_add_b_result}= A + B; //00001
assign {cout_2,a_add_b_cin_result} = A + B + Cin;
assign {cout_3,a_sub_b_result} = A - B;
assign {cout_4,a_sub_b_cin_result} = A - B - Cin;
assign {cout_5,b_sub_a_result} = B - A;
assign {cout_6,b_sub_a_cin_result} = B - A - Cin;
assign value_a_result = A;
assign value_b_result = B;
assign not_a_result = ~A; //01001
assign not_b_result = ~B;
assign a_or_b_result = A | B;
assign a_and_b_result = A & B;
assign a_xnor_b_result = ~(A ^ B);//同或
assign a_xor_b_result = A ^ B; //异或
assign a_nand_b_result = ~(A & B);
assign zero_result = 0;
//根据运算操作码进行运算的选择
//计算F
assign F = ({32{Card == `A_ADD_B}} & a_add_b_result) |
({32{Card == `A_ADD_B_Cin}} & a_add_b_cin_result) |
({32{Card == `A_SUB_B}} & a_sub_b_result) |
({32{Card == `A_SUB_B_Cin}} & a_sub_b_cin_result) |
({32{Card == `B_SUB_A}} & b_sub_a_result) |
({32{Card == `B_SUB_A_Cin}} & b_sub_a_cin_result) |
({32{Card == `Value_A}} & value_a_result) |
({32{Card == `Value_B}} & value_b_result) |
({32{Card == `NOT_A}} & not_a_result) |
({32{Card == `NOT_B}} & not_b_result) |
({32{Card == `A_OR_B}} & a_or_b_result) |
({32{Card == `A_AND_B}} & a_and_b_result) |
({32{Card == `A_XNOR_B}} & a_xnor_b_result) |
({32{Card == `A_XOR_B}} & a_xor_b_result) |
({32{Card == `A_NAND_B}} & a_nand_b_result) |
({32{Card == `ZERO}} & zero_result)|0;
//计算进位Cout
assign Cout = ((Card == `A_ADD_B) & cout_1) |
((Card == `A_ADD_B_Cin) & cout_2) |
((Card == `A_SUB_B) & cout_3) |
((Card == `A_SUB_B_Cin) & cout_4) |
((Card == `B_SUB_A) & cout_5) |
((Card == `B_SUB_A_Cin) & cout_6)|0;
//计算Zero,如果F为0,则零标志置为1
assign Zero = (F == 0)|0;
endmodule
3、仿真文件 alu_tb.v
//alu_tb.v
`timescale 1ns / 1ps //仿真时间单位/仿真时间精度
module alu_tb(
);
reg [31:0] a, b;
reg cin;
reg [4:0] card;//操作码
wire [31:0] f;
wire cout, zero;
initial begin
card = 5'b00001;
cin = 1'b0;
a = 32'h00000011;
b = 32'hffffffff;//进位1,00000010
#10 card = 5'b00010;
cin = 1'b1;
a = 32'h00000001;
b = 32'hffffffff;//进位1,00000001
#10 card = 5'b00011;
cin = 1'b1;
a = 32'hffffffff;
b = 32'hfffffffe;//进位0,00000001
#10 card = 5'b00100;
cin = 1'b1;
a = 32'hfffffff1;
b = 32'hfffffff1;//进位1,等于ffffffff
#10 card = 5'b00101;
cin = 1'b1;
a = 32'h00000000;
b = 32'hffffffff;//ffffffff
#10 card = 5'b00110;
cin = 1'b1;
a = 32'h00000000;
b = 32'hffffffff;//fffffffe
#10 card = 5'b00111;
cin = 1'b1;
a = 32'h00000001;
b = 32'h00000002;//1
#10 card = 5'b01000;
cin = 1'b1;
a = 32'h00000001;
b = 32'h00000002;//2
#10 card = 5'b01001;
cin = 1'b1;
a = 32'h00000003;
b = 32'hffffffff;//fffffffc
#10 card = 5'b01010;
cin = 1'b1;
a = 32'h00000000;
b = 32'hfffffffe;//1
#10 card = 5'b01011;
cin = 1'b1;
a = 32'h00000000;
b = 32'h0f0f0f0f;//0f0f0f0f
#10 card = 5'b01100;
cin = 1'b1;
a = 32'hf0f0f050;
b = 32'hffffff1f;//f0f0f010
#10 card = 5'b01101;
cin = 1'b1;
a = 32'h00000f60;
b = 32'hf89fffff;//07600f60
#10 card = 5'b01110;
cin = 1'b1;
a = 32'h0000f000;
b = 32'hffff67ff;//ffff97ff
#10 card = 5'b01111;
cin = 1'b1;
a = 32'h06009070;
b = 32'hff9ffaff;//f9ff6f8f
#10 card = 5'b10000;
cin = 1'b1;
a = 32'h00000000;
b = 32'hffffffff;//0
#10 card = 5'b10001;
cin = 1'b1;
a = 32'h00000001;
b = 32'hfffffff1;
#10 card = 5'b10010;
#10 card = 5'b10011;
#10 card = 5'b10100;
#10 card = 5'b10101;
#10 card = 5'b10110;
#10 card = 5'b10111;
#10 card = 5'b11000;
#10 card = 5'b11001;
#10 card = 5'b11010;
#10 card = 5'b11011;
#10 card = 5'b11100;
#10 card = 5'b11101;
#10 card = 5'b11110;
#10 card = 5'b11111;
end
//例化被测试模块
alu alu_0(
.A (a),
.B (b),
.Cin (cin),
.Card (card),
.F (f),
.Cout (cout),
.Zero (zero)
);
endmodule
五、测试结果及实验分析
测试波形与测试结果:
实验结果分析:
将实验结果与笔算结果进行比较,发现输出完全正确。
对于算术运算。对于有进位的情况,可以正确将进位表示置为1或0,例如对于A-B-Cin这种情况,在仿真时选取了结果为-1的情况,可以正确得到cout为1,f为ffffffff;对于A+B这种情况,在仿真时,选取了00000011 + ffffffff结果为正数且有进位的情况,显然进位为cout应为1,f应为00000010,输出结果正确。对于结果为0的情况,无论是否有进位,都可以将Zero正确置为1,如上表中A – B(无进位)和A + B + Cin(有进位)的情况。
对于逻辑运算,进位不参与逻辑运算,结果与手算结果相同。
对于F = 0的情况,可以将Zero置1,F置为00000000,Cout置为0。
对于Card不属于16种条件码的情况,设置F的值为0,进位Cout置为0,Zero设置为1。
总结
这次实验利用verilog语言,实现了ALU的16种算术逻辑运算操作。通过这次实验,熟悉了verilog语言以及vivado软件的基本使用方法,学会了如何编写设计文件、仿真文件以及仿真,提高了动手能力。
没有回复内容