• 算术逻辑单元的实现(ALU)


    一、实验目的

    • 掌握Vivado集成开发环境
    • 掌握Verilog语言基本知识、
    • 掌握并理解算术逻辑单元ALU的原理和设计

    二、实验预习

    1.ALU(算术逻辑单元)的16种运算的编码

    三、模块接口设计

    ALU的信号说明如下:

    • 定义四个输入信号A、B、Cin、Card。其中,A、B为32位运算数,Card为5位运算操作码,Cin为进位。
    • 定义三个输出信号F,Cout,Zero,其中F为运算结果,Cout为结果进位,Zero为零标志。
    • 要求根据16种运算操作对运算操作码Card进行编码,并实现这16种运算操作。

    四、实验设计

    设计代码

    `define A_ADD_B         5'b00001 // A 加 B
    `define A_ADD_B_ADD_CIN 5'b00010 // A 加 B 加 Cin
    `define A_SUB_B         5'b00011 // A 减 B 减 
    `define A_SUB_B_SUB_CIN 5'b00100 // A 减 B 减 Cin
    `define B_SUB_A         5'b00101 // B 减 A
    `define B_SUB_A_SUB_CIN 5'b00110 // B 减 A 减 Cin
    `define VALUE_A         5'b00111 // F = A
    `define VALUE_B         5'b01000 // F = B
    `define NOT_A           5'b01001 // F = /A
    `define NOT_B           5'b01010 // F = /B
    `define A_OR_B          5'b01011 // F = A + B
    `define A_AND_B         5'b01100 // F = AB
    `define A_XNOR_B        5'b01101 // 同或
    `define A_XOR_B         5'b01110 // 异或
    `define A_NAND_B        5'b01111 // F = /(AB)
    `define ZERO_FLAG       5'b10000 // F = 0
    
    module alu (
        input  [31:0]   A   ,
        input  [31:0]   B   ,
        input           Cin ,
        input  [4 :0]   Card,
        
        output [31:0]   F   ,
        output          Cout,
        output          Zero
    );
        
        wire [31:0]    a_add_b_result;
        wire [31:0]    a_add_b_add_cin_result;
        wire [31:0]    a_sub_b_result;
        wire [31:0]    a_sub_b_sub_cin_result;
        wire [31:0]    b_sub_a_result;
        wire [31:0]    b_sub_a_sub_cin_result;
        wire [31:0]    value_a_result;
        wire [31:0]    value_b_result;
        wire [31:0]    not_a_result;
        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_flag_result;
        
        // 6 个进位
        wire cout_1;
        wire cout_2;
        wire cout_3;
        wire cout_4;
        wire cout_5;
        wire cout_6;
        // 16 种运算
        assign {cout1, a_add_b_result} = A + B;
        assign {cout2, a_add_b_add_cin_result} = A + B + Cin;
        assign {cout3, a_sub_b_result} = A - B;
        assign {cout4, a_sub_b_sub_cin_result} = A - B - Cin;
        assign {cout5, b_sub_a_result} = B - A;
        assign {cout6, b_sub_a_sub_cin_result} = B - A - Cin;
        assign value_a_result = A;
        assign value_b_result = B;
        assign not_a_result = ~A;
        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_flag_result = 0;
        
        // 运算结果 依据操作码Card选择
        assign  F   =   ({32{Card == `A_ADD_B}}  & a_add_b_result)  |
                        ({32{Card == `A_ADD_B_ADD_CIN}}  & a_add_b_add_cin_result)  |
                        ({32{Card == `A_SUB_B}}  & a_sub_b_result)  |
                        ({32{Card == `A_SUB_B_SUB_CIN}} & a_sub_b_sub_cin_result) |
                        ({32{Card == `B_SUB_A}} & b_sub_a_result) |
                        ({32{Card == `B_SUB_A_SUB_CIN}} & b_sub_a_sub_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_FLAG}} & zero_flag_result) | 
                        0;
        // 进位标志
        assign  Cout =  ({Card == `A_ADD_B}  & cout1)  |
                        ({Card == `A_ADD_B_ADD_CIN}  & cout2)  |
                        ({Card == `A_SUB_B}  & cout3)  |
                        ({Card == `A_SUB_B_SUB_CIN} & cout4) |
                        ({Card == `B_SUB_A} & cout5) |
                        ({Card == `B_SUB_A_SUB_CIN} & cout6) |
                        0; 
        // 0标志,F为0时为1
        assign  Zero =  (F == 0) | 0;
    
    endmodule

    仿真代码

    `timescale 1ns / 1ps
    module sim();
        reg [31:0] A;
        reg [31:0] B;
        reg Cin;
        reg [4:0] Card;
        wire Cout;
        wire [31:0] F;
        wire Zero;
        
        initial begin
            Card = 5'b00000;
            A = 32'h0000_0000;
            B = 32'h0000_0000;
            Cin = 1'b0;
            
            #10 // F = A 加 B
            Card = 5'b00001;
            A = 32'hffff_ffff;
            B = 32'h0000_0001;
            Cin = 1'b1;
            
            #10 // F = A 加 B 加 Cin
            Card = 5'b00010;
            A = 32'hffff_ffff;
            B = 32'h0000_0001;
            Cin = 1'b1;
            
            #10 // F = A 减 B
            Card = 5'b00011;
            A = 32'h0000_0001;
            B = 32'h0000_0002;
            Cin = 1'b1;
            
            #10 // F = A 减 B 减 Cin
            Card = 5'b00100;
            A = 32'h0000_0001;
            B = 32'h0000_0002;
            Cin = 1'b1;
            
            #10 // F = B 减 A
            Card = 5'b00101;
            A = 32'h0000_0002;
            B = 32'h0000_0001;
            Cin = 1'b1;
            
            #10 // F = B 减 A 减 Cin
            Card = 5'b00110;
            A = 32'h0000_0002;
            B = 32'h0000_0001;
            Cin = 1'b1;
            
            #10 // F = A
            Card = 5'b00111;
            A = 32'h0000_0002;
            B = 32'h0000_0001;
            
            #10 // F = B
            Card = 5'b01000;
            A = 32'h0000_0002;
            B = 32'h0000_0001;
            
            #10 // F = /A
            Card = 5'b01001;
            A = 32'h0000_0001;
            
            #10 // F = /B
            Card = 5'b01010;
            B = 32'h0000_0002;
            
            #10 // F = A + B
            Card = 5'b01011;
            A = 32'h0000_0001;
            B = 32'hffff_fff0;
            
            #10 // F = AB
            Card = 5'b01100;
            A = 32'h0000_0001;
            B = 32'hffff_ffff;
            
            #10 // F = A XNOR B
            Card = 5'b01101;
            A = 32'h0000_f0f0;
            B = 32'h0f0f_0000;
            
            #10 // F = A XOR B
            Card = 5'b01110;
            A = 32'h0000_f0f0;
            B = 32'h0f0f_0000;
            
            #10 // F = /(AB)
            Card = 5'b01111;
            A = 32'h0808_f0f0;
            B = 32'h0f0f_8888;
            
            #10 // F = 0
            Card = 5'b10000;
            
            #10 Card = 5'b10010;
            #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 u0 (
            .A(A),
            .B(B),
            .Cin(Cin),
            .Card(Card),
            .F(F),
            .Cout(Cout),
            .Zero(Zero)
        );
    endmodule
    

    五、测试结果及实验分析

    测试波形

    运算功能 A(H) B(H) Cin 操作码 (五位) F(H) Zero
    F=A加B FFFF_FFFF 0000_0001 1 00001 0000_0000 1
    F=A加B加Cin FFFF_FFFF 0000_0001 1 00010 0000_0001 0
    F=A减B 0000_0001 0000_0002 1 00011 FFFF_FFFF 0
    F=A减B减Cin 0000_0001 0000_0002 1 00100 FFFF_FFFE 0
    F=B减A 0000_0002 0000_0001 1 00101 FFFF_FFFF 0
    F= B减A减Cin 0000_0002 0000_0001 1 00110 FFFF_FFFE 0
    F=A 0000_0002 0000_0001 1 00111 0000_0002 0
    F=B 0000_0002 0000_0001 1 01000 0000_0001 0
    F=/A 0000_0001 0000_0001 1 01001 FFFF_FFFE 0
    F=/B 0000_0001 0000_0002 1 01010 FFFF_FFFD 0
    F=A+B 0000_0001 FFFF_FFF0 1 01011 FFFF_FFF1 0
    F=AB 0000_0001 FFFF_FFFF 1 01100 0000_0001 0
    F=A⊙B 0000_F0F0 0F0F_0000 1 01101 F0F0_0F0F _ _ 0
    F=A⊕B 0000_F0F0 0F0F_0000 1 01110 0F0F_F0F0 0
    F=/(AB) 0808_F0F0 0F0F_8888 1 01111 F7F7_7F7F 0
    F=0 0808_F0F0 0F0F_8888 1 10000 0000_0000 1

    实验结果分析:

    对比实验结果与正确运算结果,实验结果符合预期。在前6个算术运算操作中,进位信号Cout表现正确。

    比如在第2个“F=A加B加Cin”操作中,选取的例子为“A = ffff_ffffH, B = 0000_0001H, Cin = 1”,结果应为进1位,和为0000_0001H,结果正确。

    逻辑运算中,测试用例较为复杂,如操作15与非运算,“A = 0808_f0f0H, B = 0f0f_8888H, F = f7f7_7f7fH”,结果正确。当运算操作码无效时,结果输出0。

    六、实验总结

    本次实验利用Vivado开发环境和Verilog硬件描述语言实现了一个简单的算术逻辑单元。通过本次实验,我们巩固了所学的数字逻辑知识,锻炼了硬件思维,提高了自身动手能力。


    __EOF__

  • 本文作者: 江水为竭
  • 本文链接: https://www.cnblogs.com/Az1r/p/17672335.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    二维码智慧门牌管理系统:信息安全与运行安全
    dockerfile创建镜像与容器卷
    String formatting
    ==和equals的区别没那么简单,看看不同级别的程序员怎么回答
    谜语,猜一猜
    Flutter开发实战之Google Play 最佳应用程序开发者分享Flutter经验与技巧
    Linux 14:HTTP协议与web服务器
    HCIA-HarmonyOS Application Developer 课程大纲
    【蓝桥杯选拔赛真题31】python演讲比赛打分 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
    【C++杂货铺】C++11特性总结:列表初始化 | 声明 | STL的升级
  • 原文地址:https://www.cnblogs.com/Az1r/p/17672335.html