跨时钟域设计(结绳法,脉冲展宽法)

跨时钟域方法总结

https://www.docin.com/p-1715858862.html

异步FIFO

https://blog.csdn.net/darknessdarkness/article/details/104726798

一、结绳法(一)

https://www.cnblogs.com/lyc-seu/p/12441366.html#%E6%96%B9%E6%B3%95%E4%BA%94%EF%BC%9Admux%E5%90%8C%E6%AD%A5%E5%99%A8

参考链接:https://blog.csdn.net/qq_15026001/article/details/100022905?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159549529319725211949682%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159549529319725211949682&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v3-7-100022905.pc_ecpm_v3_pc_rank_v3&utm_term=%E7%BB%93%E7%BB%B3%E6%B3%95&spm=1018.2118.3001.4187

https://blog.csdn.net/qq_21842097/article/details/105540803?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-1-105540803.nonecase

之前参考文章有错误,修改之后电路结果才和仿真对应。

单信号的跨时钟域处理通常有,

  • 两级寄存器串联。
  • 脉冲同步器。
  • 结绳法。
  • 采用握手。

1.数据驱动结绳

利用数据的边沿做时钟,可将脉冲延长,直到采集到数据,然后复位。

这里需要注意的是,clkB域需要等待三个clkB才会在最后一个寄存器输出并完成输入端的复位。所以如果Din_clkA变化较快,即持续时间小于三个clkB(Din_clkA的频率大于clkB的1/3),那么Din_clkA的变化将无法采样到。

该结绳法结构如图

代码:

module data_clk(
									input clk2,
									input rst2,
									input data,
									output pluse_out
								);
								
//-----------------clk1---
reg pluse_reg1;
reg clk2_r1,clk2_r2,clk2_r3;
wire rst1;
assign rst1 = clk2_r3 & ~data;
always @ (posedge data or posedge rst1)
	if(rst1)
		pluse_reg1 <= 1'b0;
	else 
		pluse_reg1 <= 1'b1;
		
always@(posedge clk2 or negedge rst2 )
	if(rst2)
		{clk2_r1,clk2_r2,clk2_r3}<=  3'b000;
	else
		{clk2_r1,clk2_r2,clk2_r3} <= {pluse_reg1,clk2_r1,clk2_r2};
		
assign pluse_out = clk2_r2&&~clk2_r3;

endmodule

测试文件:

`timescale 1ns / 1ps
module txt();
reg clk2;
reg rst2;
reg data;
wire pluse_out;
initial 
begin
    clk2=0;
    rst2 = 1;
      data =0;
   #100;
   rst2= 0;
    // data =0;
   #100 
   data =0;
   #200
   data =1;
   #10
   data =0;
   #200
      data =1;
      #10 
         data =0;
          #80
              data =1;
              #10 
                 data =0;
   
end
always #10 clk2 = ~clk2;
data_clk pluse_data_inst(
									.clk2(clk2),
									.rst2(rst2),
									.data(data),
									.pluse_out(pluse_out)
								);
endmodule

 仿真电路图:

2.脉冲同步器

由于脉冲在快时钟域传递到慢时钟域时,慢时钟有时无法采样的信号,根据奈奎是特采样定理。因此需要对信号进行处理,可以让慢信号采样到。

`timescale 1ns / 1ps
module pluse_sync(
										input src_clk,
										input src_rst_n,
										input s_pluse,
										input des_clk,
										input des_rst_n,
										output des_pluse
									);
									
/*//**********************synchronization req form src***********
reg req;
reg d_req1,d_req2;
always @(posedge des_clk ,negedge des_rst_n)
    if(!des_rst_n)
        {d_req1,d_req2} <=2'b0;
     else
        {d_req1,d_req2} <={req,d_req1};
//**************************************************************
//------------------------------synchronization ack form destination------------
reg ack;
reg d2s_ack1,d2sack2;
always @(posedge src_clk ,negedge src_rst_n)
    if(!src_rst_n)
        {d2s_ack1,d2sack2} <=2'b0;
     else
        {d2s_ack1,d2sack2} <={ack,d2s_ack1};
//*******************************************/
reg src_pluse;
always @ (posedge src_clk or negedge src_rst_n)
	if(!src_rst_n)
		src_pluse <= 1'b0;
	else if(s_pluse)
		src_pluse <= ~src_pluse;
		
