1 同步复位与异步复位
注:
2.测试
1 `timescale 1ns / 1ps 2 module FuWei( 3 input i_clk, 4 input i_rst_n, 5 input[3:0] i_data, 6 output reg[3:0] o_sync_data, 7 output reg[3:0] o_asyn_data 8 ); 9 //同步复位 10 always @(posedge i_clk) 11 if(!i_rst_n) o_sync_data<=4'd0; 12 else o_sync_data<=i_data; 13 //异步复位 14 always @(posedge i_clk or negedge i_rst_n) 15 if(!i_rst_n) o_asyn_data<=4'd0; 16 else o_asyn_data<=i_data; 17 endmodule
TestBench:
1 `timescale 1ns / 1ps 2 module TestBench( ); 3 `define CLK_PERIORD 10 //时钟周期设置为10ns(100MHz) 4 reg clk; 5 reg rst_n; 6 reg[3:0] i_data; 7 wire[3:0] o_sync_data; 8 wire[3:0] o_asyn_data; 9 FuWei my_test( 10 .i_clk(clk), 11 .i_rst_n(rst_n), 12 .i_data(i_data), 13 .o_sync_data(o_sync_data), 14 .o_asyn_data(o_asyn_data) 15 ); 16 initial begin 17 clk <= 0; 18 rst_n <= 0; 19 #10; 20 rst_n <= 1; 21 repeat(10) begin @(posedge clk); end 22 #4; 23 rst_n <= 0; 24 repeat(10) begin @(posedge clk); end 25 rst_n <= 1; 26 end 27 28 //时钟产生 29 always #(`CLK_PERIORD/2) clk = ~clk; 30 31 //测试激励产生 32 initial begin 33 i_data <= 4'b1111; 34 @(posedge rst_n); //等待复位完成 35 @(posedge clk); 36 repeat(300000) begin 37 @(posedge clk); 38 end 39 $stop; 40 end 41 endmodule
仿真:
可以看到:当复位下降沿来临时,异步复位的数据直接置为0,而同步复位的数据是等到下一个时钟上升沿来临时,才置为0
一般不建议使用异步复位
如果非要使用异步复位,可以采用:经过同步处理的异步复位输出(对异步做同步处理)
经过同步处理的异步复位输出:
1 reg r_rst_n; 2 always@(posedge i_clk) 3 r_rst_n<=i_rst_n; 4 always @(posedge i_clk or negedge r_rst_n) 5 if(!r_rst_n) o_asyn_data2<=4'd0; 6 else o_asyn_data2<=i_data;
仿真:
可以看到:经过同步处理的异步复位的输出(o_asyn_data2)和同步复位输出一样,也是当复位信号下降沿到来时,先等一会,等到紧接着时钟信号的上升沿来临时,再置为0