一、产生时钟的方式
1. 使用forever,注意一定要给时钟clk赋初始值,否则信号的缺省值为z。
initial begin
clk = 0;
#delay;
forever #(period/2) clk = ~clk;
end
2. 使用always
initial begin
clk = 0;
#delay;
always #(period/2) clk = ~clk;
end
3. 使用repeat产生3个时钟
initial begin
clk = 0;
#delay;
repeat(6) #(period/2) clk = ~clk;
end
4. 产生占空比非50%的时钟
initial begin
clk = 0;
#delay;
always begin
#3 clk = ~clk;
#2 clk = ~clk;
end
end
二、产生复位信号的方式
1. 异步复位
intial begin
rst = 1;
#100;
rst = 0;
#500;
rst = 1;
end
2. 同步复位
initial begin
rst = 1;
@(negedge clk) rst = 0;
#30;
@(negedge clk) rst = 1;
end
3. 同步复位
initial begin
rst = 1;
@(negedge clk) rst = 0;
repeat(3) @(negedge clk);
rst = 1;
end
三、复位电路类型
复位:确保系统上电后有一个明确的、稳定的初始状态,或者系统运行紊乱后可以恢复到正常的初始状态。复位电路可以分为同步复位和异步复位。
1.同步复位
复位信号不单独列出,只是作为判断条件。
优点:能够滤除复位信号的毛刺,有利于分析
缺点:大部分复位信号没有同步复位,采用同步复位会消耗多余的逻辑资源;复位信号宽度小于一个时钟周期有可能会被漏掉。
module sync_reset(
input rstn, //同步复位信号
input clk, //时钟
input din, //输入数据
output reg dout //输出数据
);
always @(posedge clk) begin //!!!复位信号不要加入到敏感列表中!!!
if(!rstn) dout <= 1'b0 ; //rstn 信号与时钟 clk 同步
else dout <= din ;
end
endmodule
2.异步复位
复位的下降沿添加到信号敏感列表中
优点:大多数复位信号带有异步复位端;设计简单,识别快速方便
缺点:复位信号与时钟信号无确定的时序关系,异步复位很容易引起时序上 removal 和 recovery 的不满足。且异步复位容易受到毛刺的干扰,产生意外的复位操作。
module async_reset(
input rstn, //异步复位信号
input clk, //时钟
input din, //输入数据
output reg dout //输出数据
);
//复位信号要加到敏感列表中
always @(posedge clk or negedge rstn) begin
if(!rstn) dout <= 1'b0 ; //rstn 信号与时钟 clk 异步
else dout <= din ;
end
endmodule
3.异步复位同步释放
复位信号到来时不受时钟信号的同步,复位信号释放时需要进行时钟信号的同步。
优点:消除异步复位的缺陷,复位电路往往会采用"异步复位、同步释放"的设计方法。
module areset_srelease(
input rstn, //异步复位信号
input clk, //时钟
input din, //输入数据
output reg dout //输出数据
);
reg rstn_r1, rstn_r2;
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
rstn_r1 <= 1'b0; //异步复位
rstn_r2 <= 1'b0;
end
else begin
rstn_r1 <= 1'b1; //同步释放
rstn_r2 <= rstn_r1; //同步打拍,时序差可以多延迟几拍
end
end
//使用 rstn_r2 做同步复位,复位信号可以加到敏感列表中
always @ (posedge clk or negedge rstn_r2) begin
if (!rstn_r2) dout <= 1'b0; //同步复位
else dout <= din;
end
endmodule