標籤:情況 form 電路設計 creat project name module use fail
一、前言
上一篇文章中已經描述了簡單的脈衝同步器,它可以實現簡單應用情境下的同步功能,同時也存在不少應用限制或缺陷,例如:
(1) 對src_clk域dst_clk關係較為敏感,當src_clk與dst_clk時鐘頻率差別很大時可能不適應;
(2) 由於沒有完整的握手機制,當多個src_pulse之間間隔較短時,可能存在脈衝同步丟失情況。
(3) 當dst_clk時鐘域出現無時鐘或複位時,src_clk時鐘域將丟失。
本文將對該同步器進行改進以滿足更多非同步脈衝同步情境。
二、原理
回顧上一篇文章中的同步器的基本設計原理:
(1)源時鐘域脈衝轉換為源時鐘域電平訊號;
(2)對單bit電平訊號進行打拍的非同步處理;
(3)在目的時鐘域中進行脈衝還原。
從以上設計原理中,我們可以發現該同步器的控制傳遞是單向的,即僅從源時鐘域到目的時鐘域,目的時鐘域並沒有狀態反饋。假設存在如下應用:
(1) 源時鐘域中的第一個脈衝和第二個脈衝間隔過短,第一個脈衝未完成同步,第二脈衝又將狀態清空,導致最終脈衝同步丟失。
要解決以上同步問題,需要引入非同步握手機制,保證每個脈衝都同步成功,同步成功後再進行下一個脈衝同步。握手原理如下:
sync_req: 源時鐘域同步請求訊號,高電平表示當前脈衝需要同步;
sync_ack: 目的時鐘域應答訊號,高電平表示當前已收到同步請求;
完整同步過程分為以下4個步驟:
(1) 同步請求產生;當同步器處於空閑(即上一次已同步完成)時,源同步脈衝到達時產生同步請求訊號sync_req;
(2) 同步請求訊號sync_req同步到目的時鐘域,目的時鐘域產生脈衝訊號並將產生應答訊號sync_ack;
(3) 同步應答訊號sync_ack同步到源時鐘域,源時鐘域檢測到同步應答訊號sync_ack後,清除同步請求訊號;
(4) 目的時鐘域檢測到sync_req撤銷後,清除sync_ack應答;源時鐘域將到sync_ack清除後,認為一次同步完成,可以同步下一個脈衝。
三、代碼
//--====================================================================================--// THIS FILE IS PROVIDED IN SOURCE FORM FOR FREE EVALUATION, FOR EDUCATIONAL USE OR FOR // PEACEFUL RESEARCH. DO NOT USE IT IN A COMMERCIAL PRODUCT . IF YOU PLAN ON USING THIS // CODE IN A COMMERCIAL PRODUCT, PLEASE CONTACT [email protected] TO PROPERLY LICENSE // ITS USE IN YOUR PRODUCT. // // Project : Verilog Common Module// File Name : handshake_pulse_sync.v// Creator(s) : [email protected]// Date : 2015/12/01// Description : A handshake pulse sync //// Modification :// (1) Initial design 2015-12-01//////--====================================================================================--module HANDSHAKE_PULSE_SYNC ( src_clk , //source clock src_rst_n , //source clock reset (0: reset) src_pulse , //source clock pulse in src_sync_fail , //source clock sync state: 1 clock pulse if sync fail. dst_clk , //destination clock dst_rst_n , //destination clock reset (0:reset) dst_pulse //destination pulse out ); //PARA DECLARATION//INPUT DECLARATIONinput src_clk ; //source clock input src_rst_n ; //source clock reset (0: reset)input src_pulse ; //source clock pulse ininput dst_clk ; //destination clock input dst_rst_n ; //destination clock reset (0:reset)//OUTPUT DECLARATIONoutput src_sync_fail ; //source clock sync state: 1 clock pulse if sync fail.output dst_pulse ; //destination pulse out//INTER DECLARATIONwire dst_pulse ;wire src_sync_idle ;reg src_sync_fail ;reg src_sync_req ;reg src_sync_ack ;reg ack_state_dly1 ;reg ack_state_dly2 ;reg req_state_dly1 ;reg req_state_dly2 ;reg dst_req_state ;reg dst_sync_ack ;//--========================MODULE SOURCE CODE==========================--//--=========================================--// DST Clock :// 1. generate src_sync_fail; // 2. generate sync req // 3. sync dst_sync_ack//--=========================================--assign src_sync_idle = ~(src_sync_req | src_sync_ack );//report an error if src_pulse when sync busy ;always @(posedge src_clk or negedge src_rst_n)begin if(src_rst_n == 1‘b0) src_sync_fail <= 1‘b0 ; else if (src_pulse & (~src_sync_idle)) src_sync_fail <= 1‘b1 ; else src_sync_fail <= 1‘b0 ;end//set sync req if src_pulse when sync idle ;always @(posedge src_clk or negedge src_rst_n)begin if(src_rst_n == 1‘b0) src_sync_req <= 1‘b0 ; else if (src_pulse & src_sync_idle) src_sync_req <= 1‘b1 ; else if (src_sync_ack) src_sync_req <= 1‘b0 ;endalways @(posedge src_clk or negedge src_rst_n)begin if(src_rst_n == 1‘b0) begin ack_state_dly1 <= 1‘b0 ; ack_state_dly2 <= 1‘b0 ; src_sync_ack <= 1‘b0 ; end else begin ack_state_dly1 <= dst_sync_ack ; ack_state_dly2 <= ack_state_dly1 ; src_sync_ack <= ack_state_dly2 ; end end//--=========================================--// DST Clock :// 1. sync src sync req // 2. generate dst pulse// 3. generate sync ack//--=========================================--always @(posedge dst_clk or negedge dst_rst_n)begin if(dst_rst_n == 1‘b0) begin req_state_dly1 <= 1‘b0 ; req_state_dly2 <= 1‘b0 ; dst_req_state <= 1‘b0 ; end else begin req_state_dly1 <= src_sync_req ; req_state_dly2 <= req_state_dly1 ; dst_req_state <= req_state_dly2 ; endend//Rising Edge of dst_state generate a dst_pulse;assign dst_pulse = (~dst_req_state) & req_state_dly2 ; //set sync ack when src_req = 1 , clear it when src_req = 0 ;always @(posedge dst_clk or negedge dst_rst_n)begin if(dst_rst_n == 1‘b0) dst_sync_ack <= 1‘b0; else if (req_state_dly2) dst_sync_ack <= 1‘b1; else dst_sync_ack <= 1‘b0;endendmodule
四、模擬
(1) 當目的時鐘域dst_rst_n複位時,脈衝不丟失;
(2) 正常同步情況;
(3) 源脈衝頻率過高情況;
【設計開發】 典型非同步電路設計-脈衝同步(2)