Bootstrap

ic八股学习第二天——锁存器的结构_触发器的结构_建立保持时间

砍柴的娃和放羊的娃一起玩,晚上回来,他的羊吃饱了,你的柴呢?

Latch

结构

锁存器(Latch):电平触发,数据存储取决于信号的电平值。电平有效时,输出信号被锁存。
锁存器如下:
在这里插入图片描述

生成latch与避免latch

在组合逻辑中,如果Verilog的if语句中缺少else分支时,或者在case语句中没有覆盖所有可能的条件且没有default分支时,综合工具往往会生成锁存器。
比如:

input[3:0] data_in;
always @(data_in)
begin
case(data_in)
    0:         out1 = 1'b1;
    1,3:       out2 = 1'b1;
    2,4,5,6,7: out3 = 1'b1;
    default:   out4 = 1'b1;
endcase
end

在这里插入图片描述
该代码生成了四个latch,
因为out1234方便只在自己值改变的情况下赋值了,在其他情况下没有赋值

在组合逻辑中,如果将输出变量显式地赋值给自己,综合工具往往也会生成锁存器。

module latch_assign (
    input wire in,
    input wire enable,
    output reg out
);
always @(*) begin
    if (enable) out = in;
    else out = out;  // 显式自赋值,生成锁存器
end
endmodule
always @(*) begin
    if(condition)
        aa = 1'b0;
    else
        aa = aa; //generate latch
end

确保所有条件分支完整,避免显式自赋值,可以规避在组合逻辑中综合出latch

always @(*) begin
    if (enable) out = in;
    else out = 0;  // 提供默认值
end

信号特别多的情况下,在每个条件下都给每个信号赋值,这样就会导致代码很冗长,此时可以给每个信号一个初值。修改方法为:

input[3:0] data_in;
always @(data_in)
begin
    out1 = 1'b0;
    out2 = 1'b0;
    out3 = 1'b0;
    out4 = 1'b0;
    case(data_in)
    0:         out1 = 1'b1;
    1,3:       begin
                    out2 = 1'b1;
                end
    2,4,5,6,7: begin
                    out3 = 1'b1;
                end
    default:   beign
                    out4 = 1'b1;
               end
    endcase
end

在这里插入图片描述

更简单的方法是,使用sv,always_comb块会综合出组合逻辑,always_latch会综合出锁存器

Flip-flop

触发器(Flip-Flop):边沿触发,数据存储取决于信号的上升沿或下降沿。

DFF

在这里插入图片描述

下面是一个典型的由一对主从latch构成的dff:
在这里插入图片描述
更省管子的TSPC DFF:

在这里插入图片描述
为什么可以这样省呢?首先,一个很正常思维的想法,SW2, INV2, SW4, INV4不直接在signal path上面的,先删了试试,那么就得到下图所示的结构

在这里插入图片描述
CK和CK非分别控制上下两个MOSFET, CK是1,CK非是0,这个clocked inverter可以导通。否则当CK是0,CK非是1,这个inverter关断。这个结构可以实现和主从latch一样的功能,这个结构叫做Clocked CMOS( C2MOS )。

但这个结构会带来一个新的问题,见 数字集成电路——(设计透视)P316:
A C2MOS register with CLK-CLK clocking is insensitive to overlap, as long as the rise and
fall times of the clock edges are sufficiently small.

所以出现了这样的结构
在这里插入图片描述
只有一个CK来控制所有的模块。比如CK是1的时候,N block(假设就是一个NMOS),输入的1可以通过N block传到X(X被N block和由CK控制的NMOS拉到0), 紧接着的P block(比如就是一个PMOS)能容易的采样到这个0,然后Y……Y没法改变。因为Y此时被下面的NMOS拉到了0,此时的X并不能传到Y。

如果用这种被N block和P block轮流控制的结构来改造传统的DFF,就成了我们所熟知的TSPC DFF。

Verilog写法

带异步复位和同步置位的DFF:

parameter len=8;

module csdff (
	input 				clk  	,   // Clock
	input 				set 	, 	// set
	input 				rst_n 	, 	// Asynchronous reset active low
	input 	   [len-1:0]d 		,	//input 
	output reg [len-1:0]q 			//output 	
);

