文章目录
一、 任务
一. 在线Verilog编程网站学习:
https://hdlbits.01xz.net/wiki/Main_Page HDLBits — Verilog Practice 在线练习网站
(参考HDLBits 中文导学 https://zhuanlan.zhihu.com/c_1131528588117385216)
从门电路、组合电路、时序电路中各选3个以上的例题进行实践练习,并记录结果(包括初学时发生的错误)。
二.
1)首先安装Logisim软件,新建一个项目,采用门电路组合电路方式完成一个1位全加器的设计,并在Logisim中进行测试。然后封装这个1位全加器为自定义的一个子电路模块(比如名称为OneAdder),然后新建一个项目,用1位全加器串行级联方式完成一个4位全加器的设计,并进行功能测试。
2)首先基于Quartus 软件完成一个1位全加器的设计。分别采用原理图输入以及 Verilog编程 这两种设计方法。然后通过4个1位全加器的串行级联,完成一个4位全加器的 原理图设计;再改用 Verilog编程(3种模式:门电路、数据流和行为级描述),完成这个4位全加器设计,并观察Verilog代码编译综合后生成的 RTL电路,与之前电路图设计的4位全加器电路进行对比 。
二、 过程
2.1 在线Verilog编程网站学习
2.1.1 门电路练习
以下面三个题为例:
- AND门
这一题了解assign和逻辑与&&的使用
module top_module(
input a,
input b,
output out );
assign out=a&&b;
endmodule
assign 赋值语句:
使用assign语句时需要遵守一些规则:
左值应该始终是标量或向量wire线网类型数据,或者标量或向量线网的级联,而不是标量或向量寄存器。
右值可以包含标量或矢量寄存器和函数调用。
每当右值上的任何操作数的值发生变化时,左值都将更新为新值。
assign语句也称为连续赋值,并且始终处于活动状态。
结果
- NOR门
本题需要掌握逻辑或 || 和取反符号 ~
module top_module(
input a,
input b,
output out );
assign out =~( a||b);
endmodule
结果
3.XNOR门
学习按位取反
异或 ^
module top_module(
input a,
input b,
output out );
assign out = ~(a^b);
endmodule
结果
2.1.2 组合电路练习
- another gate
module top_module (
input in1,
input in2,
output out
);
assign out = in1 && (~in2);
endmodule
结果
2. two gates
module top_module (
input in1,
input in2,
input in3,
output out);
wire wire1;
assign wire1=~(in1^in2);
assign out=wire1^in3;
endmodule
结果
3.
module top_module(
input a, b,
output out_and,
output out_or,
output out_xor,
output out_nand,
output out_nor,
output out_xnor,
output out_anotb
);
assign out_and = a & b;
assign out_or = a | b;
assign out_xor = a ^ b;
assign out_nand = ~(a & b);
assign out_nor = ~(a | b);
assign out_xnor = ~(a ^ b);
assign out_anotb = a & ~b;
endmodule
结果
2.1.3 时序电路
- D 触发器
译文:
D触发器是一种在时钟信号的(通常)正边沿存储位并定期更新的电路。
D 触发器由逻辑合成器在使用时钟 always 模块时创建(请参阅始终阻止
D 触发器是“组合逻辑的斑点,然后是触发器”的最简单形式,其中组合逻辑部分只是一根电线。
创建一个 D 触发器。
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q
);
always @(posedge clk) begin
q <= d; // 在正边沿时,将输入 d 的值传递给输出 q
end
endmodule
2.2 Logisim 的全加器实现
2.2.1 1位全加器
- 打开logsim
- 点开逻辑门,可以从中找到各种门
我们需要:
异或门 × 2
与门 × 2
或门 × 1
3. 从方框所示位置
添加三个输入,两个输出
并如图连接
4. 可以点击输入测试一下效果
2.2.2 4位全加器
- 封装
点击如图修改外观
变成如图所示:
可以拖住右下角调整大小,然后将管脚移到器件上
然后点击方框
选择边框和填充
可以点击修改颜色:
点击下图图标然后点击屏幕可以加批注
差不多了,可以不管这个了
2. 新建4位全加器电路图
对着项目右键添加电路
3. 绘制电路
首先放置好四个1位全加器
单击main,然后鼠标放到幕布上就能看到之前封装的全加器了
此时单击幕布即可完成放置,放置四个:
然后建立输入输出,并按如图连接线路:
输入数据和全加器都是上位高位下为低位,把两组4位输入分别从高到低连接a口/b口
此时标红是正常的,全部连接完成后就没事了
然后连接进位管脚
4. 测试
我们运算一下0001+0001,也就是每个四位输入都点亮最下面的输入
可以看到0001+0001的运算结果是0010,正确
然后再算一下0101+0111
结果是1100,正确
2.3 Quartus 的全加器的实现
2.3.1 原理图方式
一位全加器
新建项目
然后一直next直到:
点击finish
添加原理图:
打开器件库
然后如图布置:
添加输入和输出
然后按如图连线:
保存电路
编译一下:
这需要等待一段时间
看到左侧进度条拉完后查看原理图
管教名字可以在绘制界面改
创建波形文件
然后一直点ok
鼠标拖出一个范围可选中某段波形
选中后双击,可以修改值
点击开始仿真
结果正确
解决报错:
然后配置好modelsim的位置就行.
四位全加器
先将1位全加器封装
然后在元器件里就可以找到了
然后新建一个add_4的项目
新建原理图
添加四个1位全加器
然后创建两组,每组四个的输入,创建一组四个的输出
最下面两个可以不加
然后按照图示连接线路
可以更改下管脚名,方便后面调试
编译一下
查看一下电路图
有点难看,不过无碍
新建一个波形文件,按照之前步骤调试下
验证一下·1110+1010
也就是a1-1,a2-1,a3-1,a4-0
b1-1,b2-0,b3-1,b4-0
然后点击仿真
结果为
1000,且cout进位为1,正确
2.3.2 verilog方式(4位全加器)
- 行为级
module add_4_v (
input [3:0] A,
input [3:0] B,
input Cin,
output [3:0] Sum,
output Cout
);
reg [3:0] Sum_int;
reg Cout_int;
always @(A or B or Cin)
begin
Sum_int = A + B + Cin;
Cout_int = (A[3] & B[3]) | (B[3] & Cin) | (Cin & A[3]);
end
assign Sum = Sum_int;
assign Cout = Cout_int;
endmodule
编译,查看电路图
然后开启仿真
测试下1100+1011
结果:
2. 门电路
module four_bit_adder_gate (
input [3:0] A,
input [3:0] B,
input Cin,
output [3:0] Sum,
output Cout
);
// Internal signals
wire [3:0] X1, X2, X3, X4, X5;
wire Cout_int;
// XOR gates for Sum bits
assign X1 = A ^ B;
assign X2 = X1 ^ Cin;
assign Sum = X2;
// AND gates for carry generation
assign X3 = A & B;
assign X4 = B & Cin;
assign X5 = Cin & A;
// OR gate for Cout generation
assign Cout_int = X3 | X4 | X5;
assign Cout = Cout_int;
endmodule
- 数据流
module four_bit_adder_dataflow (
input [3:0] A,
input [3:0] B,
input Cin,
output [3:0] Sum,
output Cout
);
// Dataflow-style description using assignments
assign Sum = A + B + Cin;
assign Cout = (A[3] & B[3]) | (B[3] & Cin) | (Cin & A[3]);
endmodule
4. 对比
左侧是行为级、数据流、门级,右侧是通过原理图得到
三、 学习心得
学习Verilog编程和数字电路设计是一项富有挑战性但又极富乐趣的任务。通过HDLBits在线练习网站,我深入了解了Verilog的门电路、组合电路和时序电路的实践应用。选择了各类题目,包括门电路、组合电路和时序电路,通过实践练习逐步掌握了Verilog的语法和基本原理。在初学阶段,经常遇到语法错误和逻辑设计问题,但通过不断调试和查找资料,逐渐解决了这些困难。
在Logisim软件的学习过程中,我首先完成了一个1位全加器的设计,并在Logisim中进行了详细的测试。随后,将1位全加器封装为一个自定义的子电路模块,命名为OneAdder。通过串行级联4个OneAdder,完成了一个4位全加器的设计,并进行了功能测试。这一过程锻炼了我对数字电路层次化设计的理解,同时提高了我的逻辑调试能力。
使用Quartus软件进行数字电路设计进一步加深了我的Verilog编程能力。通过原理图输入和Verilog编程两种方式,我完成了1位全加器的设计,并通过串行级联得到4位全加器的原理图设计。随后,使用三种不同的Verilog描述方式(门电路、数据流、行为级描述)完成了同样的4位全加器设计,并通过观察RTL电路图进行了对比。这一过程不仅提高了我的Verilog编程水平,还让我理解了数字电路的综合和优化过程。
总的来说,通过以上学习任务,我深入了解了Verilog编程语言以及数字电路设计的原理和方法。实践练习和对比分析让我更加熟练地运用这些知识,为将来更复杂的数字电路设计打下了坚实的基础。