一、环境配置
1、quartus
(1)软件安装
-
百度网盘下载安装包链接:http://pan.baidu.com/s/1wYcHJkh2POLfLR7oohWzBw
提取码:h123
-
下载完成后,解压安装包点击Setup文件进入安装界面
-
进入安装界面,点击next按钮
-
选择【I accept the agreement】,然后点击Next。
-
选择安装路径,然后点击next等待安装即可。
(2)软件使用 -
创建新工程,选择new->New Quartus Prime Project
-
一直点击next直至如下界面,选择文件路径并且填写文件名称,随后点击next:
-
选择芯片型号 Cyclone Iv E,下方选择EP4CE115F29C7。点击next进入下一界面。
-
Simulation选择事先安装好的ModelSim-Alter然后点击next,点击finish即创建完成项目
2、modelsim
-
下载安装文件之后,点击exe文件进入安装,在安装界面点击next进入下一步。
-
选择Modelsim - Intel FPGA Starter Edition,随后点击next进入下一步。
-
选择同意协议之后,点击next按钮进入下一步。
-
选择想要安装的路径地址,随后点击next进行安装。
二、四位全加器的设计
(1)绘制电路图设计四位全加器
在绘制四位全加器之前先绘制半加器电路以及全加器电路并存储为可调用元件。具体参考博客:
半加器和一位全加器绘制并存储为可调用元件
使用事先绘制好的一位全加器按照四位全加器的原理进行绘制,电路图如下所示:
(2)Verilog代码设计四位全加器
除了可以通过绘制电路图来设计四位全加器,我们也可以采用verilog代码的形式让系统帮我们生成四位全加器的电路图,接下来我将分析我的Verilog代码以及它的含义:
verilog代码:
bash
module full_adder_4(
input [3:0] A, // 第一个四位二进制数
input [3:0] B, // 第二个四位二进制数
input Cin, // 初始进位输入
output [3:0] Sum, // 四位和输出
output Cout // 最终进位输出
);
wire C0, C1, C2; // 中间进位信号
// 实例化第一个全加器
full_adder FA0(
.A(A[0]),
.B(B[0]),
.Cin(Cin),
.Sum(Sum[0]),
.Cout(C0)
);
// 实例化第二个全加器
full_adder FA1(
.A(A[1]),
.B(B[1]),
.Cin(C0),
.Sum(Sum[1]),
.Cout(C1)
);
// 实例化第三个全加器
full_adder FA2(
.A(A[2]),
.B(B[2]),
.Cin(C1),
.Sum(Sum[2]),
.Cout(C2)
);
// 实例化第四个全加器
full_adder FA3(
.A(A[3]),
.B(B[3]),
.Cin(C2),
.Sum(Sum[3]),
.Cout(Cout)
);
endmodule
// 一位全加器模块
module full_adder(
input A, // 输入 A
input B, // 输入 B
input Cin, // 进位输入
output Sum, // 和输出
output Cout // 进位输出
);
assign Sum = A ^ B ^ Cin; // 计算和
assign Cout = (A & B) | (A & Cin) | (B & Cin); // 计算进位
endmodule
代码解释:
①模块定义
bash
module full_adder_4(
input [3:0] A, // 第一个四位二进制数
input [3:0] B, // 第二个四位二进制数
input Cin, // 初始进位输入
output [3:0] Sum, // 四位和输出
output Cout // 最终进位输出
);
module full_adder_4:
定义了一个名为full_adder_4的模块。input [3:0] A:
定义了一个4位输入信号A,表示第一个4位二进制数。input [3:0] B:
定义了一个4位输入信号B,表示第二个4位二进制数。input Cin:
定义了一个输入信号Cin,表示初始进位输入。output [3:0] Sum:
定义了一个4位输出信号Sum,表示4位加法的结果。output Cout:
定义了一个输出信号Cout,表示最终的进位输出。
②进位信号
bash
wire C0, C1, C2; // 中间进位信号
- 定义了3个中间进位信号C0、C1和C2,用于连接4个一位全加器之间的进位。
③第一个全加器的设计
bash
full_adder FA0(
.A(A[0]),
.B(B[0]),
.Cin(Cin),
.Sum(Sum[0]),
.Cout(C0)
);
- 命名第一个全加器(full_adder)为FA0。
A(A[0]):
将A的最低位(A[0])连接到FA0的A输入。 B(B[0]):
将B的最低位(B[0])连接到FA0的B输入。Cin(Cin):
将初始进位输入Cin连接到FA0的Cin输入。Sum(Sum[0]):
将FA0的Sum输出连接到Sum的最低位(Sum[0])。Cout(C0):
将FA0的Cout输出连接到中间进位信号C0。
后面的第二个第三个第四个全加器的设计以此类推
④定义一位全加器模块
bash
module full_adder(
input A, // 输入 A
input B, // 输入 B
input Cin, // 进位输入
output Sum, // 和输出
output Cout // 进位输出
);
- 定义了一个名为full_adder的一位全加器模块。
input A
:定义了一个输入信号A。input B
:定义了一个输入信号B。input Cin
:定义了一个输入信号Cin,表示进位输入。output Sum
:定义了一个输出信号Sum,表示加法的结果。output Cout
:定义了一个输出信号Cout,表示进位输出。
⑤一位全加器的逻辑实现
bash
assign Sum = A ^ B ^ Cin; // 计算和
assign Cout = (A & B) | (A & Cin) | (B & Cin); // 计算进位
assign Sum = A ^ B ^ Cin;
:使用异或运算计算和。异或运算的特性是:当且仅当输入中有奇数个1时,输出为1。assign Cout = (A & B) | (A & Cin) | (B &Cin);
:使用与运算和或运算计算进位。当任意两个输入为1时,会产生进位。
最后保存并编译,此时编译无误可以通过tool->Netlist Viewers->RTL Viewer,查看电路图:
三、 DE2-115开发板实验
1、四位全加器实验
(1)四位全加器的设计如第二部分内容所示
(2)四位全加器modelsim仿真波形图
波形仿真的步骤:
- 创建一个向量波形文件,选择菜单项 File→New->University Program VWF
- 点击左侧空白区域弹出如下界面,并且点击红框圈出的按钮:
- 随后点击list载入输入输出等元素:
因此得到仿真的四位全加器波形如图所示:
(3)引脚定义:
引脚配置步骤:
- 点击引脚配置按钮
- 进入引脚配置界面,在下方的表中输入对应引脚即可
引脚表:
Node Name | Location |
---|---|
A[3] | PIN_AB28 |
A[2] | PIN_AC28 |
A[1] | PIN_AC27 |
A[0] | PIN_AD27 |
B[3] | PIN_AB27 |
B[2] | PIN_AC26 |
B[1] | PIN_AD26 |
B[0] | PIN_AB26 |
Cin | PIN_AB25 |
Cout | PIN_F18 |
Sum[3] | PIN_G19 |
Sum[2] | PIN_F19 |
Sum[1] | PIN_E19 |
Sum[0] | PIN_F21 |
按照上述表格赋予对应的引脚,结果如下所示:
- 最后点击开始按键即可,Processing->Start l/O Assignment Analysis
上板效果:
四位全加器
2、38译码器实验
(1)38译码器的设计
通过verilog代码进行设计38译码器:
bash
module three_eight_decoder(a, b, c, out);
input a; // 输入端口a
input b; // 输入端口b
input c; // 输入端口c
output [7:0] out; // 输出端口out,8位宽
reg [7:0] out; // 声明out为寄存器类型
// 或者可以直接写成:output reg [7:0] out;
// always块:当a、b或c发生变化时触发
always @(a, b, c) begin
// case语句:根据{a, b, c}的组合值选择输出
case ({a, b, c})
3'b000: out = 8'b0000_0001; // 当{a, b, c}为000时,out输出0000_0001
3'b001: out = 8'b0000_0010; // 当{a, b, c}为001时,out输出0000_0010
3'b010: out = 8'b0000_0100; // 当{a, b, c}为010时,out输出0000_0100
3'b011: out = 8'b0000_1000; // 当{a, b, c}为011时,out输出0000_1000
3'b100: out = 8'b0001_0000; // 当{a, b, c}为100时,out输出0001_0000
3'b101: out = 8'b0010_0000; // 当{a, b, c}为101时,out输出0010_0000
3'b110: out = 8'b0100_0000; // 当{a, b, c}为110时,out输出0100_0000
3'b111: out = 8'b1000_0000; // 当{a, b, c}为111时,out输出1000_0000
endcase
end
endmodule
代码解释:
①:模块声明:
bash
module three_eight_decoder(a, b, c, out);
- 定义了一个名为 three_eight_decoder 的模块,它是一个三到八译码器(3-to-8 decoder)。
- 模块有四个端口:a、b、c 和 out。
②输入端口声明
bash
input a; // 输入端口a
input b; // 输入端口b
input c; // 输入端口c
- 声明了三个输入端口 a、b 和 c 这三个输入端口将用于控制译码器的输出
③输出端口声明
bash
output [7:0] out; // 输出端口out,8位宽
reg [7:0] out; // 声明out为寄存器类型
- 声明了一个8位宽的输出端口 out。
- 使用 reg 类型声明 out,表示它是一个可赋值的寄存器变量。在 Verilog 中,reg类型通常用于 always 块中赋值的变量。
④情况分类:
bash
case ({a, b, c})
3'b000: out = 8'b0000_0001; // 当{a, b, c}为000时,out输出0000_0001
3'b001: out = 8'b0000_0010; // 当{a, b, c}为001时,out输出0000_0010
3'b010: out = 8'b0000_0100; // 当{a, b, c}为010时,out输出0000_0100
3'b011: out = 8'b0000_1000; // 当{a, b, c}为011时,out输出0000_1000
3'b100: out = 8'b0001_0000; // 当{a, b, c}为100时,out输出0001_0000
3'b101: out = 8'b0010_0000; // 当{a, b, c}为101时,out输出0010_0000
3'b110: out = 8'b0100_0000; // 当{a, b, c}为110时,out输出0100_0000
3'b111: out = 8'b1000_0000; // 当{a, b, c}为111时,out输出1000_0000
endcase
- 使用 case 语句根据输入信号 {a, b, c} 的组合值选择对应的输出。
- {a, b, c} 是一个3位的组合信号,表示输入端口a、b 和 c 的值拼接在一起。
- 每个 case 分支对应一个输入组合,根据输入值将 out 赋值为对应的8位二进制数。
- 例如:
当{a, b, c} = 3'b000 时,out 被赋值为 8'b0000_0001。
当 {a, b, c} = 3'b001时,out 被赋值为 8'b0000_0010。
以此类推。 - 这种译码器的功能是将3位输入信号转换为8位输出信号,其中只有一个输出位为1,其余位为0。
(2)38译码器modelsim仿真波形图
仿真结果如下:
(3)用三八译码器点亮七段数码管
①数码管简单介绍:
以共阴极七段数码管为例,假设我们需要b,c亮,我们只需要给b,c接低电平,其他接高电平就可。
②代码实现:
bash
// 数码管段选信号定义(共阳极)
// seg[6:0] 分别对应数码管的 g, f, e, d, c, b, a
// 共阳极数码管:0 点亮,1 熄灭
always @(sw) begin
case (sw)
3'b000: seg = 8'b1100_0000; // 显示数字 0
3'b001: seg = 8'b1111_1001; // 显示数字 1
3'b010: seg = 8'b1010_0100; // 显示数字 2
3'b011: seg = 8'b1011_0000; // 显示数字 3
3'b100: seg = 8'b1001_1001; // 显示数字 4
3'b101: seg = 8'b1001_0010; // 显示数字 5
3'b110: seg = 8'b1000_0010; // 显示数字 6
default: seg = 8'b1111_1111; // 默认全灭
endcase
end
endmodule
③引脚配置:
④测试结果:
我们FPGA板子的数码管有问题,所以没办法展示。