같은 clock domain의 level 신호에서 rising edge를 한 cycle pulse로 만들려면 이전 값을 register에 저장하고 현재 값과 비교한다. 비동기 입력은 먼저 destination clock domain으로 동기화하되, 2-FF synchronizer가 모든 CDC 문제를 해결한다고 생각하면 안 된다.
동기 신호의 rising edge 검출
logic signal_d;
logic pulse;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
signal_d <= 1'b0;
pulse <= 1'b0;
end else begin
signal_d <= signal;
pulse <= signal & ~signal_d;
end
end
signal이 0에서 1로 바뀌어 sample되면 pulse는 한 clock 동안 1이 된다. 이전 값 signal_d도 같은 edge에서 갱신되므로 다음 cycle에는 pulse가 다시 0이 된다.
falling edge를 찾을 때는 비교를 ~signal & signal_d로 바꾼다.
비동기 입력은 먼저 동기화
외부 입력처럼 clk와 관계없는 신호를 바로 edge detector에 넣으면 metastability 위험이 있다. 단일 bit level signal이라면 일반적으로 두 단계 synchronizer를 거친 뒤 edge를 검출한다.
logic sync1, sync2, sync2_d;
logic pulse;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sync1 <= 1'b0;
sync2 <= 1'b0;
sync2_d <= 1'b0;
pulse <= 1'b0;
end else begin
sync1 <= async_signal;
sync2 <= sync1;
sync2_d <= sync2;
pulse <= sync2 & ~sync2_d;
end
end
두 단계 synchronizer는 metastability가 다음 단계로 전파될 가능성을 낮추지만 없애지는 않는다. 이 구조는 안정된 단일 bit level을 다른 clock domain으로 넘길 때 쓰며, 여러 bit bus의 각 bit에 독립적으로 붙이는 방법은 값의 일관성을 보장하지 않는다.
source domain의 pulse가 destination clock보다 짧으면 sample되지 않을 수 있다. 짧은 event 전달에는 pulse stretching, toggle synchronizer, handshake 또는 async FIFO처럼 데이터와 event에 맞는 CDC 구조를 선택한다.
확인할 것
- 입력이
clk와 synchronous인지 asynchronous인지 구분한다. - asynchronous 입력이면 edge detector 앞에 synchronizer를 둔다.
- reset 해제 직후 입력이 이미 high일 때 pulse가 나오는 동작이 요구사항에 맞는지 확인한다.
- simulation에서 짧은 pulse와 연속 event가 누락되거나 합쳐지는지 확인한다.
- multi-bit data라면 독립 2-FF 대신 handshake, async FIFO 또는 값의 전이가 안전하게 설계된 encoding을 검토한다.
reset과 구분하기
비동기 reset의 해제 시점을 clock에 맞추는 회로는 일반 signal synchronizer와 목적이 다르다. reset은 reset synchronizer 구성의 별도 기준을 따른다.
공식 자료
원문 기록
- edge detect pulse - 트리거된 이벤트를 알아내 한 클럭 pulse 만들기
- Verilog - Metastable, CDC (clock domain crossing) 정리
- CDC(Clock Domain Crossing) 설계시 반드시 들어가는 synchronizer
한 줄 요약
동기 신호의 이전 값과 현재 값을 비교해 edge pulse를 만들고, asynchronous event는 CDC 방식으로 먼저 안전하게 전달한다.