关于异步复位与同步复位的实际举例在上篇博文中已经讲述,这里不在讲述。接下来将分享几个常用的异步复位同步释放的方法。
-
用最高时钟将复位信号往后打几拍,如下用两个寄存器实现系统复位
module sync_rst( sys_clk, ext_rst_n, sys_rst_n);
input sys_clk;//系统时钟50M input ext_rst_n;//复位信号 output sys_rst_n;//系统复位信号
//---------------------------------------------- //系统复位信号产生,低有效 //异步复位,同步释放 reg rst_nr1,rst_nr2; always@(posedge sys_clk ornegedge ext_rst_n) begin if(!ext_rst_n) rst_nr1 <=1'b0; else rst_nr1 <=1'b1; end
always@(posedge sys_clk ornegedge ext_rst_n) begin if(!ext_rst_n) rst_nr2 <=1'b0; else rst_nr2 <= rst_nr1; end
assign sys_rst_n = rst_nr2;
endmodule |
Quartus II 12.0综合出来的RTL图
Modelsim 6.5仿真图如下:
从仿真图中可以看出系统复位的信号往后打慢了两个时钟周期。
这样一来既解决了同步复位信号带来的逻辑资源消耗的问题,也解决了异步复位信号出现的亚稳态稳定。
- 当系统采用PLL时,系统复位信号的设计和上面的设计稍有点不同。Verilog 代码为:
module sync_rst( sys_clk, ext_rst_n, sys_rst_n, pll_rst );
input sys_clk;//系统时钟50M input ext_rst_n;//复位信号 output sys_rst_n;//系统复位,低电平有效 output pll_rst;//pll复位,高电平有效
wire pll_clk0; //---------------------------------------------- //PLL复位信号产生,高有效 //异步复位,同步释放 wire pll_rst;//PLL复位信号,高有效
reg rst_r1,rst_r2;
always@(posedge sys_clk ornegedge ext_rst_n) begin if(!ext_rst_n) rst_r1 <=1'b1; else rst_r1 <=1'b0; end
always@(posedge sys_clk ornegedge ext_rst_n) begin if(!ext_rst_n) rst_r2 <=1'b1; else rst_r2 <= rst_r1; end
assign pll_rst = rst_r2;
//---------------------------------------------- //系统复位信号产生,低有效 //异步复位,同步释放 wire rst_nr0; reg rst_nr1,rst_nr2; wire pll_locked; assign rst_nr0 = ext_rst_n & pll_locked; always@(posedge pll_clk0 ornegedge rst_nr0) begin if(!rst_nr0) rst_nr1 <=1'b0; else rst_nr1 <=1'b1; end
always@(posedge pll_clk0 ornegedge rst_nr0) begin if(!rst_nr0) rst_nr2 <=1'b0; else rst_nr2 <= rst_nr1; end
assign sys_rst_n = rst_nr2;
pll pll_inst ( .areset ( pll_rst ), .inclk0 ( sys_clk ), .c0 ( pll_clk0 ), .locked ( pll_locked ) );
endmodule |
从代码中可以看出pll先复位,复位完成之后产生的pll_locked和ext_rst_n进行与操作,得到最好的系统复位信号。
Quatus II 12.0的RTL图
Modelsim 6.5仿真图如下:
- 最佳的异步复位,同步释放的方法
当FPGA在上电的时候,总是需要一些时间给所有逻辑块上电,即使上电时间非常短暂。在一些时序要求不高的场合,我们将其忽略不计似乎也不会对系统设计有什么影响,但是在某些时序要求比较严谨的场合,这几十纳秒和几十微妙的上电,FPGA系统工作其不稳定。因此提出一种有效的解决办法,就是在异步复位,同步释放的时候将系统延时几百微妙或者几毫秒。这样处理的好处是在FPGA上电后内部稳定后在对逻辑进行操作,系统也更加稳定。工程实践中,延时的值根据需求来定。笔者一般采用延时1ms的时间,Verilog代码如下:
module sync_rst( sys_clk, ext_rst_n, sys_rst_n, pll_rst, pll_clk0, );
input sys_clk; //系统时钟50M input ext_rst_n; //复位信号 output sys_rst_n; //系统复位,低电平有效 output pll_rst; //pll复位,高电平有效 output pll_clk0;
//延时一段时间使系统运行稳定 reg [15:0] delay_cnt; always@(posedge sys_clk) begin if(delay_cnt <16'd50_000) //50000*20ns=1ms delay_cnt <= delay_cnt +16'h1; else delay_cnt <= delay_cnt; end
assign delay_flag =(delay_cnt ==16'd50_000)?1'b1:1'b0;
//---------------------------------------------- //PLL复位信号产生,高有效 //异步复位,同步释放 wire pll_rst; //PLL复位信号,高有效
reg rst_r1,rst_r2;
always@(posedge sys_clk ornegedge ext_rst_n) if(!ext_rst_n) rst_r1 <=1'b1; else rst_r1 <=1'b0;
always@(posedge sys_clk ornegedge ext_rst_n) if(!ext_rst_n) rst_r2 <=1'b1; else rst_r2 <= rst_r1;
assign pll_rst = rst_r2 &(~delay_flag);
//---------------------------------------------- //系统复位信号产生,低有效 //异步复位,同步释放 wire rst_nr0; reg rst_nr1,rst_nr2; wire pll_locked; assign rst_nr0 = ext_rst_n & pll_locked & delay_flag; always@(posedge pll_clk0 ornegedge rst_nr0) begin if(!rst_nr0) rst_nr1 <=1'b0; else rst_nr1 <=1'b1; end
always@(posedge pll_clk0 ornegedge rst_nr0) begin if(!rst_nr0) rst_nr2 <=1'b0; else rst_nr2 <= rst_nr1; end
assign sys_rst_n = rst_nr2;
pll pll_inst ( .areset ( pll_rst ), .inclk0 ( sys_clk ), .c0 ( pll_clk0 ), .locked ( pll_locked ) );
endmodule |
Quartus II 12.0的RTL图