前言

看别人的好设计,能让自己从细节上提升,所谓好的设计,除了从各种指标上评判,我们都知道,设计的兼容性(参数化),可读性,可扩展性等等,可是既然是学习,我们本身就不知道什么样的才是好的,这些指标也分辨不出来,怎么办呢?

那就不如简单粗暴些,看官方的例程,例如Xilinx的例程,不过我也需要澄清一点,我并不是说官方的设计一定是好的设计,例如我曾见过A家的uart设计,那风格简直了,各个模块都放到一个文件里,就这一点就不可原谅。

当然,原因也可能人家就不是自己写的,机器生成的罢了。

对于官方的设计,很多地方还是值得学习的,见过的逻辑设计多了, 我们就可以去辨别,对好的设计也颇为感觉,工程师的洁癖以及共识,会让你不自觉的认为这种设计是好的。(今天的内容借鉴与X家的例程:wavegen)

今天的话题是复位,当然对于复位,我在学生时期就总结很多,什么异步复位以及同步复位的好处,但总归,这些复位方式都有一些弊端,看会不会对你的工程产生影响,如果工程的结构就不在乎,那直接异步复位简单粗暴也无可厚非,但很多设计是对复位敏感的。

如果要使用复位让所有模块一起工作,作为一种起点性的东西(你有更充分的理由吗?欢迎打出来告诉大家),复位还是需要设计的,推荐的方式,老生常谈,就是异步复位,同步释放。

逻辑设计

可以设计成一个模块,供工程调用,代码可读性强,清晰明了,是好的设计。


module reset_bridge (
input clk_dst, // Destination clock
input rst_in, // Asynchronous reset signal
output reg rst_dst // Synchronized reset signal
);

//......

endmodule

模块名reset_bridge,很不错的名字。

废话不多说,上图:

对于高电平复位信号,使用时钟对其两拍同步,当然起点位置一定要和原复位信号一致,保证能检测到复位,复位的结束位置是设计的精华,重点,那就是大家要同时释放,用时钟采样复位结束位置,保证同步,且保证复位长度至少一个时钟,这里打两拍,复位长度就为两个时钟了。

如下图示意:

逻辑设计中复位的稳妥处理方法?_sed

对于低电平复位,下图示意:

逻辑设计中复位的稳妥处理方法?_时序约束_02

后面就只讨论高电平复位了,低电平复位留作作业。

为什么上面强调打两拍使用呢?

这是因为输入的复位信号是一个异步信号,什么时候都可能出现,如果出现的位置不巧,不满足时钟采样的建立保持时间,就会出现亚稳态,也就是在下图圈出来的位置,不知道是高电平还是低电平,不确定:

逻辑设计中复位的稳妥处理方法?_sed_03

那就达不到设计的初衷,从设计上就解决这种时序问题,后面还可以在时序约束时候,直接false复位路径,不做考虑。

于是我们使用的复位信号,在其他模块中使用的复位信号是最后一个信号rst_dst。

好了,就这样,直接分享A家的Verilog逻辑:

//-----------------------------------------------------------------------------
//
// Copyright (c) 2008 Xilinx Inc.
//
// Project : Programmable Wave Generator
// Module : reset_bridge.v
// Parent : Various
// Children : None
//
// Description:
// This is a specialized metastability hardener intended for use in the
// reset path. The reset will assert ASYNCHRONOUSLY when the input reset is
// asserted, but will deassert synchronously.
//
// In designs with asynchronous reset flip-flops, this generates a reset
// that can meet the "recovery time" requirement of the flip-flop (be sure
// to enable the recovery time arc checking - ENABLE=reg_sr_r).
//
// In designs with synchronous resets, it ensures that the reset is
// available before the first valid clock pulse arrives.
//
// Parameters:
// None
//
// Notes :
//
// Multicycle and False Paths, Timing Exceptions
// A tighter timing constraint should be placed between the rst_meta
// and rst_dst flip-flops to allow for meta-stability settling time
//

`timescale 1ns/1ps


module reset_bridge (
input clk_dst, // Destination clock
input rst_in, // Asynchronous reset signal
output reg rst_dst // Synchronized reset signal
);


//***************************************************************************
// Register declarations
//***************************************************************************

reg rst_meta; // After sampling the async rst, this has
// a high probability of being metastable.
// The second sampling (rst_dst) has
// a much lower probability of being
// metastable

//***************************************************************************
// Code
//***************************************************************************

always @(posedge clk_dst or posedge rst_in)
begin
if (rst_in)
begin
rst_meta <= 1'b1;
rst_dst <= 1'b1;
end
else // if !rst_dst
begin
rst_meta <= 1'b0;
rst_dst <= rst_meta;
end // if rst
end // always

endmodule