
写在前面
这个实验纯粹是为了让同学更好地理解ALU的原理,配合理论课的进度,没有对硬件设计技巧或者代码能力提出更高的要求,有了前面几个实验的基础,直接原理图绘制就可以,功能代码也相对比较简单。

1. 实验目的和要求
掌握减法器的实现原理
掌握加减法器的设计方法
掌握ALU基本原理及在CPU中的作用
掌握ALU的设计方法
2. 实验内容和原理
2.1 实验内容
任务1:原理图方式设计4位加减法器
任务2:实现4位ALU及应用设计
2.2 实验原理
2.2.1 多位串行进位加法器
由一位全加器将进位串接构成
低位进位C0为0,Ci为高位进位输出

多位串行进位加法器示意图
2.2.2 多位串行进位全减器
用负数补码加法实现,减数当作负数求补码
共用加法器
用“异或”门控制求反,低位进位C0为1

多位串行进位全减器原理图
2.2.3 一位加减法器
原理图如下所示:

一位加减法器原理图
生成元件如下图所示:

一位加减法器元件示意图
2.2.4 四位串行加减法器
原理图如下所示:

四位串行加减法器原理图
生成原件如下图所示:

四位串行加减法器元件示意图
2.2.5 设计按键数据输入模块
使用行为描述设计,在实验8基础上,更新 Adder4b 为 AddSub4b 模块;代码如下:
module CreateNumber(
input wire [1:0] btn,
input wire [1:0] sw,
output reg [7:0] num
);
wire [3:0] A1,B1;
initial num <= 8'b 1010_1011;
myAddSub4b a1(.A(num[3:0]), .B(4'b0001), .Ctrl(sw[0]), .S(A1));
myAddSub4b b1(.A(num[7:4]), .B(4'b0001), .Ctrl(sw[1]), .S(B1));
always@(posedge btn[0]) num[ 3: 0] <= A1;
always@(posedge btn[1]) num[ 7: 4] <= B1;
endmodule 2.2.6 4位ALU
原理图如下图所示:

四位ALU原理图
3. 主要仪器设备
实验设备:装有Xilinx ISE 14.7的计算机 1台,SWORD开发板 1套
实验材料:无
4. 操作方法和实验步骤
4.1 原理图方式设计4位加减法器
4.1.1 1位加减法器设计
1. 新建工程,命名为MyALU_3190103044,Top Level Source Type 为 HDL
2. 新建类型为 schematic 的源文件,命名为 myAddSub1b
3. 用原理图方式设计,具体如下所示:

1位加减法器原理图
4. 生成逻辑符号和.vf文件:点击 Process 窗口下 Design Utilities -> Create schematic symbol,在工程文件夹里可以找到相应的.sym文件
4.1.2 4位加减法器设计
1. 新建类型为 schematic 的源文件,命名为 myAddSub4b
2. 调用 myAddSub1b元件,用原理图方式设计,具体如下所示:

4位加减法器原理图
3. 生成逻辑符号和.vf文件:点击 Process 窗口下 Design Utilities -> Create schematic symbol,在工程文件夹里可以找到相应的.sym文件
4. 进行波形仿真,激励输入至少4组,具体代码如下:
`timescale 1ns / 1ps
module myAddSub4b_myAddSub4b_sch_tb();
// Inputs
reg Ctrl;
reg [3:0] A;
reg [3:0] B;
// Output
wire Co;
wire [3:0] S;
// Bidirs
// Instantiate the UUT
myAddSub4b UUT (
.Co(Co),
.S(S),
.Ctrl(Ctrl),
.A(A),
.B(B)
);
// Initialize Inputs
initial begin
Ctrl = 0;
A = 0;
B = 0;
#100
Ctrl = 0;
A = 4'b0101;
B = 4'b1010;
#100
Ctrl = 0;
A = 4'b1000;
B = 4'b0001;
#100
Ctrl = 1;
A = 4'b1000;
B = 4'b0001;
#100
Ctrl = 1;
A = 4'b1100;
B = 4'b0001;
end
endmodule
4.2 4位与元件设计
1. 新建类型为 schematic 的源文件,命名为 myAnd4b
2. 用原理图方式实现 4 位与的逻辑功能,具体如下:

4位与元件原理图
3. Check Syntax 无误后,点击 Process 窗口下 Design Utilities -> Create schematic symbol生成逻辑符号和.vf文件
4.3 4位或元件设计
1. 新建类型为 schematic 的源文件,命名为 myOr4b
2. 用原理图方式实现 4 位或的逻辑功能,具体如下:

4位或元件原理图
3. Check Syntax 无误后,点击 Process 窗口下 Design Utilities -> Create schematic symbol生成逻辑符号和.vf文件
4.4 实现4位ALU及应用设计
4.4.1 ALU元件设计
1. 新建类型为 schematic 的源文件,命名为 myALU
2. 调用 myAddSub4b、myAnd4b、myOr4b,用原理图方式实现 ALU 的逻辑功能,具体如下:

ALU元件原理图
3. Check Syntax 无误后,点击 Process 窗口下 Design Utilities -> Create schematic symbol生成逻辑符号和.vf文件
4. 进行波形仿真,激励输入至少4组,具体代码如下:
`timescale 1ns / 1ps
module myALU_myALU_sch_tb();
// Inputs
reg [3:0] A;
reg [3:0] B;
reg [1:0] S;
// Output
wire [3:0] C;
wire Co;
// Bidirs
// Instantiate the UUT
myALU UUT (
.C(C),
.Co(Co),
.A(A),
.B(B),
.S(S)
);
// Initialize Inputs
initial begin
A = 0;
B = 0;
S = 0;
#100
S = 2'b00;
A = 4'b1100;
B = 4'b0011;
#100
S = 2'b01;
A = 4'b1100;
B = 4'b0011;
#100
S = 2'b10;
A = 4'b1100;
B = 4'b0011;
#100
S = 2'b11;
A = 4'b1100;
B = 4'b0011;
end
endmodule
4.4.2 Disp_num模块设计
1. 新建类型为 schematic 的文件,命名为 Disp_num
2. 使用原理图方式设计,具体如下:

Disp_num模块原理图
3. 生成逻辑符号和.vf文件:点击 Process 窗口下 Design Utilities -> Create schematic symbol,在工程文件夹里可以找到相应的.sym文件
4.4.3 ALU应用设计
1. 新建类型为 verilog 的文件,命名为 Top,右键“Set as Top Module”设置为顶层文件
2. 调用 pbdebounce 模块、Adder4b 模块、clkdiv 模块、Disp_num 模块、CreateNumber 模块,其中 CreateNumber 需做修改
3. 输入 verilog 代码设计 ALU 元器件的应用功能,具体代码如下:
module Top(
input wire clk,
input wire [1:0]btn,
input wire [1:0]SW,
input wire [1:0]SW2,
input wire BN,
output wire [3:0]AN,
output wire [7:0]SEGMENT,
output wire K_ROW
);
wire [7:0] num;
wire [1:0] btn_out;
wire [3:0] C;
wire Co;
wire [31:0] clk_div;
clkdiv m2(.clk(clk),.rst(1'b0),.clkdiv(clk_div));
pbdebounce m0(clk_div[17],btn[0],btn_out[0]);
pbdebounce m1(clk_div[17],btn[1],btn_out[1]);
CreateNumber m3(.btn(btn_out[1:0]), .sw(SW[1:0]), .num(num));
myALU m4(.A(num[3:0]), .B(num[7:4]), .S(SW2[1:0]), .C(C[3:0]), .Co(Co));
Disp_num m5( clk, {num[7:0], 3'b0, Co, C[3:0]}, 0, AN, SEGMENT);
BUF m6(BN, K_ROW);
endmodule
4. Check Syntax 无误后,点击 Process 窗口下 Design Utilities -> Create schematic symbol生成逻辑符号和.vf文件
5. 进行引脚约束,下载到 SWORD 板进行验证。新建类型为 Implementation constraints file 的源文件,命名为 k7.ucf,具体代码如下所示:
NET "clk" LOC=AC18 | IOSTANDARD=LVCMOS18;
NET "SW[0]" LOC = AA10 | IOSTANDARD = LVCMOS15;#POINT
NET "SW[1]" LOC = AB10 | IOSTANDARD = LVCMOS15;
NET "SW2[0]" LOC = AA13 | IOSTANDARD = LVCMOS15;
NET "SW2[1]" LOC = AA12 | IOSTANDARD = LVCMOS15;
NET "SEGMENT[0]" LOC = AB22 | IOSTANDARD = LVCMOS33 ;#a
NET "SEGMENT[1]" LOC = AD24 | IOSTANDARD = LVCMOS33 ;#b
NET "SEGMENT[2]" LOC = AD23 | IOSTANDARD = LVCMOS33 ;
NET "SEGMENT[3]" LOC = Y21 | IOSTANDARD = LVCMOS33 ;
NET "SEGMENT[4]" LOC = W20 | IOSTANDARD = LVCMOS33 ;
NET "SEGMENT[5]" LOC = AC24 | IOSTANDARD = LVCMOS33 ;
NET "SEGMENT[6]" LOC = AC23 | IOSTANDARD = LVCMOS33 ;#g
NET "SEGMENT[7]" LOC = AA22 | IOSTANDARD = LVCMOS33 ;#point
NET "AN[3]" LOC = AC22 | IOSTANDARD = LVCMOS33 ;
NET "AN[2]" LOC = AB21 | IOSTANDARD = LVCMOS33 ;
NET "AN[1]" LOC = AC21 | IOSTANDARD = LVCMOS33 ;
NET "AN[0]" LOC = AD21 | IOSTANDARD = LVCMOS33 ;
NET "btn[1]" LOC = V14 |IOSTANDARD = LVCMOS18 ;
NET "btn[0]" LOC = W14 |IOSTANDARD = LVCMOS18 ;
NET "K_ROW" LOC = V17 | IOSTANDARD = LVCMOS18 ;
NET "BN" LOC = AE10 | IOSTANDARD = LVCMOS15 ;
5. 实验结果和分析
5.1 4位加减法器
运行仿真代码后波形图如下图所示,与理论结果一致,故元件逻辑功能正确。

4位加减法器仿真波形图
5.2 4位ALU
5.2.1 仿真测试结果
运行仿真代码后波形图如下图所示,与理论结果一致,故元件逻辑功能正确。

4位ALU仿真波形图
5.2.2 物理验证
各个开关、按钮对应功能以及LED板相应的显示内容如下图所示:

开关、按钮、LED板对应功能示意图
专栏不方便发表格,此处仅展示部分实验结果:
1 加

1+2 = 3

A + 5 = F
2 减

1 - 2 = -1

5 - A = -B
3 与

0001 & 0010 = 0000

1010 & 0101 = 0000
4 或

0001 | 0010 = 0011

1010 | 0101 = 1111

Top 文件 verilog 代码补全:接口位数要仔细核对,尽量使用标准语法,例如 .A(num[3:0]),结构更清晰,更容易看出错误,而不是 {num[3:0]},项数多了以后容易搞错。同时,需要注意,同一元件的接口声明要保持语法一致。
引脚文件修改:在实验八的基础上对应 Top 文件中的输入输出修改引脚文件即可。
模块调用问题:调用模块时只需要将 .sym 和 .v 文件添加到工程目录下,将 .v 文件添加到工程中即可,.sym不需要加入。 下述错误有可能是这个原因导致的,虽然之前将 .sym 也加入文件并没有报错。

ERROR信息
绘制原理图的时候,如果 net 需要命名,可以在命名的时候顺便将其可视化,便于检查命名问题,
欢迎评论区讨论,感谢一键三连。