锁存器 触发器 寄存器的关系 modelsim仿真打拍失效怎么解决?

一、锁存器(D锁存器)

1、锁存器的结构

在这里插入图片描述
可以看出由四个与非门组成,第一个部分是由 G1、 G2 两个与非门组成的 RS 锁存器,第二个部分是由 G3、 G4 两个与非门组成的控制电路
D(data)为数据输入,C(control)为控制信号,Qn 是指当前逻辑状态也即触发前的状态, Qn+1 是指触发后的状态。
由1,0高低电平触发
在这里插入图片描述
在这里插入图片描述

2、锁存器是什么

锁存器(Latch)是一种对脉冲和电平敏感的存储单元电路,它们可以在特定输入脉冲或电平作用下改变
状态。锁存,就是把信号暂存以维持某种电平状态。锁存器在不锁存数据时,输出端的信号随输入信号变化, 一旦锁存信号起锁存作用,则数据被锁住, 输出信号不随输入信号的变化而变化。因此锁存器也称为透明锁存器,指的是不锁存时输出对输入是透明的。

3、什么情况下会产生锁存器

锁存器的分类包括 RS 锁存器、门控 RS 锁存器和 D 锁存器, 一般我们经常使用的是 D 锁存器, 此处我们详细介绍下 D 锁存器。

代码里面出现 latch 的两个原因是在组合逻辑中, if 或者 case 语句不完整的描述, 比如 if 缺少 else 分
支, case 缺少 default 分支,导致代码在综合过程中出现了 latch。解决办法就是 if 必须带 else 分支, case 必
须带 default 分支。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意!只有不带时钟的 always 语句 if 或者 case 语句不完整才会产生 latch, 带时钟的语句if 或者 case 语句不完整描述不会产生 latch。

4、锁存器需要注意的点

  • 代码结构要尽量减少锁存器latch的产生,锁存器对毛刺敏感,enable毛刺的变化会反映到输出端上
  • 由之前结构分析我们可以看到,锁存器没有时钟信号,只有数据输入和使能以及输出 q 端,没有时钟信号也就说明我们没有办法对这种器件进行时序分析,这个在时序电路里面是非常危险的行为,因为可能引起时序不满足从而导致电路功能实现有问题。
  • 锁存器数据采样条件为电位信号控制(电平)

二、触发器

1、触发器的结构

在这里插入图片描述

F1,F2分别是两个锁存器,下方是两个非门
假设CLK是一个上升沿,并且D为1
前半个周期CLK为0:F1中经过非门C1输入为1,1D输入为1,Q0输出1,F2中经过两个非门C1为0,Q1输出不受1D影响,保持。
后半个周期CLK为1:F1中经过非门C1输入为0,Q0保持输出1,F2中经过两个非门C1为1,1D等于Q0为1,Q输出1。
总结:

  • 在 CLK 信号由 0 变为 1 这样的一个变化周期内,触发器的输出状态只可能改变一次。
  • 触发器是同步时钟上升沿控制

三、寄存器

1、寄存器的结构

一个触发器可以组成一个一位的寄存器(一个触发器其实可以看作一个寄存器),多个触发器可以组成一个多位的寄存器,多位的寄存器可以存储多 bit 的二进制数据。

结构图
在这里插入图片描述
这是一个2bit寄存器,由两个1bit寄存器(即两个触发器)组成
在这里插入图片描述

通过上图,我们可以看到,第一个触发器的输入是 D0, F1 触发器的 D0 经过时钟上升沿采样后输出Q0, 输出的 Q0 为 F2 的输入。 由于 F2 的输入来自于上一个触发器的输出 Q0,因此 F2 的输出比 F1 的输出要晚一个时钟周期, 这个地方也就是通常所说的延迟一拍的概念, 在逻辑电路设计里面, 俗称“打一拍”,或者寄存一拍。

2、通过四个串联的寄存器理解打拍的概念

RTL电路
在这里插入图片描述
在这里插入图片描述从绘制的波形图我们可以看出,因为是时序逻辑电路,所以输入 a 的值会延迟一个时钟周期赋值给
a_reg1。以此类推,每个寄存器的值都会延迟一个时钟周期赋值给下一个寄存器。

3、modelsim仿真中打拍失效的解决方法

有时在仿真中不会延迟一拍,因为现实中D端到Q端有延时,但是仿真中没有,所以在赋值时延迟一个单位时间

module shift_reg
(
input		wire		clk	,
input		wire		rst_n	,
input		wire		a	,

output		wire		y	

);

reg 	a_reg1;
reg 	a_reg2;
reg 	a_reg3;
reg 	a_reg4;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
	a_reg1	<=	0;
	a_reg2	<=	0;
	a_reg3	<=	0;
	a_reg4	<=	0;
    end
    else begin
	a_reg1	<=	a	;
	a_reg2	<=	a_reg1	;
	a_reg3	<=	a_reg2	;
	a_reg4	<=	a_reg3	;
    end
end

endmodule

仿真文件

module tb_shift_reg();
reg 	sys_clk		;
reg 	sys_rst_n	;
reg 	a		;
 

wire	y		;


initial begin
	sys_clk = 1'b1;
	sys_rst_n <= 1'b0;
	a <= 1'b0;
	#200
	sys_rst_n <= 1'b1;
	#100
	a <= 1'b1;
	#100
	a <= 1'b0;
end

always #10 sys_clk <= ~sys_clk;

shift_reg shift_reg_inst(
	.clk 		(sys_clk 	),
	.rst_n 		(sys_rst_n 	),
	.a 		(a 		),

	.y 		(y 		)
);


endmodule

没有延迟打拍
在这里插入图片描述

module tb_shift_reg();
reg 	sys_clk		;
reg 	sys_rst_n	;
reg 	a		;
 

wire	y		;


initial begin
	sys_clk = 1'b1;
	sys_rst_n <= 1'b0;
	a <= 1'b0;
	#201//这里延迟一个时间单位在301ns会错过上升沿所以可以延迟一拍
	sys_rst_n <= 1'b1;
	#100
	a <= 1'b1;
	#100
	a <= 1'b0;
end

always #10 sys_clk <= ~sys_clk;

shift_reg shift_reg_inst(
	.clk 		(sys_clk 	),
	.rst_n 		(sys_rst_n 	),
	.a 		(a 		),

	.y 		(y 		)
);


endmodule

延迟了一拍
在这里插入图片描述
总结

  • 寄存器是同步时钟信号控制上升沿采样
  • 实际电路中会产生因为D端到Q端的时延产生延迟打拍现象,modelsim仿真中不会体现,需要手动延迟一个时间单位。

https://www.zhihu.com/question/279664328
https://www.zhihu.com/question/279664328

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值