赞
踩
用途:一般用在AB两个时钟关系不确定的时候,可能是快到慢,也可能是慢到快;
基本原理:双方电路在声明或终止各自的握手信号信号前都要等待对方的相应。完整的同步过程(A→B)可有以下4个步骤:
请求信号的产生:当同步器处于空闲状态时,在输入脉冲到来时,A声明它的请求信号sync_reg;
请求信号的跨越与应答信号的产生:sync_reg信号需要跨时钟域同步到B,与此同时,B产生同步脉冲,并产生应答信号sync_ack,此时,已经给出了要输出的脉冲
应答信号的跨越与请求信号的清除:sync_ack信号跨时钟域同步到A,与此同时,A清除之前产生的sync_reg;
应答信号的清除:在sync_reg信号清除之后,B清除sync_ack信号。此时,一次信号的跨时钟域完成,等待同步下一个脉冲。
缺点:延时大
握手代码
- `timescale 1ns / 1ps
- //
- // Company:
- // Engineer:
- //
- // Create Date: 2021/01/11 16:35:34
- // Design Name:
- // Module Name: top
- // Project Name:
- // Target Devices:
- // Tool Versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.01 - File Created
- // Additional Comments:
- //
- //
-
-
- module top(
- input wire din,
- input wire clk_A,
- input wire rst_n_A,
- input wire clk_B,
- input wire rst_n_B,
-
- output wire sync_idle, //给出同步器是否空闲的信号
- output reg sync_fail, //同步失败:位于原时钟域
-
- output wire dout
- );
-
- reg src_sync_req; //原时钟产生同步请求
- reg req_state_dly1;
- reg req_state_dly2; //同步器的输出
- reg req_state_dly3; //目的时钟延后信号,以保证脉冲输出
-
- reg dst_sync_ack; //目的时钟产生应答
- reg ack_state_dly1;
- reg ack_state_dly2; //同步器的输出
- wire src_sync_ack; //原时钟接收应答
-
-
- //同步器空闲状态的判断:原时钟下:请求和应答信号同时无效
- assign sync_idle = ~(src_sync_req | src_sync_ack );
-
- //同步失败的判断
- always @(posedge clk_A or negedge rst_n_A)
- begin
- if(rst_n_A == 1'b0)
- sync_fail <= 1'b0;
- else if(din & (~sync_idle)) //源时钟脉冲到来,此时同步器不空闲,给出同步失败
- sync_fail <= 1'b1;
- else
- sync_fail <= 1'b0;
- end
-
- //原时钟产生请求信号,请求信号的产生相当于将脉冲转化为了电平
- always @(posedge clk_A or negedge rst_n_A)
- begin
- if(rst_n_A == 1'b0)
- src_sync_req <= 1'b0;
- else if(din & sync_idle) //源时钟脉冲到来,且源时钟空闲,传递请求。同时完成了脉冲转电平
- src_sync_req <= 1'b1;
- else if(src_sync_ack) //检测到应答以后,清除请求
- src_sync_req <= 1'b0;
- end
-
- //同步原时钟请求信号到目的时钟,利用请求信号跨时钟域
- always @(posedge clk_B or negedge rst_n_B)
- begin
- if(rst_n_B == 1'b0)
- begin
- req_state_dly1 <= 1'b0;
- req_state_dly2 <= 1'b0;
- req_state_dly3 <= 1'b0;
- end
- else
- begin
- req_state_dly1 <= src_sync_req;
- req_state_dly2 <= req_state_dly1; //打两拍结束
- req_state_dly3 <= req_state_dly2; //再外接一个寄存器,以保证脉冲输出
- end
- end
-
- //上升沿检测,产生输出脉冲
- assign dout = (~req_state_dly3) & req_state_dly2; //完成输出脉冲
-
- //目的时钟产生应答信号
- always @(posedge clk_B or negedge rst_n_B)
- begin
- if(rst_n_B == 1'b0)
- dst_sync_ack <= 1'b0;
- else if (req_state_dly2) //同步高电平已到达
- dst_sync_ack <= 1'b1;
- else begin
- dst_sync_ack <= 1'b0;
- end
-
- end
-
- //同步目的时钟产生的应答信号到原时钟
- always @(posedge clk_A or negedge rst_n_A)
- begin
- if(rst_n_A == 1'b0)
- begin
- ack_state_dly1 <= 1'b0;
- ack_state_dly2 <= 1'b0;
- end
- else
- begin
- ack_state_dly1 <= dst_sync_ack;
- ack_state_dly2 <= ack_state_dly1;
- end
- end
- assign src_sync_ack = ack_state_dly2;
-
- endmodule

测试代码:
-
- `timescale 1ns/1ns
-
-
- module top_tb;
-
- reg clk_A;
- reg clk_B;
- reg rst_n;
- wire clk_write;
- reg din;
- initial begin
- clk_A=1;
- clk_B=1;
- end
-
- always #20 clk_A=~clk_A; //50
- always #40 clk_B=~clk_B; //25
-
-
- initial begin
- rst_n=0;
- #10
- rst_n=1;
- end
-
-
-
- assign clk_write = clk_A&rst_n; //复位期间不应写入数据
- reg [31:0] cnt;
- always@(posedge clk_write or negedge rst_n) begin
- if(rst_n==1'b0) begin
- cnt <= 32'd0;
- end
- else begin
- cnt <=cnt + 1;
- end
- end
-
- always@(posedge clk_write or negedge rst_n) begin
- if(rst_n==1'b0) begin
- din <= 32'd0;
- end
- else if(cnt==10) begin
- din <=1;
- end
- else begin
- din <=0;
- end
- end
-
-
- top top_inst(
- .din (din),
- .clk_A (clk_A),
- .rst_n_A (rst_n),
- .clk_B (clk_B),
- .rst_n_B (rst_n)
-
-
- );
-
-
-
-
- endmodule

原文链接:https://blog.csdn.net/u013668469/article/details/99643154
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。