(转)跨时钟域数据采集总结

一.典型方法

二.结绳法

 1.结绳法1:利用数据的边沿作时钟(例子中上升沿)。(可以将脉冲无限延长,直到可以采集到数据,然后复位,要考虑产生数据的频率)。

  实例1

实例2

 2结绳法2:利用数据作为异步复位,置位信号。(适合将不足时钟宽度的脉冲扩展1周期)

 实例1:输入高脉冲(clka域),输出高脉冲(clkb域)

实例2:输入高脉冲(clka域),输出低脉冲(clkb域)

实例3:输入低脉冲(clka域),输出低脉冲(clkb域)

实例4:输入低脉冲(clka域),输出高脉冲(clkb域)

 3结绳法3:输入作为数据输入,同样也是检测高有效后,输出一直为高,异步时钟域可以采集到数据后再复位。
因为没有将输入作为时钟,或者作为异步set,reset,所以这类方便比较常用。

参考代码:http://bb2hh.blogbus.com/files/12357833650.v

//================================================================================
// Created by         : Ltd.com
// Filename           : sync_clk1_clk2.v
// Author             : Python_Wang
// Created On         : 2009-02-27 22:47
// Last Modified      : 2009-02-28 09:09
// Description        : 
//                      
//                      
//================================================================================
module sync_clk1_clk2(
  clk1                       ,
  rst_n1                     ,
  clk2                       ,
  rst_n2                     ,
  data_clk1_i                ,
  data_clk2_o              
);
input        clk1            ;
input        rst_n1          ;
input        clk2            ;
input        rst_n2          ;
input        data_clk1_i     ;
output       data_clk2_o     ;

reg          data_clk1_q1    ;
reg          data_clk1_q2    ;

reg          data_clk2_q1    ;
reg          data_clk2_q2    ;
reg          data_clk2_q3    ;
reg          data_clk2_q4    ;
reg          data_clk2_q5    ;

wire         data_clk1       ;

assign  data_clk1 = data_clk1_i | ( !data_clk2_q5 & data_clk1_q1) ;

always@(posedge clk1 or negedge rst_n1)
begin
  if(!rst_n1) begin
    data_clk1_q1  <= #1 'b0;
    data_clk1_q2  <= #1 'b0;
  end
  else begin
    data_clk1_q1  <= #1 data_clk1   ;
    data_clk1_q2  <= #1 data_clk1_q1;
  end
end

always@(posedge clk2 or negedge rst_n2)
begin
  if(!rst_n2) begin
    data_clk2_q1  <= #1 'b0;
    data_clk2_q2  <= #1 'b0;
    data_clk2_q3  <= #1 'b0;
  end
  else begin
    data_clk2_q1  <= #1 data_clk1_q1;
    data_clk2_q2  <= #1 data_clk2_q1;
    data_clk2_q3  <= #1 data_clk2_q2;
  end
end

always@(posedge clk1 or negedge rst_n1)
begin
  if(!rst_n1) begin
    data_clk2_q4  <= #1 'b0;
    data_clk2_q5  <= #1 'b0;
  end
  else begin
    data_clk2_q4  <= #1 data_clk2_q2;
    data_clk2_q5  <= #1 data_clk2_q4;
  end
end

assign data_clk2_o = data_clk2_q2 & ~data_clk2_q3 ;

endmodule

仿真:

4.结绳法3:利用握手协议:(可以将脉冲无限延长,直到可以采集到数据,然后复位,要考虑产生数据的频率)。

 

    

参考代码:http://bb2hh.blogbus.com/files/12357826152.v

//================================================================================
// Created by         : Ltd.com
// Filename           : handover.v
// Author             : Python_Wang
// Created On         : 2009-02-19 19:31
// Last Modified      : 2009-02-20 08:38
// Description        : 
//                      
//                      
//================================================================================
module handover(
rst_n                        ,
ClkA                         ,
Req_ClkA                     ,
Ack_ClkA                     ,
ClkB                         ,
Dvld_ClkB                   
);
input        rst_n           ;
input        ClkA            ;
input        Req_ClkA        ;
input        ClkB            ;
output       Ack_ClkA        ;
output       Dvld_ClkB       ;
reg          Dvalid_ClkB     ;
reg          Q_Dvalid_ClkB   ;


reg          Dvalid_ClkA     ;
always@(posedge ClkA) 
begin
  if(!rst_n) begin
    Dvalid_ClkA <= #1 1'b0;
  end
  else if(Req_ClkA) begin
    Dvalid_ClkA <= #1 ~Dvalid_ClkA ;
  end
end


reg          Q1_ClkB         ;
reg          Q2_ClkB         ;
reg          Q3_ClkB         ;
always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Q1_ClkB <= #1 'b0;
    Q2_ClkB <= #1 'b0;
    Q3_ClkB <= #1 'b0;
  end
  else begin
    Q1_ClkB <= #1 Dvalid_ClkA ;
    Q2_ClkB <= #1 Q1_ClkB     ;
    Q3_ClkB <= #1 Q2_ClkB     ;
  end
end

wire Req_ClkB = Q2_ClkB ^ Q3_ClkB ;


always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Dvalid_ClkB   <= #1 'b0;
    Q_Dvalid_ClkB <= #1 1'b0;
  end
  else if(Req_ClkB) begin
    Dvalid_ClkB   <= #1 ~Dvalid_ClkB ;
    Q_Dvalid_ClkB <= #1 Dvalid_ClkB  ;
  end
end

always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Q_Dvalid_ClkB <= #1 1'b0;
  end
  else begin
    Q_Dvalid_ClkB <= #1 Dvalid_ClkB  ;
  end
end


reg          Q1_ClkA         ;
reg          Q2_ClkA         ;
reg          Q3_ClkA         ;
always@(posedge ClkA) 
begin
  if(!rst_n) begin
    Q1_ClkA <= #1 'b0 ;
    Q2_ClkA <= #1 'b0 ;
    Q3_ClkA <= #1 'b0 ;
  end
  else begin
    Q1_ClkA <= #1 Dvalid_ClkB ;
    Q2_ClkA <= #1 Q1_ClkA     ;
    Q3_ClkA <= #1 Q2_ClkA     ;
  end
end

assign  Ack_ClkA = Q2_ClkA ^ Q3_ClkA ;
assign  Dvld_ClkB = Dvalid_ClkB & ~Q_Dvalid_ClkB;

endmodule

仿真:

另外对于为了提高速度和准确度的握手操作中,可以将设置一定的握手模块(n>2(clk1+clk2)/Trd),流水操作

 

结绳就是将单脉冲延长,以方便采集到数据。

结绳的方法归结为2类:

1.利用脉冲的边沿做时钟;

2.利用脉冲的电平(部分场合要求最小脉冲宽度)做选择器或者异步复位,置位。

另外的关键点就是什么时候结绳结束(采集到了数据就要让对方回到初始状态),

这里的操作也有2种方法:

1.利用采集到的脉冲做异步复位,置位。

2.利用采集到的脉冲再次结绳采集做握手响应信号。

处理的时候应该选择对应的方法。

同时共享一下用到的电子电路图形库(visio的)

http://bb2hh.blogbus.com/files/12350304650.rar

原文地址:https://www.cnblogs.com/lueguo/p/3567569.html