众所周知,我们在IC设计中采用异步复位的方式,那么异步复位寄存器在你的RTL下它到底长什么样子呢?
为此我找到一篇知乎前辈的文章,进行精选,下面详细的了解一下异步复位异步置位寄存器的生成以及结构和相关的timing约束如何进行。
verilog语法中always@(posedge clk or negedge clk)这种语句是我们最常用的语句之一。
IC设计中一般我们的写法是:
always @ (posedge clk or negedge resetn)begin
if(~resetn)
q <= 1'b0;
else
q <= 1'b1;
end
这里需要说明的是 always block块中
1:必须要有if 条件语句,否则dc 工具会报错,
2:if条件判断语句中的信号必须在always块的敏感信息列表中
3:if中条件如果为(resetn),则会报错,因为在敏感列表中写的是negedge resetn,如果敏感列表中为posedge resetn,则不会报错。
4:敏感信号列表中要么都是边沿触发信号,要么都是电平触发,不能混合。
规避掉以上问题,上面代码框中的RTL综合后你就会得到一个如下所示的寄存器:
这是一个带反相器的异步复位寄存器结构。
那么加入我把always块中的negedge resetn改为posedge resetn,综合出来的寄存器会是什么样子?
看,反相器没了。
此时我们可以暂时性的得出一个结论,异步复位寄存器都是high active。
我们继续往下看:
always块中不仅可以控制异步复位还可以控制异步置位。在敏感列表中添加更多的trigger signal,可以让dc产生带有异步置位pin的DFF。
TSMC的lib中,异步置位的pin都是SDN,low active,因此下面的电路图都是以SDN表示异步置位管脚。
always @ ( posedge clk or negedge resetn or negedge setn ) begin
if ( ~resetn ) q <= 1'b0;
else if ( ~setn ) q <= 1'b1;
else q <= d;
end
这是标准的同时带有异步复位和异步置位的verilog代码,综合后的电路如下:
DFF的异步复位输入pin是CD,它是high active,而异步置位输入pin是SDN,是low active,verilog代码使用的resetn和setn都是negedge trigger,因此异步复位会多出来一个INV cell,而SDN就不会。
如果把set_n放在rst_n前面,依然能综合成功,此时set_n在if条件中有更高的优先级,而且dc工具综合后的电路会多出来一些cell,用于判断setn优先级高于resetn。
always @ ( posedge clk or negedge resetn or negedge setn ) begin
if ( ~setn ) q <= 1'b1;
else if ( ~resetn ) q <= 1'b0;
else q <= d;
end
综合后的电路如下:
在TMSC的doc目录中找到描述cell的文档,能发现其实TSMC对CD和SDN是有要求的,要求CD和SDN不能同时有效,如下图中所示:
同时,对应的verilog model中,找到DFF对应的primitive原语,发现CD比SDN的优先级更高。如图中所示。
dc工具也认为异步复位比异步置位的优先级高,当verilog代码中把resetn放在前面时,~resetn和setn会被连接在CD和SDN上,而当代码中把setn放在前面时,综合后的电路会多出来一些cell,用于判断setn优先级高于resetn,如上述图中所示。
还要说明的一点是,always语句的敏感列表中的信号数不局限于2个或者3个,而是可以有更多,只要他们全都是edge trigger即可,那么假如在RTL时,我设置两个异步复位信号,综合以后的电路会是什么样子?
下面就举个例子简单的说明一下:
always @ ( posedge clk or negedge resetn or negedge setn or posedge resetp or posedge setp ) begin
if ( ~resetn ) q <= 1'b0;
else if ( resetp ) q <= 1'b0;
else if ( ~setn ) q <= 1'b1;
else if ( setp ) q <= 1'b1;
else q <= d;
end
调整4个signal的先后顺序,他们的优先级也随之改变,也会产生不同的电路结构,就不细说了。
接下来我要说的是,如何在sdc中对异步复位寄存器的复位端口和置位端口进行约束。