reg d_reg1,d_reg2;
always @ (posedge des_clk or negedge des_rst_n)
	if(!des_rst_n)
		{d_reg1,d_reg2} <= 2'b00;
	else
		{d_reg1,d_reg2} <= {src_pluse,d_reg1};

assign des_pluse = (d_reg1 != d_reg2) ? 1'b1:1'b0;

endmodule


`timescale 1ns / 1ps



module tset();
reg src_clk;
reg src_rst_n;
reg s_pluse;
reg des_clk;
reg des_rst_n;
wire des_pluse;
//wire syn_fail;
initial
begin
    src_clk =0;
    des_clk =0;
    src_rst_n=0;
    des_rst_n =0;
    s_pluse =0;
    #40
    src_rst_n=1;
     des_rst_n =1;
    #60
    s_pluse =0;
    
       
    #20
    s_pluse =1;
    #20
    s_pluse =0;
    #140
    s_pluse =1;
    #20
     s_pluse=0;
     #100
      //#20
        s_pluse =1;
        #20
        s_pluse =0;
         #20
           s_pluse =1;
           #20
           s_pluse =0;
end
always #10 src_clk =~src_clk;
always #5 des_clk =~des_clk;

 pluse_sync pluse_sync_inst(
                  .src_clk(src_clk),
                  .src_rst_n(src_rst_n),
                  .s_pluse(s_pluse),
                  .des_clk(des_clk),
                  .des_rst_n(des_rst_n),
                  .des_pluse(des_pluse)
              //    .syn_fail
              );
endmodule

 

二、结绳法(二)

结绳法1这种结绳法的原理是,数据作为时钟,即当数据有上升沿(0->1)时,寄存器1的输出将会稳定在高电平,此时等待clkB采样,当clkB完成采样后,寄存器4会输出高电平,若此时数据为高电平,那么即可完成复位,开始下一次采样等待。这种设计数据来临(即上升沿)时,clkB域需要等待3个clkB才会在寄存器4输出并完成输入端的复位,所以数据如果变化较快即持续时间短于3个clkB,也就是clkA频率大于clkB的1/3,那么这时数据的变化将无法被采样到,因为clkB域需要3个clkB才能完成采样,并且此时数据必须是低电平才能复位,并且复位后的0也要延迟3个clkB才能到达输出端。即这种结绳法慢时钟采样快时钟信号,数据变化至少需要间隔3个慢时钟域的时钟。
输入脉冲需要是单周期脉冲,否则无法进行结绳。


结绳法2又可分为两种电路,在快时钟域->慢时钟域时如果:
                                               fd>=fs∗(fp+1.25)

其中f_p为寄存器级数即源时钟域到目的输出需要的寄存器数量。如果目的时钟满足上面的要求即可以在一个时钟周期内采样到信号。因此可以不需要握手信号,这样可以减少电路设计的延时以及不必要的电路逻辑节省资源。

1.不需要握手信号的结绳法电路结构

代码:

module jieshen_reqnoack(
    input clk1,
    input clk2,
    input rst_1,rst_2,
    input pulse_1,
    output pulse_2
);
reg reg_clk1;
always@(posedge clk1 or negedge rst_1)begin
    if(!rst_1)
     reg_clk1<=0;
     else if(pulse_1)
     reg_clk1<=~reg_clk1;
end


reg reg1_clk2,reg2_clk2,reg3_clk2;
always@(posedge clk2 or negedge rst_2)begin
    if(!rst_2)begin
   {reg3_clk2,reg2_clk2,reg1_clk2}<=3'b000;
    end
    else
    {reg3_clk2,reg2_clk2,reg1_clk2}<={reg2_clk2,reg1_clk2,reg_clk1};
end
assign pulse_2=reg2_clk2 ^ reg3_clk2;
endmodule

测试文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/23 17:03:46
// Design Name: 
// Module Name: tb_jieshen_reqnoack
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_jieshen_reqnoack;
reg clk1,clk2;
reg rst_1,rst_2;
reg pulse_1;
wire pulse_2;
initial
begin
clk1=0;
clk2=0;
pulse_1=0;
rst_1=0;
rst_2=0;
#100 rst_1=1;
rst_2=1;
#400 pulse_1=1;
#100 pulse_1=0;
#600 pulse_1=1;
#100 pulse_1=0;
#600 pulse_1=1;
#100 pulse_1=0;
#600 pulse_1=1;
#100 pulse_1=0;
end
always #50 clk1=~clk1;
always #100 clk2=~clk2;

jieshen_reqnoack u_module(
.clk1(clk1),
.clk2(clk2),
.rst_1(rst_1),
.rst_2(rst_2),
.pulse_1(pulse_1),
.pulse_2(pulse_2)
);
endmodule

仿真波形:

2.握手协议结绳法

结绳法可以解决快时钟向慢时钟过渡的问题,适用范围广,但是实现较为复杂,且效率不高

`timescale 1ns / 1ps

