一、全加器
经过前面的学习能对整个编程思路有个大概的了解,但是之前介绍的只是一些简单的器件,用一个模块就能表达清楚,当面对复杂的模块时还用这种方法就比较麻烦了,所以就需要层次化设计
1.层次化设计
(1)自底向上Bottom_top
(2)自顶向下Top_Bottom
2.全加器
全加器定义
全加器与半加器不同的地方时输入有3路,比半加器多一路输入信号
3.过程
(1)visio模型绘制
从绘制的模型可以看出,全加器与半加器的区别,全加器时由两个半加器模块组成
(2)编写全加器程序
因为全加器用了两个半加器模块,所以先将半加器的端口模块复制过来两份,将cn0、cn1、sum0定义成线性wire,只作为连线,其部分代码如下所示
half_adder half_adder_inst1
(
.in1 (in1) ,
.in2 (in2) ,
.sum (sum0) ,
.count (count0)
);
half_adder half_adder_inst2
(
.in1 (sum0) ,
.in2 (cin) ,
.sum (sum) ,
.count (count1)
);
(3)测试代码编写
与正常的测试代码编写一样,没有太大区别,需要注意的是,其输入输出与中间变量无关。在测试代码中间只需要设置总的输入与总的输出,不管中间的部分。
注意:模块实例化的时候一定要注意中间不能带空格,否则在仿真的时候会报错。
(4)代码
模块代码
module full_adder
(
input wire in1,
input wire in2,
input wire cin,
output wire count,
output wire sum
);
wire sum0;
wire count0;
wire count1;
half_adder half_adder_inst1
(
.in1 (in1) ,
.in2 (in2) ,
.sum (sum0) ,
.count (count0)
);
half_adder half_adder_inst2
(
.in1 (sum0) ,
.in2 (cin) ,
.sum (sum) ,
.count (count1)
);
assign count = (count0|count1);
endmodule
测试代码
`timescale 1ns/1ns
module tb_full_adder();
reg in1;
reg in2;
reg cin;
wire count;
wire sum;
initial
begin
in1 <= 1’b0;
in2 <= 1’b0;
cin <= 1’b0;
end
initial
begin
$timeformat (-9,0,“us”,6);
m
o
n
i
t
o
r
(
"
@
t
i
m
e
monitor("@time%t:in1=%b,in2=%b,cin=%b,sum=%b,count=%b",
monitor("@timetime,in1,in2,cin,sum,count);
end
always #10 in1 <= ($random) %2;
always #10 in2 <= ($random) %2;
always #10 cin <= ($random) %2;
full_adder full_adder _inst
(
.in1 (in1),
.in2 (in2),
.cin (cin ),
. count (count),
. sum (sum)
);
endmodule
二、避免latch产生
1.latch定义
latch其实就是锁存器,在异步电路中产生,锁存器在未锁存时,输出信号随着输入信号而变化。当锁存信号有效的时候,在数据被锁存,输入信号不起任何作用。
2.异步电路与同步电路
(1)异步电路
异步电路主要是组合逻辑电路,用于产生FIFO或RAM的读写控制信号脉冲,但它同时也用在时序电路中,此时它没有统一的时钟,状态变化的时刻是不稳定的,通常输入信号只在电路处于稳定状态时才发生变化。
(2)同步电路
同步电路:同步电路是由时序电路(寄存器和各种触发器)和组合逻辑电路构成的电路,其所有操作都是在严格的时钟控制下完成的。这些时序电路共享同一个时钟CLK,而所 有的状态变化都是在时钟的上升沿(或下降沿)完成的。
3.latch危害
对毛刺敏感
不能异步复位
复杂的静态时序分析
占用更多的逻辑资源
额外的延时
4.产生lanch的情况
(1)组合逻辑中if-else条件分支语句缺少else语句,下面分别是正常的if-else与缺少else的rtl电路
(2)组合逻辑中case条件分支语句条件未完全列举,且缺少default语句
(3)组合逻辑中输出变量赋值给自己