基于Verilog设计的复位电路设计

1.1简介

复位指的是将寄存器中的值全部置成默认值,一般复位包括同步复位和异步复位,复位可以由硬件开关控制,也可以由软件逻辑控制。复位电路复杂是因为复位本身是对大规模的硬件单元进行一种操作,必须要结合底层的设计来考虑问题。

相信大家在学习 FPGA 或者 ASIC 的时候都有如下的疑问:
1、 数字逻辑为什么需要复位?
2、 FPGA 板上面没有复位按键怎么办?
3、 复位只有通过按键复位一个控制方式吗?
4、 同步复位好还是异步复位好呢?
5、 复位是高电平有效还是低电平有效好呢?
1、 数字逻辑为什么需要复位?
数字电路中寄存器和 RAM 在上电之后默认的状态和数据是不确定的,如果有复位,我们可以把寄存器
复位到初始状态 0, RAM 的数据可以通过复位来触发 RAM 初始化到全 0。那可能很多人会问为什么是全 0
呢?其实一般逻辑起始都是从 0 开始变化的,这个是根据设计的需要设定的一个值,如果设计需要寄存器
上电复位为 1,也是可以的。 还有一种情况是逻辑进入了错误的状态, 通过复位可以把所有的逻辑状态恢复
到初始值,如果没有复位,那么逻辑可能永远运行在错误的状态。因此复位功能是很重要的一个功能。
2、 FPGA 板上面没有复位按键怎么办?
没有复位按键也没有关系,因为 FPGA 内部也会有上电复位的功能, 不管是 Intel(已收购 ALTERA)
还是 Xilinx 的 FPGA,都是有上电复位电路,也就是 POR(Power On Reset)电路。 FPGA 芯片内部有一个
上电检测模块,一旦检测到电源电压超过检测门限后,就产生一个上电复位脉冲(Power On Reset)送给所有
的寄存器,这个脉冲会自动作用在各个寄存器的复位端,和功能复位管脚共同控制寄存器的复位。
还有一种情况,就是 FPGA 重新配置之后,也会触发上电复位。因此 FPGA 板上面即使没有复位按键
也是没有关系的。
3、 复位只有通过按键复位一个控制方式吗?
复位按键是一种控制方式,还有一种上电自动复位控制, 

基于Verilog设计的复位电路设计_第1张图片


