跨时钟域信号处理

一、场景描述:

某信号signal需要在不同的时钟域进行处理,需要同步到的不同的时钟域继续使用。

举例说明:某定时器Timer包含两个时钟域bus_clk和tmr_clk。状态寄存器STS和控制寄存器CTRL定义如下。寄存器读写访问采用bus_clk时钟,Timer功能采用tmr_clk时钟,当发生溢出时置位溢出标志,即set_tof=1,set_tof属于tmr_clk时钟域,通过对寄存器相应位写1清零清除溢出标志,即clr_tof=1,clr_tof属于bus_clk时钟域。经过跨时钟域处理之后,需要产生两个信号TOF和tof_async,TOF为寄存器标志位供用户访问属于bus_clk时钟域,tof_async用于产生异步中断属于tmr_clk时钟域,两个信号TOF和tof_async属于不同的时钟域。

Name STS  
Offset 0x00
Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Read  
Write
Reset 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Read   TOF
Write W1C
Reset 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

TOF:计数器溢出标志,通过写1清零。

Name CTRL  
Offset 0x04
Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Read  
Write
Reset 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Read                              IE EN
Write
Reset 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

IE:溢出中断使能。

EN:Timer计数使能。

二、代码实现:

1、cross_clk_domain模块设计

 1 module cross_clk_domain(
 2 
 3     output  wire  signal1,                // for clk1 domain
 4     output  wire  signal2,                // for clk2 domain
 5 
 6     input    wire  set_signal_condition,  // siganl set condition in clk1 domain
 7     input    wire  clk1,
 8     input    wire  rstn1,
 9 
10     input    wire  clr_signal_condition,  // signal clr condition in clk2 domain
11     input    wire  clk2,
12     input    wire  rstn2
13 );
14 
15 reg  set_signal;
16 reg  set_signal_d;
17 reg  set_signal_dd;
18 reg  clr_signal;
19 reg  clr_signal_d;
20 reg  clr_signal_dd;
21 
22 always @(posedge clk1 or negedge rstn1)begin
23     if(!rstn1)begin
24         set_signal <= 1'b0;
25     end
26     else if(clr_signal_dd)begin
27         set_signal <= 1'b0;
28     end
29     else if(set_signal_condition)begin
30         set_signal <= 1'b1;
31     end
32 end
33 
34 always @(posedge clk2 or negedge rstn2)begin
35     if(!rstn2)begin
36         set_signal_d   <= 1'b0;
37         set_signal_dd  <= 1'b0;
38     end
39     else begin
40         set_signal_d   <= set_signal;
41         set_signal_dd  <= set_signal_d;
42     end
43 end
44 
45 always @(posedge clk2 or negedge rstn2)begin
46     if(!rstn2)begin
47         clr_signal <= 1'b0;
48     end
49     else if(~set_signal_dd )begin
50         clr_signal <= 1'b0;
51     end
52     else if(clr_signal_condition)begin
53         clr_signal <= 1'b1;
54     end
55 end
56 
57 always @(posedge clk1 or negedge rstn1)begin
58     if(!rstn1)begin
59         clr_signal_d   <= 1'b0;
60         clr_signal_dd  <= 1'b0;
61     end
62     else begin
63         clr_signal_d   <= clr_signal;
64         clr_signal_dd  <= clr_signal_d   ;
65     end
66 end
67 
68 assign signal1 = set_flag;     // signal1 in clk1 domain
69 assign signal2 = set_flag_dd;  // signal2 in clk2 domain
70 
71 endmodule

 2、实例化

 1 cross_clk_domain  cross_clk_domain_inst(
 2     signal1(tof_async),
 3     signal2(tof),
 4 
 5     set_signal_condition(set_tof),
 6     clk1(tmr_clk),
 7     rstn1(tmr_clk_rstn),               // asynchronous reset and synchronous release
 8 
 9     clr_signal_condition (clr_tof),
10     clk2(bus_clk),
11     rstn2(bus_clk_rstn)
12 );

注:tmr_clk_rstn和bus_clk_rstn两个复位信号不属于同一复位信号,否则会存在亚稳态问题(后期会详细探讨这个问题),一般顶层端口只提供一个复位信号bus_clk_rstn,这里的tmr_clk_rstn需要做异步复位同步释放处理。

 

posted @ 2021-05-28 22:57  芯客栈  阅读(294)  评论(0)    收藏  举报