FPGA中韩彬(大神)的异步复位,同步释放方法

module system_ctrl//无PLL的全局时钟模块顶层(下面的那个模块是这个顶层模块的子模块)
(

input clk,
input rst_n,


output clk_ref, //输出时钟
output sys_rst_n //输出复位
);


//----------------------------------------------


reg     rst_nr1, rst_nr2;//打节拍,使其达到同步状态(异步:是指reset和clk这两个小信号原来不是一起触发;同步:是指这两个信号经过打一拍后变成了输出都取决于clk信号)
always @(posedge clk)//同步复位,打节拍使其只受clk控制
begin
if(!rst_n)
begin
rst_nr1 <= 1'b0;
rst_nr2 <= 1'b0;
end
else
begin
rst_nr1 <= 1'b1;
rst_nr2 <= rst_nr1;
end
end




//----------------------------------


wire delay_done; //例化延时模块,延时50ms
system_init_delay
#(
.SYS_DELAY_TOP (24'd2500000)//这里我有不懂为什么用这样写,不过我觉着可以自己直接定义一个常数就行
 )
u_system_init_delay
(
.clk (clk),
.rst_n (1'b1), //永远不复位,为的是就用一次这个延时50ms的模块
.delay_done (delay_done)
);


assign clk_ref = clk;
assign sys_rst_n = rst_nr2 & delay_done; //输出复位的条件


endmodule




module system_init_delay//延时50ms,作为全局时钟顶层中的子模块
#(
parameter SYS_DELAY_TOP = 24'd2500000 //50ms 定时
)
(

input clk, //50MHz
input rst_n,

output delay_done
);


//------------------------------------------


reg [23:0] delay_cnt = 24'd0;//因为永远不复位,所以这里要直接赋值为0
always@(posedge clk or negedge rst_n)//延时50ms的计数
begin
if(!rst_n)
delay_cnt <= 0;
else if(delay_cnt < SYS_DELAY_TOP - 1'b1)
delay_cnt <= delay_cnt + 1'b1;
else
delay_cnt <= SYS_DELAY_TOP - 1'b1;
end
assign delay_done = (delay_cnt == SYS_DELAY_TOP - 1'b1)? 1'b1 : 1'b0;//完成的标志


endmodule






//有PLL的复位模板,就是要把PLL作为输出的主时钟和复位要再做一次同步释放处理
//`timescale 1 ns / 1 ns
module system_ctrl_pll//系统的异步复位,同步处理模块
(

input clk,
input rst_n,



output clk_c0, //clock output 这里可以好几个经过pll输出的时钟,在同步时钟时选择其中频率最高的作为同步时钟,
output sys_rst_n //system reset
);


//----------------------------------


wire delay_done; //这是例化延时模块,以后这个快可以照搬,为了使FPGA上电后稳定,所以要延时50ms
system_init_delay
#(
.SYS_DELAY_TOP (24'd2500000)
// .SYS_DELAY_TOP (24'd256) //这个仅仅用于仿真操作
)
u_system_init_delay
(

.clk (clk),
.rst_n (1'b1), //用于不复位,因为复位就一次,不能再在个延时中使用

.delay_done (delay_done)
);
wire pll_rst = ~delay_done;// pll的复位,当延时完成时就复位




//-----------------------------------
//例化pll IP核
wire locked;//locked信号为PLL完成的标志
sys_pll u_sys_pll 
(
.inclk0 (clk),
.areset (pll_rst),
.locked (locked),
.c0 (clk_c0)
);


//----------------------------------------------
//异步复位,同步操作
reg     rst_nr1, rst_nr2;
always @(posedge clk_c0)//这个时钟用PLL例化后输出里的主时钟如果(输出多个时钟,自己看一下哪个是主时钟,就同步哪里主时钟),
begin
if(!rst_n)
begin
rst_nr1 <= 1'b0;
rst_nr2 <= 1'b0;
end
else
begin
rst_nr1 <= 1'b1;
rst_nr2 <= rst_nr1;
end
end
assign sys_rst_n = rst_nr2 & locked; //复位的条件!


endmodule


下面是等待时间,是上一个模块的子模块


`timescale 1 ns / 1 ns
module system_init_delay
#(
parameter SYS_DELAY_TOP = 24'd2500000 //  50ms延时,用于FPGA开机
)
(

input clk, //50MHz
input rst_n,

output delay_done
);


//------------------------------------------
//延时的计数器
reg [23:0] delay_cnt = 24'd0;//因为只有一次复位的机会,所以下面的那个复位就是个摆设而已,所以这个地方要直接赋值
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
delay_cnt <= 0;
else if(delay_cnt < SYS_DELAY_TOP - 1'b1)
delay_cnt <= delay_cnt + 1'b1;
else
delay_cnt <= SYS_DELAY_TOP - 1'b1;
end
assign delay_done = (delay_cnt == SYS_DELAY_TOP - 1'b1)? 1'b1 : 1'b0;


endmodule
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA(现场可编程门阵列)可以使用异步复位同步释放来实现复位功能。异步复位表示当特定条件满足时,立即对电路进行复位操作。而同步释放是在特定时钟边沿上释放复位。 要实现异步复位同步释放功能,可以按照以下步骤进行操作: 1. 定义一个异步复位信号:首先,您需要定义一个异步复位信号,通常命名为"reset_n"。这个信号是一个低电平有效的信号,当信号处于低电平时,电路处于复位状态。 2. 实现异步复位逻辑:将异步复位信号与需要进行复位的电路模块相连。在异步复位信号为低电平时,这些模块将被复位。 3. 添加同步释放逻辑:为了实现同步释放,您需要创建一个同步释放信号。这个信号也是一个低电平有效的信号,通常命名为"release"或"reset_release"。它将在时钟边沿上发出释放复位的命令。 4. 使用寄存器进行同步释放:在时钟边沿上,将同步释放信号输入到一个寄存器,以确保在稳定的时钟状态下进行释放操作。 5. 解除复位状态:将寄存器的输出与需要解除复位的电路模块相连。当同步释放信号为低电平,且在时钟边沿上稳定时,这些模块将离开复位状态。 需要注意的是,异步复位同步释放是一种常见的实现方式,但在具体的设计可能会有一些微调和优化,以满足特定的要求和约束。此外,确保异步复位同步释放的时序满足FPGA器件的要求也很重要。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值