当前位置:   article > 正文

牛客刷题总结——跨时钟域处理_快时钟域到慢时钟域跨时钟处理

快时钟域到慢时钟域跨时钟处理

在做SoC设计中,免不了包含异步时钟,那就需要进行正确的跨时钟域处理来保证数据在不同时钟域传输不出错。

一、亚稳态

当bclk的时钟正好采到aclk下data变化的边沿,就会产生亚稳态。

二、单bit跨时钟域处理

1. 快时钟域到慢时钟域

因为慢时钟域采快时钟域的信号可能采不到,所以需要将快时钟域的信号进行脉冲展宽之后再用慢时钟域的时钟采样。

脉冲同步:将时钟域clk_a下的脉冲转化为时钟域clk_b下的脉冲。要求时钟域clk_a下的脉冲必须为一个单时钟脉冲。

原理:将时钟域clk_a下的单脉冲信号pulse_a转化为电平信号pulse_inv,然后在时钟域clk_b下对该电平信号进行异或边沿检测便得到时钟域clk_b下的脉冲信号pulse_b,采用三级寄存器进行边沿检测,可以防止亚稳态传播。

  1. `timescale 1ns/1ns
  2. module pulse_detect(
  3. input clk_fast ,
  4. input clk_slow ,
  5. input rst_n ,
  6. input data_in ,
  7. output dataout
  8. );
  9. reg data_inv;
  10. reg data_reg1;
  11. reg data_reg2;
  12. reg data_reg3;
  13. //脉冲信号转为电平信号
  14. always@(posedge clk_fast or negedge rst_n)
  15. if(!rst_n)
  16. data_inv <= 1'b0;
  17. else if(data_in)
  18. data_inv <= ~data_inv;
  19. //打拍降低亚稳态
  20. always@(posedge clk_slow or negedge rst_n)
  21. if(!rst_n)begin
  22. data_reg1 <= 1'b0;
  23. data_reg2 <= 1'b0;
  24. data_reg3 <= 1'b0;
  25. end else begin
  26. data_reg1 <= data_inv;
  27. data_reg2 <= data_reg1;
  28. data_reg3 <= data_reg2;
  29. end
  30. //边沿检测
  31. assign dataout = data_reg3^data_reg2;
  32. endmodule

我们在使用这个模块时,无论对于快时钟域到慢时钟域还是慢时钟域到快时钟域,我们都要尽可能让data_inv的高电平持续时间大于等于2个clk_b周期,这样会得到正常的单脉冲输出。

三、多bit跨时钟域处理

1. 多bit DMUX同步器

该方法适合带数据有效标志信号的多bit数据做跨时钟域传输,原理框图如下:

数据有效信号为高电平时,说明此时数据也处于稳定状态,在这种情况下慢时钟域寄存器对信号进行采样,可以保证没有setup/hold违例。当同步过后的data_en作为mux的sel端,当其为1时,将aclk下的data输出给bclk下

对应题目:

在data_en为高期间,data_in将保持不变,data_en为高至少保持3个B时钟周期。表明,当data_en为高时,可将数据进行同步。

本题中data_in端数据变化频率很低,相邻两个数据间的变化,至少间隔10个B时钟周期。

  1. `timescale 1ns/1ns
  2. module mux(
  3. input clk_a ,
  4. input clk_b ,
  5. input arstn ,
  6. input brstn ,
  7. input [3:0] data_in ,
  8. input data_en ,
  9. output reg [3:0] dataout
  10. );
  11. reg data_en_a;
  12. reg data_en_b_reg1;
  13. reg data_en_b_reg2;
  14. reg [3:0] data_reg;
  15. //输入使能寄存
  16. always@(posedge clk_a or negedge arstn)
  17. if(!arstn)
  18. data_en_a <= 0;
  19. else
  20. data_en_a <= data_en;
  21. //使能信号打两拍
  22. always@(posedge clk_b or negedge brstn)
  23. if(!brstn)begin
  24. data_en_b_reg1 <= 'b0;
  25. data_en_b_reg2 <= 'b0;
  26. end else begin
  27. data_en_b_reg1 <= data_en_a;
  28. data_en_b_reg2 <= data_en_b_reg1;
  29. end
  30. //输入数据寄存
  31. always@(posedge clk_a or negedge arstn)
  32. if(!arstn)
  33. data_reg <= 4'd0;
  34. else
  35. data_reg <= data_in;
  36. //输出
  37. always@(posedge clk_b or negedge brstn)
  38. if(!arstn)
  39. dataout <= 0;
  40. else if(data_en_b_reg2)
  41. dataout <= data_reg;
  42. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/861051
推荐阅读
相关标签
  

闽ICP备14008679号