Skip to content
DevBJ
Go back

SystemVerilog에서 rising edge를 한 clock pulse로 만들기

Updated:
Editor

같은 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 구조를 선택한다.

확인할 것

  1. 입력이 clk와 synchronous인지 asynchronous인지 구분한다.
  2. asynchronous 입력이면 edge detector 앞에 synchronizer를 둔다.
  3. reset 해제 직후 입력이 이미 high일 때 pulse가 나오는 동작이 요구사항에 맞는지 확인한다.
  4. simulation에서 짧은 pulse와 연속 event가 누락되거나 합쳐지는지 확인한다.
  5. multi-bit data라면 독립 2-FF 대신 handshake, async FIFO 또는 값의 전이가 안전하게 설계된 encoding을 검토한다.

reset과 구분하기

비동기 reset의 해제 시점을 clock에 맞추는 회로는 일반 signal synchronizer와 목적이 다르다. reset은 reset synchronizer 구성의 별도 기준을 따른다.

공식 자료

원문 기록

한 줄 요약

동기 신호의 이전 값과 현재 값을 비교해 edge pulse를 만들고, asynchronous event는 CDC 방식으로 먼저 안전하게 전달한다.


Share this post on:

Previous Post
Verilog와 SystemVerilog filelist를 find로 만드는 방법
Next Post
Tcl 명령을 여러 줄로 나눠 작성하는 방법