文章目录
- 一、同步器——快时钟域到慢时钟域
- 二、握手——快时钟域到慢时钟域
一、同步器——快时钟域到慢时钟域
脉冲同步器的基本原理:
- 将src_clk时钟域的
输入脉冲转换为src_clk时钟域的电平信号src_state
; 对src_state电平信号进行打拍(打两拍)同步到dst_clk时钟域
;- 对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
43module 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
128module 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
最后
以上就是迷人巨人最近收集整理的关于跨时钟域脉冲信号处理——脉冲同步器一、同步器——快时钟域到慢时钟域二、握手——快时钟域到慢时钟域的全部内容,更多相关跨时钟域脉冲信号处理——脉冲同步器一、同步器——快时钟域到慢时钟域二、握手——快时钟域到慢时钟域内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复