一、实验目的
- 掌握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硬件描述语言实现了一个简单的算术逻辑单元。通过本次实验,我们巩固了所学的数字逻辑知识,锻炼了硬件思维,提高了自身动手能力。