always @(posedge clk , negedge rst_n , posedge set) begin 
	if(~rst_n) begin
		 q <= {len{1'b0}} 	;
	end 
	else if(set) begin
		 q <= {len{1'b1}} ;
	end
	else begin
		 q <=  d 	;
	end
end

endmodule 

T触发器
T触发器是在数字电路中,凡在CP时钟脉冲控制下,根据输入信号T取值的不同,具有保持和翻转功能的触发器,即当T=0时能保持状态不变,当T=1时一定翻转的电路。
在这里插入图片描述
在这里插入图片描述

module tff (	
			input 		clk 		,
			input 		rst_n 		,
			input 		T  			,
			output reg 	Q 			

	);
		always @(posedge clk or negedge rst_n) begin
			if(~rst_n) begin
				 Q 	<= 0;
			end 
			else begin
				 Q <= (T&~Q)|(~T&Q) ;
			end
		end

JK触发器
JK触发器是数字电路触发器中的一种基本电路单元。JK触发器具有置0、置1、保持和翻转功能。在各类集成触发器中,JK触发器的功能最为齐全。在实际应用中,它不仅有很强的通用性,而且能灵活地转换其他类型的触发器。由JK触发器可以构成D触发器和T触发器。
在这里插入图片描述

在这里插入图片描述

建立保持时间

在这里插入图片描述
在这里插入图片描述

建立时间

set up time 就是时钟有效沿(本文以上升沿为例)到来前信号需要保持稳定的时间。

这句话就是个套话官话是吧,时钟上升沿是哪个的时钟上升沿?为什么需要保持稳定?我上课时第一次听也没听懂,下来网上查了查才明白,说人话就是:

时钟上升沿指的这一级的DFF的Capture edge。对这一级的DFF的Capture edge来说,上一级DFF通过datapath传到它D端的这一拍的数据不能来的太晚,否则这一级的DFF就会采样到还在变化的非稳态数据(x态,可能成0了也可能成1了),甚至是时钟上一拍的数据;

具体计算方法

数据到达UFF1/D所需时间Arrival time为:
Ta = T_launch + T_ck2q + T_dp

满足setup要求时所允许的最长时间Required time为:
Tr = T_capture + T_clk - T_setup

因此setup time要求可表示为:Tr - Ta = T_margin ,时间裕度,通常最低要求取决于jitter以及时钟不确定性。
我们在DC或者ICC里面看到的setup slack的计算方式就是:
Setup Slack = Data Required Time – Data Arrival Time=Tr - Ta
我们要求这个值至少是大于0的,才能满足setup的要求

其中:

T_launch:CLKM到UFF0时钟端CK的延时

T_ck2q:UFF0的CK->Q的传输时间
为什么是ck2q或者c2Q,而不是d2q?一个是因为这个触发器不一定是dff,可能是tff或者大家都喜欢的jk,二是因为d的值是早就变化了的,这个时间是 “clk变化稳定后” 到 “q变化稳定后” 的时间,和d没关系

T_dp:组合逻辑延时

T_margin:设计裕量

T_setup:UFF1的setup时间要求

T_capture:CLKM到UFF1时钟端CK的延时

T_clk: 时钟周期

Data Arrival Time : 数据在datapath上传输的时间

Data Required Time : 时钟在clock path上传输的时间

由此可见,setup检查发生在不同时钟边沿,与时钟频率有关。

保持时间

hold time是指在时钟有效沿(本文以上升沿为例)之后,数据输入端信号必须保持稳定的最短时间。

说人话:对这一级的DFF的Capture edge来说,上一级DFF通过datapath传到它D端的下一拍的数据不能来太早,不然这一拍的数据都还没采样完,就被下一拍的数据覆盖了。

计算方法

同setup计算一样,数据到达UFF1/D所需时间Arrival time没有变,仍然为:

Ta = T_launch + T_ck2q + T_dp

但是满足hold要求时所允许的最短时间Required time和setup的不一样,为:

Tr = T_capture + T_hold

这是从另一个方面提出的要求,即下一拍的数据不能来太早

因此hold time要求可表示为:Ta - Tr = T_margin >= 0。

我们在DC或者ICC里面看到的hold slack的计算方式就是:
Setup Slack = Data Arrival Time - Data Required Time = Ta - Tr
我们要求这个值至少是大于0的,才能满足hold 的要求
注意这个计算公式和setup是相反的。

总结一下,我们可以把一条流水线比作一群做题家坐一排在算题,第一个人算第一步,第二个人算第二步,第n个人算第n步,两个人中间摆一个草稿本(也就是寄存器或者说dff),这些个做题家就是两个寄存器之间的组合逻辑,也叫datapath;第一个草稿本就写的是老板让做题家们算的题,就叫输入,最后一个草稿本就写的是给甲方爸爸看的答案,就叫output,中间的草稿本就写做题家们算的中间结果,第二个草稿本就是第一步的结果,第三个草稿本就是第二步的结果。clk有效沿一到,做题家们一听啪的一声时钟敲拍了,就齐刷刷往左边的草稿本瞟一眼上一个做题家算出来的中间结果,然后脑袋里面开始算,算好了之后就把右边的草稿本擦了写上自己算的中间结果。

要是你身为做题家算的太慢了,或者写答案太慢了,右边的做题家听到时钟敲拍的声音来瞟你的答案了,你都还没写完你的答案,就叫setup不满足; 要是你身为做题家算太快了,右边的做题家听到时钟敲拍的声音来瞟你的答案的时候,你都开始擦答案写下一个答案了甚至都擦完了,就叫hold不满足;如果你离clk敲拍的地方太远了,声音传播有时间的,每次大家齐刷刷看左边的时候你都慢个几ns,这就叫time skew。

setup不满足怎么办呢,把你开除了换个算得快点的,这就叫逻辑优化;你不想被开除,和右边的做题家商量一下,让他每次听到时钟敲拍的声音的时候等个几纳秒,等你写完了答案再来瞟你右边的草稿本,这就叫time borrow;那他不lend给你时间呢?他等你几纳秒再看草稿本,少的是他的时间,待会他该看不完了。你找老板,老板说你这个步骤确实要复杂些,这样吧,你把它也分成两步,你说你不会分,或者确实这个工作就是分不了,就得一个人算,不能串行也不能并行。老板说好好好,我看你花的时间是别人的六倍,那你听到六次敲拍的声音后再写草稿本,你不写后面的人不算,这就叫反压;你一想这样不行啊,我一个人慢连累着后面的人全慢了,不行不行,在这里插入图片描述
于是你还是找老板要来了5个人,你们六个一起算。第一次敲钟,做题家1看左边的草稿本然后算;第二次敲钟,做题家2看左边的草稿本然后算;第n次敲钟做题家n mod 6看左边的草稿本然后算。你们都是听到六次敲拍的声音后再写草稿本。这样虽然你们不能一起工作不能分工,还是6拍做一次,但是吞吐量上升了6倍,不会影响后面的做题家同学了。

那你离clk敲拍的地方太远了,导致每次大家齐刷刷看左边的时候你都慢个几ns这事儿怎么解决呢?让隔得近的等一下,保证你们“齐刷刷”,这就是CTS。其实也没必要真的齐刷刷,反正不耽搁看草稿本写草稿本的事就行,都还有人悄悄借时间呢。那如果确实影响到事儿了呢,而且如果流水钱太长离clk敲拍的地方近的人也等太久了,等的时间都敲几拍了。那这事儿就说明你们没坐对位置(布局布线太烂了),明儿个叫人事来给你们调整一下位置,坐成一个ring,每个人离敲拍的地方等距。那确实人太多了办公室太小了(面积限制),位置不好做呢。那干脆放多放两个敲拍的钟了,左边一个右边一个,一楼一个二楼一个。

如果多个时钟是同一个人敲的(同步时钟,派生时钟),好办,相差固定,要是远一点刚好差个整数倍时钟周期,调都不用调。

那不同的人敲的拍子不好同步啊,异步时钟源的相位差问题怎么解决?明天,继续介绍:

亚稳态_STA_CDC

;