算术逻辑单元实验

实验目的

  1. 理解ALU电路结构;

  2. 掌握ALU运算电路的HDL描述方法。

  3. 掌握SystemVerilog的package、结构体、枚举等语法知识。

实验内容1:ALU设计与验证

算术逻辑单元(ALU)完成计算机中的算术运算和逻辑运算。本项目在前面加减运算实验的基础上增加移位运算和逻辑运算。

参考设计1:简单ALU

算术逻辑单元(ALU)完成计算机中的算术运算和逻辑运算。实验材料中给出了一个简单ALU的设计,如图 1,虚线框内是前面加减运算实验的参考设计,只是简化了画法,将4位数据用一根较粗的信号线表示,左下方增加了与、或、异或逻辑运算,并通过一个四选一多路器选择运算的功能。理解HDL代码和电路功能,并思考该电路如何实现对X的逻辑非运算。

图4-12
图 1. 参考设计的ALU原理图

设计任务1

用HDL设计ALU,实现表 1列出的运算功能。和参考设计相比,运算功能增加了移位运算;被移位的数据来自X输入,移位位数由输入Y提供,由于X是4位数据,最多移3位,因此只截取Y的最低两位作为移位位数。

表 1. ALU运算功能与控制信号
ALUop 运算 功能描述

0001

F=X+Y

加法(ADD)

0010

F=X-Y

减法(SUB)

0011

F=X∧Y

逻辑与(AND)

0100

F=X∨Y

逻辑或(OR)

0101

F=X⊕Y

逻辑异或(XOR)

0110

F=X>>>Y

算术右移Y[1:0]位

0111

F=X<<Y

逻辑左移Y[1:0]位

1000

F=X>>Y

逻辑右移Y[1:0]位

除了增加了移位运算,和参考设计相比,并不产生SZOC四个标志位,而是直接输出相等、不等、小于、大于等于四种比较结果,类似加减运算电路实验的设计任务;但是在加减电路实验中,并没有强调参与比较的运算数是无符号数还是带符号数,本实验任务要求将运算数当做带符号的补码进行比较。带符号数的表示可参考单元1教学视频:Verilog语法概要。

硬件描述语言具有不同抽象层次的描述能力。如参考设计的代码完全是按照图 1电路结构进行描述,这种风格要求设计者对电路的结构非常清楚,并且有能力设计最简的电路,前面实验大都是这类描述风格。另一种是更高层次的抽象,只关注电路的功能,不关注电路的结构,电路实现交给综合工具。本设计任务可以选择电路结构的描述风格,也可选择更高抽象的行为描述,实验材料中提供了两种方案的虚拟面板。下面对这两种描述风格的设计方案给一些具体的提示。

(1)面向结构的ALU设计方案举例

图 2所示,和图 1参考设计相比,主要不同在虚线框内的加减运算和移位运算部分。加减运算和比较运算的方案与“加减运算电路实验”设计任务的方案相同,移位运算的方案与“流水灯与移位寄存器实验”任务2的桶形移位方案相同,此外增加了ALUop译码,ALUop与运算功能的对应关系应按表 1设计,以便于机器考核。

也可以设计与图 2不同的电路结构,自己绘制原理框图作为虚拟面板的背景。如果需要可以自行添加指示灯和数码管。
image
图 2. 面向结构的ALU设计框图

(2)面向行为的ALU设计方案

行为描述不关心电路的实现结构,只关心所要实现的电路的功能。验证时可以使用图 2的虚拟面板,只用基本的输入输出,忽略电路结构和内部指示灯;也可以使用任务2的虚拟面板。

实验内容2:将ALU封装为模块

在上面的参考设计和实验任务,为了便于在虚拟面板上观察ALU内部信号,代码直接写在VirtualBoard模块;现在将ALU写成独立的模块(功能没有变化),并且字长采用参数定义,以便在后面的CPU设计中重复使用。

封装为模块后,虚拟面板只给出ALU外框,如图 3所示。

image
图 3. ALU的虚拟面板

参考设计2

参考设计代码使用了SystemVerilog的package、结构体、枚举等描述方法,相关语法和用法与C/C++语言类似,请读者自己阅读理解,也是本项目要求掌握的内容。

package defs;
typedef struct packed{
logic sign;
logic zero;
logic overflow;
logic carryOut;
} t_flag;

enum logic [3:0] {
ADD = 4'b0001,
SUB = 4'b0010,
AND = 4'b0011,
OR = 4'b0100,
XOR = 4'b0101
} aluop;

endpackage

这里对结构体定义中的packed修饰符做一些说明,packed表示这是一个压缩的结构体,它会被当做一个向量进行存储。比如t_flag结构体类型将存储为4位向量,结构体的第一个成员sign在向量的最左边,最后一个成员carryOut是向量的最低位,相当于{sign, zero, overflow, carryOut}。正因为如此,才可以在VirtualBoard模块中将结构体变量赋给一个向量。

assign L[21:18] = flag;

设计任务2

将自己设计的ALU写成独立的模块,要求使用枚举常量定义运算功能,定义t_cmp结构体表示比较运算的结果。ALU模块的端口定义如下。

module ALU
#(parameter N=4)
(
input wire [N-1:0] iX, iY,
input wire [3:0] iALUop,
output logic [N-1:0]oF,
output defs::t_cmp oCmp
);
电路测试采用图 3所示的虚拟面板,但并不意味着必须采用面向行为的方案。因为测试只是针对电路的功能,与内部结构和实现方案无关。

讨论:你设计的ALU使用了多少逻辑资源

编译完成后,可以通过Flow Summary查看FPGA逻辑资源的占用情况,如图 4

image
图 4. Flow Summary中的FPGA逻辑资源占用报告

也可以打开output文件夹下生成的Lab.fit.summary文件查看,如图 5

image
图 5. fit.summary文件中的FPGA逻辑资源占用报告

因为一种型号的FPGA芯片的逻辑资源是固定的,所以报告的是占用比例。虽然占用的比例对特定的FPGA芯片来说不存在成本问题,但是可用于其他功能的逻辑资源就少了。而且如果是专用集成电路ASIC,逻辑资源的多少直接影响着硅片面积的大小,也就是芯片的材料成本。类似于软件中的内存占用,逻辑资源占用是硬件设计的一个指标,实现同样的功能,资源占用越少越好。

讨论:

实验指导中提到了两种实现方案,如果两种方案你都做了,查看output文件夹下编译产生的 .fit.summary文件,对比两种方案所占用的逻辑资源数量是否不同。如果只做了一种,和采用另一种方案的同学交流对比,讨论如何减少逻辑资源占用。

另外需要说明的是,编译报告中的逻辑资源并不仅仅是ALU的逻辑资源,还包括了实验系统的片上调试器,但是不影响比较两种方案。