pulse_synchronizer(异步信号处理)程序理解
2010-12-14 20:10
302 查看
本地地址:E:/FPGA/NetFPGA/project_top/src_for_graduate/big_fpga/gemac_group/pulse_synchronizer.v
///////////////////////////////////////////////////////////////////////////////
// $Id: pulse_synchronizer.v 1887 2007-06-19 21:33:32Z grg $
//
// Module: pulse_synchronizer.v
// Project: UNET-SWITCH4-64bit-wbs
// Description: transforms a pulse(脉冲) from one domain(领域,范围,范畴) into a pulse in another domain
// note that the arriving pulses should be separated by around 5 cycles
// in each domain.
//
///////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps
module pulse_synchronizer
( input pulse_in_clkA, //输入脉冲A
input clkA, //输入时钟A
output pulse_out_clkB, //输出脉冲
input clkB, //输入时钟B
input reset_clkA, //输入时钟A复位信号
input reset_clkB //输入时钟B复位信号
);
reg ackA; //
reg ackB; //
reg ackA_synch;
reg ackA_clkB;
reg ackB_synch;
reg ackB_clkA;
reg pulse_in_clkA_d1;
reg ackA_clkB_d1;
reg ackB_d1;
/* detect rising edges in clkA domain, set the ackA signal
* until the pulse is acked from the other domain */
always @(posedge clkA) begin
if(reset_clkA) begin
ackA <= 0;
end
else if(!pulse_in_clkA_d1 & pulse_in_clkA) begin //捕捉在clkA中的脉冲的上升沿。在后仿真时,clkA_d1的赋值比较clkA的慢,会出现很短的clkA_d1为低,clkA为高
ackA <= 1; //的情况,是ackA置位。。
end
else if(ackB_clkA) begin //ackB_clkA比ackB慢一个clkA的时钟,因此当ackB_clkA为低时xx
ackA <= 0;
end
end // always @ (posedge clkA)
/* detect the rising edge of ackA and set ackB until ackA falls */
always @(posedge clkB) begin
if(reset_clkB) begin
ackB <= 0;
end
else if(!ackA_clkB_d1 & ackA_clkB) begin //
ackB <= 1;
end
else if(!ackA_clkB) begin
ackB <= 0;
end
end // always @ (posedge clkB)
/* detect rising edge of ackB and send pulse */
assign pulse_out_clkB = ackB & !ackB_d1;
/* synchronize the ack signals */
always @(posedge clkA) begin
if(reset_clkA) begin
pulse_in_clkA_d1 <= 0;
ackB_synch <= 0;
ackB_clkA <= 0;
end
else begin
pulse_in_clkA_d1 <= pulse_in_clkA; //clkA时钟下的脉冲寄存器
ackB_synch <= ackB; //ackB的同步信号
ackB_clkA <= ackB_synch; //ackB慢一个clkA周期的信号
end
end
/* synchronize the ack signals */
always @(posedge clkB) begin
if(reset_clkB) begin
ackB_d1 <= 0;
ackA_synch <= 0;
ackA_clkB <= 0;
ackA_clkB_d1 <= 0;
end
else begin
ackB_d1 <= ackB; //仿真波形不一致??
ackA_synch <= ackA; //ackA的同步信号
ackA_clkB <= ackA_synch; //ackA在clkB的一个周期的延迟信号
ackA_clkB_d1 <= ackA_clkB; //ackA在clkB的两个周期的延迟信号
end
end
endmodule // pulse_synchronizer
第二次仿真:
always #10 clkA = ~clkA;
always #20 clkB = ~clkB;
initial begin
// Initialize Inputs
pulse_in_clkA = 0;
clkA = 0;
clkB = 0;
reset_clkA = 0;
reset_clkB = 0;
// Wait 100 ns for global reset to finish
#10 reset_clkA = 1;
#10 reset_clkA = 0; reset_clkB = 1;
#10 reset_clkB = 0;
#100 pulse_in_clkA = 1;
#100 pulse_in_clkA = 0;
第三次仿真:
将#100 pulse_in_clkA = 1;改为#110 pulse_in_clkA = 1;
波形分析:
ackA的置位:捕捉在pluse_in_clkA中的脉冲的上升沿。在后仿真时,pluse_in_clkA_d1的赋值比较pluse_in_clkA的慢,会出现很短的pluse_in_clkA_d1为低,pluse_in_clkA为高的情况,是ackA置位
ackA_synch的上升沿:在clkB的上升沿时,进行采集信号,延迟有所不同,比如第三次仿真整整满了一个clkB的周期,而第二次仿真则没有到一个clkB的周期。
ackA_clkB的上升沿:比ackA_synch慢一个clkB的周期
ackA_clkB_d1的上升沿:比ackA_clkB慢一个clkB的周期
ackB的上升沿:以clkB为参照时钟,捕捉在!ackA_clkB_d1 & ackA_clkB时,产生上升沿。
pluse_in_clkA_d1的下降:根据clkA的上升沿进行捕捉。第三次仿真慢了半个clkA的周期
ackB_synch的上升沿:根据clkA的上升沿判断,捕捉ackB信号。
总体信号间的影响关系图:
pluse_in_clkA上升沿 =》 pluse_in_clkA_d1的上升沿 =》ackA 的上升沿 =》 ackA_synch的上升沿 =》 ackA_clkB的上升沿 =》 ackA_clkB_d1的上升沿 =》ackB的上升沿 =》ackB_synch的上升沿 =》ackB_clkA的上升沿
=》ackA的下降沿=》 ackA_synch的下降沿 =》 ackA_clkB的下降沿 =》 ackA_clkB_d1的下降沿 =》ackB的下降沿 =》ackB_synch的下降沿 =》ackB_clkA的下降沿
(注:红色的为以clkA作为参照,蓝色的为以clkB作为参照)
最后是assign pulse_out_clkB = ackB & !ackB_d1;将输出信号提取出来。
上面的仿真是将快时钟域中的信号向慢时钟域信号转变,进行扩充。
这个是慢时钟域的信号向快时钟域中的信号转变。
备注:每次转变时都要求是快的时钟信号先复位,然后慢的时钟在复位。(自己仿真的结果,不知道为什么)
///////////////////////////////////////////////////////////////////////////////
// $Id: pulse_synchronizer.v 1887 2007-06-19 21:33:32Z grg $
//
// Module: pulse_synchronizer.v
// Project: UNET-SWITCH4-64bit-wbs
// Description: transforms a pulse(脉冲) from one domain(领域,范围,范畴) into a pulse in another domain
// note that the arriving pulses should be separated by around 5 cycles
// in each domain.
//
///////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps
module pulse_synchronizer
( input pulse_in_clkA, //输入脉冲A
input clkA, //输入时钟A
output pulse_out_clkB, //输出脉冲
input clkB, //输入时钟B
input reset_clkA, //输入时钟A复位信号
input reset_clkB //输入时钟B复位信号
);
reg ackA; //
reg ackB; //
reg ackA_synch;
reg ackA_clkB;
reg ackB_synch;
reg ackB_clkA;
reg pulse_in_clkA_d1;
reg ackA_clkB_d1;
reg ackB_d1;
/* detect rising edges in clkA domain, set the ackA signal
* until the pulse is acked from the other domain */
always @(posedge clkA) begin
if(reset_clkA) begin
ackA <= 0;
end
else if(!pulse_in_clkA_d1 & pulse_in_clkA) begin //捕捉在clkA中的脉冲的上升沿。在后仿真时,clkA_d1的赋值比较clkA的慢,会出现很短的clkA_d1为低,clkA为高
ackA <= 1; //的情况,是ackA置位。。
end
else if(ackB_clkA) begin //ackB_clkA比ackB慢一个clkA的时钟,因此当ackB_clkA为低时xx
ackA <= 0;
end
end // always @ (posedge clkA)
/* detect the rising edge of ackA and set ackB until ackA falls */
always @(posedge clkB) begin
if(reset_clkB) begin
ackB <= 0;
end
else if(!ackA_clkB_d1 & ackA_clkB) begin //
ackB <= 1;
end
else if(!ackA_clkB) begin
ackB <= 0;
end
end // always @ (posedge clkB)
/* detect rising edge of ackB and send pulse */
assign pulse_out_clkB = ackB & !ackB_d1;
/* synchronize the ack signals */
always @(posedge clkA) begin
if(reset_clkA) begin
pulse_in_clkA_d1 <= 0;
ackB_synch <= 0;
ackB_clkA <= 0;
end
else begin
pulse_in_clkA_d1 <= pulse_in_clkA; //clkA时钟下的脉冲寄存器
ackB_synch <= ackB; //ackB的同步信号
ackB_clkA <= ackB_synch; //ackB慢一个clkA周期的信号
end
end
/* synchronize the ack signals */
always @(posedge clkB) begin
if(reset_clkB) begin
ackB_d1 <= 0;
ackA_synch <= 0;
ackA_clkB <= 0;
ackA_clkB_d1 <= 0;
end
else begin
ackB_d1 <= ackB; //仿真波形不一致??
ackA_synch <= ackA; //ackA的同步信号
ackA_clkB <= ackA_synch; //ackA在clkB的一个周期的延迟信号
ackA_clkB_d1 <= ackA_clkB; //ackA在clkB的两个周期的延迟信号
end
end
endmodule // pulse_synchronizer
第二次仿真:
always #10 clkA = ~clkA;
always #20 clkB = ~clkB;
initial begin
// Initialize Inputs
pulse_in_clkA = 0;
clkA = 0;
clkB = 0;
reset_clkA = 0;
reset_clkB = 0;
// Wait 100 ns for global reset to finish
#10 reset_clkA = 1;
#10 reset_clkA = 0; reset_clkB = 1;
#10 reset_clkB = 0;
#100 pulse_in_clkA = 1;
#100 pulse_in_clkA = 0;
第三次仿真:
将#100 pulse_in_clkA = 1;改为#110 pulse_in_clkA = 1;
波形分析:
ackA的置位:捕捉在pluse_in_clkA中的脉冲的上升沿。在后仿真时,pluse_in_clkA_d1的赋值比较pluse_in_clkA的慢,会出现很短的pluse_in_clkA_d1为低,pluse_in_clkA为高的情况,是ackA置位
ackA_synch的上升沿:在clkB的上升沿时,进行采集信号,延迟有所不同,比如第三次仿真整整满了一个clkB的周期,而第二次仿真则没有到一个clkB的周期。
ackA_clkB的上升沿:比ackA_synch慢一个clkB的周期
ackA_clkB_d1的上升沿:比ackA_clkB慢一个clkB的周期
ackB的上升沿:以clkB为参照时钟,捕捉在!ackA_clkB_d1 & ackA_clkB时,产生上升沿。
pluse_in_clkA_d1的下降:根据clkA的上升沿进行捕捉。第三次仿真慢了半个clkA的周期
ackB_synch的上升沿:根据clkA的上升沿判断,捕捉ackB信号。
总体信号间的影响关系图:
pluse_in_clkA上升沿 =》 pluse_in_clkA_d1的上升沿 =》ackA 的上升沿 =》 ackA_synch的上升沿 =》 ackA_clkB的上升沿 =》 ackA_clkB_d1的上升沿 =》ackB的上升沿 =》ackB_synch的上升沿 =》ackB_clkA的上升沿
=》ackA的下降沿=》 ackA_synch的下降沿 =》 ackA_clkB的下降沿 =》 ackA_clkB_d1的下降沿 =》ackB的下降沿 =》ackB_synch的下降沿 =》ackB_clkA的下降沿
(注:红色的为以clkA作为参照,蓝色的为以clkB作为参照)
最后是assign pulse_out_clkB = ackB & !ackB_d1;将输出信号提取出来。
上面的仿真是将快时钟域中的信号向慢时钟域信号转变,进行扩充。
这个是慢时钟域的信号向快时钟域中的信号转变。
备注:每次转变时都要求是快的时钟信号先复位,然后慢的时钟在复位。(自己仿真的结果,不知道为什么)
相关文章推荐
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装 【手记】走近科学之为什么明明实现了IEnumerable<T>的类型却不能调用LINQ扩展方法 【手记】手机网页弹出层后屏蔽底层的滑动响应 【手记】ASP.NET提示“未能创建类型”处理 【Web】一个非常简单的移动web消息框 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”
- 异步(ajax)配合一般处理程序 验证用户名
- Android 异步消息处理机制 让你深入理解 Looper、Handler、MessageQueue、Message四者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- [转载]对于可重入、线程安全、异步信号安全几个概念的理解
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Spring MVC 异步处理请求,提高程序性能
- TCP 回射程序(处理子进程的SIGCHLD信号)
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Linux程序退出时的信号捕获及处理
- 【信号处理】因果系统的理解
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- linux内核中异步通信机制--信号处理机制
- PetShop程序中的购物车和订单处理模块(Profile技术,异步MSMQ消息)
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 深入理解 Looper、Handler、Message
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解