【计算机组织与体系结构及其FPGA实现】实验一:算术逻辑单元的实现-FPGA常见问题论坛-FPGA CPLD-ChipDebug

【计算机组织与体系结构及其FPGA实现】实验一:算术逻辑单元的实现

 

 

系列文章目录

【计算机组织与体系结构】实验一:算术逻辑单元的实现
【计算机组织与体系结构】实验二:给定指令系统的处理器设计
【计算机组织与体系结构】实验三:流水线处理器
【计算机组织与体系结构】实验四:指令 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软件的基本使用方法,学会了如何编写设计文件、仿真文件以及仿真,提高了动手能力。

 

请登录后发表评论

    没有回复内容