module JS_ReqAck(
										input clk1,clk2,
										input rst1,rst2,//active state H
										input req_clk1,
										output ACK_clk1,
										output pluse
									);
//*************req*****************************
//---------------clk1 domain-------------
//-------------_clk1--------
reg reg_clk1;
always @ (posedge clk1 or posedge rst1)
	if(rst1)
		reg_clk1 <= 1'b0;
	else if(req_clk1)
		reg_clk1 <= ~reg_clk1;
		
//---------------clk2 domain-----------------
reg reg1_clk2,reg2_clk2,reg3_clk2;
always @(posedge clk2 or posedge rst2)	
	if(rst2)
		{reg1_clk2,reg2_clk2,reg3_clk2}	<= 3'b000;
	else
		{reg1_clk2,reg2_clk2,reg3_clk2}	<= {reg_clk1,reg1_clk2,reg2_clk2};
//***********************req end*******************************
//************************ACK*****************************
//---------------clk2 domain-------------
//-------------_clk2--------
reg reg4_clk2;
always @ (posedge clk2 or posedge rst2)
	if(rst2)
		reg4_clk2 <= 1'b0;
	else if(pluse)
		reg4_clk2 <= ~reg4_clk2;
		
//---------------clk1 domain-----------------
reg reg1_clk1,reg2_clk1,reg3_clk1;
always @(posedge clk1 or posedge rst1)	
	if(rst1)
		{reg1_clk1,reg2_clk1,reg3_clk1}	<= 3'b000;
	else
		{reg1_clk1,reg2_clk1,reg3_clk1}	<= {reg4_clk2,reg1_clk1,reg2_clk1};
//------output-------------
assign pluse = reg2_clk2 ^ reg3_clk2;
assign ACK_clk1 =  reg2_clk1 ^ reg3_clk1;
endmodule

测试文件:

`timescale 1ns / 1ps

module text();
reg clk1, clk2;
reg rst1,rst2;
reg req_clk1;
wire pluse;
wire ACK_clk1;
initial 
begin
    clk2=0;
     clk1=0;
   rst2 = 1;
    rst1 = 1;
      req_clk1=0;
   #20;
  rst1= 0;
  #20;
    rst2= 0;
     #130
        req_clk1=0;
   #20
  req_clk1=1;
   #20
   req_clk1=0;
   #200
   req_clk1=1;
   #20
      req_clk1=0;
   #60
      req_clk1=1;
   #20
      req_clk1=0;
   
end
always #10 clk1 = ~clk1;
always #25 clk2 = ~clk2;
JS_ReqAck JS_ReqnoAck(
									.clk1(clk1),
									.rst1(rst1),
									.clk2(clk2),
									.rst2(rst2),
									.req_clk1(req_clk1),
									.pluse(pluse),
									.ACK_clk1(ACK_clk1)
								);
endmodule

 仿真图片

三、脉冲展宽法

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值