一、实验目的

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

算术逻辑单元的实现(ALU)的更多相关文章

  1. 【知识强化】第二章 数据的表示和运算 2.4 算术逻辑单元ALU

    从本节开始我们就进入到本章的最后一节内容了,也就是我们算术逻辑单元的它的实现.这部分呢是数字电路的一些知识,所以呢,如果你没有学过数字电路的话,也不要慌张,我会从基础开始给大家补起.那么在计算机当中, ...

  2. 手写一个简易的多周期 MIPS CPU

    一点前言 多周期 CPU 相比单周期 CPU 以及流水线 CPU 实现来说其实写起来要麻烦那么一些,但是相对于流水线 CPU 和单周期 CPU 而言,多周期 CPU 除了能提升主频之外似乎并没有什么卵 ...

  3. 【基础知识】CPU 是如何工作的 |CPU 通过总线读取内存的工作方式

    一.简单cpu  是如何工作 方式讲解 CPU 的根本任务就是执行指令,对计算机来说最终都是一串由 0 和 1 组成的序列.CPU 从逻辑上可以划分成 3 个模块,分别是控制单元.运算单元和存储单元 ...

  4. 【从零开始自制CPU之学习篇07】最简单的ALU—全加器

    ALU是算术逻辑单元,是CPU中重要的一部分,因为CPU本质上就是不断重复最简单的计算.而我们这一版CPU的ALU部分更为简单,是一个只能做加法的ALU. 理论部分 我们需要一个能帮我们进行数学计算的 ...

  5. ALU底层方法及计算机整数加减乘除模拟

    ALU是计算机CPU的核心,即 算术逻辑单元(arithmetic and logic unit)ALU有几大功能,是计算机计算最基础的功能:1.算术运算:包含加法.减法等2.逻辑运算:主要是布尔运算 ...

  6. 《CPU的工作过程》

    本文转载自inter官方网址:https://software.intel.com/zh-cn/articles/book-Processor-Architecture_CPU_work_proces ...

  7. 在配有英特尔® Iris™ 显卡的系统上通过优化对 Just Cause 3 进行增强

    高端 PC 继续通过高性能显卡驱动桌面游戏. 一流的"梦想机器"基于第六代智能 英特尔® 酷睿™ 处理器i7-6700K等 CPU,通常与高端独立显卡配合使用以运行要求最严苛的游戏 ...

  8. 初步了解CPU

    了解CPU By JackKing_defier 首先说明一下,本文内容主要是简单说明CPU的大致原理,所需要的前提知识我会提出,但是由于篇幅我不会再详细讲解需要的其他基础知识.默认学过工科基础课. ...

  9. [CUDA] CUDA to DL

    又是一枚祖国的骚年,阅览做做笔记:http://www.cnblogs.com/neopenx/p/4643705.html 这里只是一些基础知识.帮助理解DL tool的实现. “这也是深度学习带来 ...

  10. Linux系统1.md

    计算机 介绍 电子计算机(英语:computer),亦称电脑,是一种利用电子学原理,根据一系列指令对数据进行处理的工具. 在现代,机械计算机的应用已经完全被电子计算机所替换,其所相关的技术研究叫计算机 ...

随机推荐

  1. 文件系统考古:1974-Unix V7 File System

    有时,进步难以察觉,特别是当你正身处其中时.而对比新旧资料之间的差异,寻找那些推动变革的信息源,我们就可以清晰地看到进步的发生.在Linux(以及大部分Unix系统)中,都可以印证这一点. Unix ...

  2. 创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作

    本文为博主原创,转载请注明出处: 1.使用npm进行初始化 在本地创建项目的文件夹名称,如 node_test,并在该文件夹下进行黑窗口执行初始化命令 2. 安装 expres包和myslq依赖包 n ...

  3. tryhackem_wonderland

    涉及,解密,扫描,横向移动,纵向移动 仙境 掉进兔子洞,进入仙境. 获得shell 解法一: 目录扫描 ffuf -u http://10.10.134.189/FUZZ -w /usr/share/ ...

  4. Basic Pentesting

    来自tryhackme的 Basic Pentesting 开靶场IP:10.10.227.255 # nmap 端口扫描 PORT STATE SERVICE VERSION 22/tcp open ...

  5. 前端学习C语言 - 函数和关键字

    函数和关键字 本篇主要介绍:自定义函数.宏函数.字符串处理函数和关键字. 自定义函数 基本用法 实现一个 add() 函数.请看示例: #include <stdio.h> // 自定义函 ...

  6. 如何在Databricks中使用Spark进行数据处理与分析

    目录 <如何在Databricks中使用Spark进行数据处理与分析> 随着大数据时代的到来,数据处理与分析变得越来越重要.在数据处理与分析过程中,数据的存储.处理.分析和展示是不可或缺的 ...

  7. GO 语言中 slice 的理解

    GO 语言中 slice 理解 为什么说 Go 语言的 slice 是引用类型,其底层实现明明是一个结构体? slice 的底层实现是一个包含三个字段的结构体:指向底层数组的指针.slice 的长度和 ...

  8. 图书商城项目练习②后端服务Node/Express/Sqlite

    本系列文章是为学习Vue的项目练习笔记,尽量详细记录一下一个完整项目的开发过程.面向初学者,本人也是初学者,搬砖技术还不成熟.项目在技术上前端为主,包含一些后端代码,从基础的数据库(Sqlite).到 ...

  9. 精讲Mybatis··#{}和${}

    题目 笔记Notes 面试题目:#{}和${}的区别是什么? 网上的答案是:#{}是预编译处理,${}是字符串替换.mybatis在处理#{}时, 会将sql中的#{}替换为?号,调用Prepared ...

  10. 浅析synchronized锁升级的原理与实现

    背景 在多线程编程中,线程同步是一个关键的概念,它确保了多个线程对共享资源的安全访问.Java中的synchronized关键字是一种常用的线程同步机制,它不仅提供了互斥访问的功能,还具备锁升级的特性 ...