通过 R1 对 C2 进行充电,经过一段延迟后加到电路这种是一种简单的 RC 复位电路,电源接通时候,
当中产生复位信号,这个复位信号的上升速度低于电源的上电速度,当复位引脚检低于电源的上电速度,当复位引脚检测到高电平时候,系统复位结束,进入正常的工作状态
同步复位指的是当时钟上升沿检测到复位信号,执行复位操作, 有效的时钟沿是前提。
Verilog 中是这样写的:
1 always @ (posedge clk) begin
1 if (rst_n == 1'b0)
1 y <= 1'b0 ;
1 else
1 y <= b ;
2 end
同步复位的优点如下:
a、有利于仿真器的仿真;
b、可以使所设计的系统成为 100%的同步时序电路,有利于时序分析,而且可综合出较高的 Fmax;
c、由于只在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的复位毛刺。
同步复位也有一些缺点, 缺点如下:
a、复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑诸如
时钟偏移、组合逻辑路径延时、复位延时等因素(所以复位信号有时需要脉冲展宽,用以保证时钟有效期间
有足够的复位宽度);
b、由于大多数的逻辑器件的目标库内的 DFF 都只有异步复位端口,所以,倘若采用同步复位的话,综
合器就会在寄存器的数据输入端口插入组合逻辑,这样就会一方面额外增加 FPGA 内部的逻辑资源,另一
方面也增加了相应的组合逻辑门时延。
异步复位
异步复位指的是无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。当时钟上升沿检测到复
位信号,执行复位操作。
Verilog 中是这样写的:
1 always @ (posedge clk or negedge rst_n) begin
1 if (rst_n == 1'b0)
1 y <= 1'b0 ;
1 else
1 y <= b ;
2 end
优点:
a、大多数目标器件库的 DFF 都有异步复位端口,那么该触发器的复位端口就不需要额外的组合逻辑,
这样就可以节省资源;
b、设计相对简单;
c、异步复位信号产生和响应都很方便(电路在任何情况下都能复位而不管是否有时钟出现)。
异步复位也有一些缺点, 缺点如下:
a、最大的问题在于它属于异步逻辑,问题出现在复位释放时,而不是有效时,如果复位释放接近时钟
有效沿,则触发器的输出可能进入亚稳态(此时 clk 检测到的 rst_n 的状态就会是一个亚稳态,即是 0 是 1
是不确定的),从而导致复位失败。
b、可能因为噪声或者毛刺造成虚假复位信号(比如系统正常工作时突然复位)(注意:时钟端口、清零和置位端口对毛刺信号十分敏感,任何一点毛刺都可能会使系统出错,因此判断逻辑电路中是否存在冒
险以及如何避免冒险是设计人员必须要考虑的问题);
c、静态定时分析比较困难,静态时序分析一般是针对同步设计的,都是基于时钟周期来分析时序的。
d、对于 DFT(DesignForTest 可测性设计) 设计,如果复位信号不是直接来自于 I/O 引脚,在 DFT 扫描
和测试时,复位信号必须被禁止,因此需要额外的同步电路。
总结下来,我们推荐使用异步复位、同步释放的方式,并且复位信号为低电平有效
复位信号到来的有效与否与 clk 无关,而且复位信号的撤除也与 clk 无关,但是复位信号的撤除是在
下一个 clk 来到后才起的作用。
2、异步复位同步撤离的目的为了防止复位信号撤除时,可能产生的亚稳态。
 

always @ (posedge clk or negedge rst_async_n) begin
2 if (!rst_async_n) begin
3 rst_s1 <= 1'b0;
4 rst_s2 <= 1'b0;
5 end
6 else begin
7 rst_s1 <= 1'b1;
8 rst_s2 <= rst_s1;
9 end
10 end
11
12 assign rst_sync_n = rst_s2;
13
14 always @ (posedge clk or negedge rst_sync_n ) begin
15 if (rst_sync_n == 1'b0)
16 y <= 1'b0 ;
17 else
18 y <= b ;
19 end

 基于Verilog设计的复位电路设计_第2张图片

 复位信号 rst_sync_n 由高拉低时实现 y 寄存器的异步复位。同步释放, 这个是关键,即当复位信号
rst_async_n 撤除时(由低拉高),由于双缓冲电路(双触发器)的作用, rst_sync_n 不会随着 rst_async_n 的
撤除而撤除。假设 rst_async_n 撤除时发生在 clk 上升沿,如果不加此电路则可能发生亚稳态事件,但是加
上此电路以后,假设第一级 D 触发器 clk 上升沿时 rst_async_n 正好撤除,(第一个 DFF 此时是处于亚稳态
的;假设此时识别到高电平;若是识别到低电平,则增加一个 Delay)则 DFF1 输出高电平,此时第二级触
发器也会更新输出,但是输出值为前一级触发器 clk 来之前时的 Q1 输出状态,显然 Q1 之前为低电平,所
以第二级触发器输出保持复位低电平,直到下一个 clk 来之后,才随着变为高电平,即同步释放。

2.1 设计一个按键消抖电路

//file name : key_debounce.v
//file funcition   : 设计一个复位按键消抖电路
//file version  : 1.0version 
//file date : 2023/4/3
//Author  : ZihangNie

//******************************************

module key_debounce(
    //输入信号
    input               sys_clk , //输入时钟
	input               key  ,//复位按键
	
   //输出信号
    output    wire      sys_rst_n  // 按键消抖后的数据输出

) ;

// reg  寄存器定义

reg   [31:0]      delay_cnt   ; // 定义一个延时计数器
reg               key_reg     ; // 定义一个寄存器用来存储延时后的按键信号
reg               key_value   ; // 定义一个寄存器用来存储最终的信号


//**********************main code*************************
//********************************************************
//********************************************************


always @ (posedge sys_clk) begin 
    key_reg <= key ; //把信号写入寄存器
	
	if (key_reg != key) begin  //如果信号的状态发生了变化(有按键按下或者释放)
	    delay_cnt <=  32'b1000000 ; //给计数器置初始值 ,产生20ms的延迟量
	end
	else if ( key_reg == key ) begin  // 如果信号的状态稳定
	    if(delay_cnt > 1) begin 
		     delay_cnt <= delay_cnt - 1'b1 ; //开始进行倒计时20ms
		end
		else begin 
		     delay_cnt <= delay_cnt ;  // 没有达到稳定状态的时候则不进行计时
		end
	end	
end		   
	
always @(posedge sys_clk) begin 
    if(delay_cnt == 1) begin	// 如果计数器的值为1 ,说明消抖过程结束
	    key_value <= key  ;  // 将信号存入结果信号中
    end 
    else begin 
        key_value <= sys_rst_n ;
	end
end

assign  sys_rst_n =  key & key_value ;  //去除毛刺;

endmodule
 

2.2testbench文件测试

//file name : tb_key_debounce.v
//file function : 用于测试复位按键消抖的仿真文件
//file date :2023/4/5
//file version : 1.0version 
//Author : ZihangNie


//****************************************************************

`timescale 1ns/1ps   //仿真的时间1ns/仿真的精度是1ps

module  tb_key_debounce(); //定义仿真的模块


// input signal 

reg sys_clk ;
reg     key ;

//output signal 

wire   sys_rst_n ;

//信号进行初始化

initial begin
    key  = 1'b0 ;
	sys_clk = 1'b0 ;
#200
    key = 1'b1 ;
#100 
    key = 1'b0 ;
#60
    key = 1'b1 ;
#80 
    key = 1'b0 ;
#100
    key = 1'b1 ;
end 

always # 10 sys_clk = ~sys_clk ;

//对key_debounce模块进行消抖

key_debounce u_key_debounce (
    .sys_clk(sys_clk),
	.key(key),
	.sys_rst_n(sys_rst_n)


);
endmodule 

你可能感兴趣的:(fpga开发)