我是靠谱客的博主 迷人巨人,这篇文章主要介绍跨时钟域脉冲信号处理——脉冲同步器一、同步器——快时钟域到慢时钟域二、握手——快时钟域到慢时钟域,现在分享给大家,希望可以做个参考。

文章目录

  • 一、同步器——快时钟域到慢时钟域
  • 二、握手——快时钟域到慢时钟域

一、同步器——快时钟域到慢时钟域

脉冲同步器的基本原理:

  1. 将src_clk时钟域的输入脉冲转换为src_clk时钟域的电平信号src_state
  2. 对src_state电平信号进行打拍(打两拍)同步到dst_clk时钟域
  3. 对dst_clk时钟域的电平信号进行检测,产生dst_clk时钟域脉冲

电路如下:

在这里插入图片描述
代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module pulse_sync(src_clk, src_rst_n, src_pulse, dst_clk, dst_rst_n, dst_pulse); input src_clk; //source clock input src_rst_n; //source reset input src_pulse; //source pulse in input dst_clk; //destination clock input dst_rst_n; //destination reset output dst_pulse; //destination pulse out //Internal singles reg src_state; reg state_delay1; reg state_delay2; reg dst_state; wire dst_puase; //==============MODULE MAIN CODE========================= //1.输入脉冲转成电平信号,确保时钟B可以采到 always@(posedge src_clk or negedge src_rst_n)begin if(src_rst_n==0) src_state <= 0; else if(src_pulse) src_state <= ~src_state; end //2.//源时钟域的src时钟下电平信号转成时钟dst下的脉冲信号 always@(posedge dst_clk or negedge dst_rst_n)begin if(dst_rst_n)begin state_delay1 <= 0; state_delay2 <= 0; dst_state <= 0; end else begin state_delay1 <= src_state; state_delay2 <= state_delay1; dst_state <= state_delay2; end end assign dst_pulse = dst_state^state_delay2; endmodule

二、握手——快时钟域到慢时钟域

   从上一部分的设计原理中,我们可以发现该同步器的控制传递是单向的,即仅从源时钟域到目的时钟域,目的时钟域并没有状态反馈。假设存在如下应用:

  • 源时钟域中的第一个脉冲和第二个脉冲间隔过短,第一个脉冲未完成同步,第二脉冲又将状态清空,导致最终脉冲同步丢失。

   要解决以上同步问题,需要引入异步握手机制,保证每个脉冲都同步成功,同步成功后再进行下一个脉冲同步。握手原理如下:

  • sync_req: 源时钟域同步请求信号,高电平表示当前脉冲需要同步;
  • sync_ack: 目的时钟域应答信号,高电平表示当前已收到同步请求;
    在这里插入图片描述
     完整同步过程分为以下4个步骤:

(1) 同步请求产生;当同步器处于空闲(即上一次已同步完成)时,源同步脉冲到达时产生同步请求信号sync_req;
  (2) 同步请求信号sync_req同步到目的时钟域,目的时钟域产生脉冲信号并将产生应答信号sync_ack;
  (3) 同步应答信号sync_ack同步到源时钟域,源时钟域检测到同步应答信号sync_ack后,清除同步请求信号;
  (4) 目的时钟域检测到sync_req撤销后,清除sync_ack应答;源时钟域将到sync_ack清除后,认为一次同步完成,可以同步下一个脉冲。

代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
module HANDSHAKE_PULSE_SYNC ( src_clk , //source clock src_rst_n , //source clock reset (0: reset) src_pulse , //source clock pulse in src_sync_fail , //source clock sync state: 1 clock pulse if sync fail. dst_clk , //destination clock dst_rst_n , //destination clock reset (0:reset) dst_pulse //destination pulse out ); //PARA DECLARATION //INPUT DECLARATION input src_clk ; //source clock input src_rst_n ; //source clock reset (0: reset) input src_pulse ; //source clock pulse in input dst_clk ; //destination clock input dst_rst_n ; //destination clock reset (0:reset) //OUTPUT DECLARATION output src_sync_fail ; //source clock sync state: 1 clock pulse if sync fail. output dst_pulse ; //destination pulse out //INTER DECLARATION wire dst_pulse ; wire src_sync_idle ; reg src_sync_fail ; reg src_sync_req ; reg src_sync_ack ; reg ack_state_dly1 ; reg ack_state_dly2 ; reg req_state_dly1 ; reg req_state_dly2 ; reg dst_req_state ; reg dst_sync_ack ; //--========================MODULE SOURCE CODE==========================-- //--=========================================-- // DST Clock : // 1. generate src_sync_fail; // 2. generate sync req // 3. sync dst_sync_ack //--=========================================-- assign src_sync_idle = ~(src_sync_req | src_sync_ack ); //report an error if src_pulse when sync busy ; always @(posedge src_clk or negedge src_rst_n) begin if(src_rst_n == 1'b0) src_sync_fail <= 1'b0 ; else if (src_pulse & (~src_sync_idle)) src_sync_fail <= 1'b1 ; else src_sync_fail <= 1'b0 ; end //set sync req if src_pulse when sync idle ; always @(posedge src_clk or negedge src_rst_n) begin if(src_rst_n == 1'b0) src_sync_req <= 1'b0 ; else if (src_pulse & src_sync_idle) src_sync_req <= 1'b1 ; else if (src_sync_ack) src_sync_req <= 1'b0 ; end always @(posedge src_clk or negedge src_rst_n) begin if(src_rst_n == 1'b0) begin ack_state_dly1 <= 1'b0 ; ack_state_dly2 <= 1'b0 ; src_sync_ack <= 1'b0 ; end else begin ack_state_dly1 <= dst_sync_ack ; ack_state_dly2 <= ack_state_dly1 ; src_sync_ack <= ack_state_dly2 ; end end //--=========================================-- // DST Clock : // 1. sync src sync req // 2. generate dst pulse // 3. generate sync ack //--=========================================-- always @(posedge dst_clk or negedge dst_rst_n) begin if(dst_rst_n == 1'b0) begin req_state_dly1 <= 1'b0 ; req_state_dly2 <= 1'b0 ; dst_req_state <= 1'b0 ; end else begin req_state_dly1 <= src_sync_req ; req_state_dly2 <= req_state_dly1 ; dst_req_state <= req_state_dly2 ; end end //Rising Edge of dst_state generate a dst_pulse; assign dst_pulse = (~dst_req_state) & req_state_dly2 ; //set sync ack when src_req = 1 , clear it when src_req = 0 ; always @(posedge dst_clk or negedge dst_rst_n) begin if(dst_rst_n == 1'b0) dst_sync_ack <= 1'b0; else if (req_state_dly2) dst_sync_ack <= 1'b1; else dst_sync_ack <= 1'b0; end endmodule

参考:https://www.cnblogs.com/digital-wei/p/6014450.html

最后

以上就是迷人巨人最近收集整理的关于跨时钟域脉冲信号处理——脉冲同步器一、同步器——快时钟域到慢时钟域二、握手——快时钟域到慢时钟域的全部内容,更多相关跨时钟域脉冲信号处理——脉冲同步器一、同步器——快时钟域到慢时钟域二、握手——快时钟域到慢时钟域内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(107)

评论列表共有 0 条评论

立即
投稿
返回
顶部