先来明确下什么是同步复位:
同步复位:就是指复位信号只有在时钟上升沿到来时,才能有效,否则无法完成对系统的复位工作。用verilog描述如下:
always @ (posedge clk)
begin
if (!Rst_n)
...
end
异步复位:它是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。用Verilog描述如下:
always @ (posedge clk or negedge Rst_n)
begin
if (!Rst_n)
...
end
quote:”Wishbone规范规定的复位是同步复位,因此在复位信号有效后接下来的时钟上升沿,所有信号和寄存器进入预定状态。“
为了实现同步复位,在编写Wishbone总线接口时应该注意对复位信号的处理。
举例说明:
Wishbone接口的verilog文件中对复位信号的处理为:
// reset signal
wire reset_sig;
wire reset;
reg reset_r;
assign reset = wb_stb_i & wb_cyc_i & (wb_adr_i[6:2]==5'h3) & wb_we_i;
always@(posedge wb_clk_i)
begin
if(wb_rst_i)
reset_r <= 1'b0;
else
reset_r <= reset;
end
assign reset_sig = (reset_r == 1'b1)&&(reset == 1'b0);
// Instantiate the Unit Under Test (UUT)
uut uut (
.clk_i(wb_clk_i),
.rst_i(reset_sig),
.other_signal(other_signal),
);
分析此段代码不要被wb_rst_i信号干扰,wb_rst_i信号是Wishbone的复位信号,与模块uut的复位信号是两码事。这段代码现将实时信号reset存入寄存器reset_r,每次时钟上升沿更新reset_r值,reset_sig 信号可在时钟上升沿时捕捉到可能存在的reset下降沿,从而实现同步复位。
在testbench中用以下语句来测试:
always #5 wb_clk_o = ~wb_clk_o;
initial
begin
@(posedge wb_clk_o);
@(posedge wb_clk_o);
#21 wb_we_o = 1;
wb_adr_o[6:2] = 5'h3;//复位信号
#17 wb_we_o = 0;
wb_adr_o[6:2] = 5'h0;
...
end
可获得如下波形:
如图所示,实现了模块的同步复位。
PS:洗洗睡了~~