한 클럭 영역의 enable
100 MHz 기준 클럭으로 동작하는 상태 기계를 100주기마다 한 번 갱신하면 갱신 빈도는 1 MHz입니다. 소비 레지스터는 여전히 같은 100 MHz 클럭을 받으며, enable이 유효한 에지에서만 값을 바꿉니다. 이는 새 1 MHz 클럭으로 레지스터를 구동하는 것과 다릅니다.
값을 유지해야 하는 동기 조건문은 clock enable로 합성될 수 있습니다. 그러나 enable을 썼다고 클럭 배선의 스위칭 자체가 멈추는 것은 아닙니다. AMD UG949의 Creating Clock Enables는 불필요한 enable이 control set 수를 늘릴 수 있고, 큰 레지스터 묶음에서는 전력 측면의 이점이 있을 수 있음을 구분합니다. 면적·전력·타이밍 개선을 일괄 보장하지 않습니다.
생성 에지와 소비 에지
다음 JavaScript 모델은 등록된 enable과 소비 상태의 에지 전·후 값을 나눕니다. 동일한 상승 에지의 nonblocking assignment들이 이전 값을 읽는 상황을 설명하기 위한 수치·에지 참고 모델이며, 실행 가능한 RTL 또는 HDL 시뮬레이터 출력은 아닙니다. 정수 N≥2, 초기 상태 {count: 0, enable: false, updates: 0}, reset이 첫 에지 전에 해제된 조건입니다.
function tick(old, n) {
return {
count: old.count === n - 1 ? 0 : old.count + 1,
enable: old.count === n - 1,
updates: old.updates + (old.enable ? 1 : 0)
};
}
N=4라면 에지 4 직전에 count=3입니다. 그 에지 뒤에 enable=1이 되지만, 소비 레지스터는 에지 4에서 아직 이전 enable=0을 봅니다. 첫 갱신은 에지 5이고 이후 에지 9, 13으로 이어집니다. 주기는 4로 같아도 시작 위상은 생성 이벤트보다 한 주기 늦습니다. 조합 비교식을 같은 에지에서 직접 소비하는 다른 설계와 이 파형을 혼용하지 않습니다.
| 에지 | count | enable | 누적 소비 갱신 |
|---|---|---|---|
| 1 | 1 | 0 | 0 |
| 2 | 2 | 0 | 0 |
| 3 | 3 | 0 | 0 |
| 4 | 0 | 1 | 0 |
| 5 | 1 | 0 | 1 |
| 8 | 0 | 1 | 1 |
| 9 | 1 | 0 | 2 |
enable의 빈도만 보고 모든 데이터 경로에 N주기 multicycle 예외를 주면 안 됩니다. 실제 launch·capture 조건과 setup·hold 관계가 먼저 입증되어야 합니다. 예외가 없다면 같은 기준 클럭의 일반 타이밍 요구가 그대로 적용됩니다.
누산기 overflow는 평균율을 만든다
W비트 위상 누산기의 법을 M=2^W라 하고, 매 주기 정수 STEP을 더합니다. 합이 M 이상이면 이벤트를 하나 만들고 M을 뺍니다. 초기 누산값 0, 0 < STEP < M이면 t주기까지 발생한 이벤트 수는 floor(t × STEP / M)입니다. 따라서 장기 평균 이벤트율은 f_clk × STEP / M이며, 각 이벤트 간격은 정수 클럭 수입니다.
function advance(acc, step, modulus) {
const sum = acc + step;
const event = sum >= modulus;
return {acc: event ? sum - modulus : sum, event};
}
W=16, STEP=0x517d=20861이면 비율은 20861/65536=0.3183135986328125, 평균 간격은 약 3.1415560136주기입니다. 실제 간격은 3 또는 4주기입니다. 100 MHz 기준이면 장기 평균은 약 31.83136 MHz지만, 등간격의 그 주파수 클럭이 만들어지는 것은 아닙니다.
| 검사 범위 | 이벤트 수 | 마지막 누산값 | 이벤트 간격 |
|---|---|---|---|
| 65,536주기 | 20,861 | 0 | 3 또는 4주기 |
| 1,000,000주기 | 318,313 | 39,232 | 3 또는 4주기 |
짧은 구간의 이벤트 수는 바닥 함수 때문에 장기 평균과 정확히 같지 않습니다. 이 예시의 처음 이벤트는 에지 4이며, 발생한 event를 레지스터에 저장하고 다른 레지스터가 소비한다면 앞 절처럼 소비는 한 에지 늦습니다. 초기 누산값이나 reset 시점을 바꾸면 위상도 바뀝니다.
STEP이 M/2보다 크면 연속된 주기에서 event가 1일 수도 있습니다. 이때는 매 기준 클럭 에지의 enable 값으로 사건을 세어야 하며, event 신호의 상승 에지만 세면 사건을 놓칩니다. 단일 주기 이벤트라는 말이 항상 사이에 0이 있는 고립 펄스를 뜻하지는 않습니다. STEP=0과 STEP≥M은 여기서 정한 계약 밖입니다.
3·4주기의 간격 변동은 이산 주기 양자화의 결과입니다. 평균율만 맞춘 이 신호를 ADC용 저지터 샘플 클럭이나 외부 인터페이스 클럭으로 간주하지 않습니다. 필요한 주기 변동, duty cycle, 위상 관계를 따로 명세해야 합니다.
실제 클럭이 필요한 경우
카운터 비트를 다른 레지스터의 clock 핀에 연결하면 그 비트는 실제 분주 클럭입니다. UG949의 local clock 설명은 fabric 카운터 분주를 일반 fabric 배선에 놓이는 클럭의 원인 중 하나로 들고 skew·배선·타이밍 수렴 문제를 설명합니다. 실제 구현이 전용 버퍼를 사용하는지 보고서로 확인해야 합니다.
분주 도메인과 원래 클럭 사이에 고정 관계가 있다고 해서 데이터 전달 분석이 없어지지는 않습니다. 반대로 둘을 무조건 비동기 도메인이라고 단정하지도 않습니다. generated-clock 정의, 원 클럭과의 에지 관계, 경로 제약과 실제 CDC 요구를 구분합니다.
별도 클럭이 필요하면 대상 제품의 PLL/MMCM, 전용 분주·클럭 버퍼와 해당 연결 제약을 검토합니다. UG949 Clock Primitives의 자원 이름·가용 수는 해당 제품군의 설명이지 모든 FPGA의 공통 보장값이 아닙니다. enable fanout·control set·clock utilization·setup/hold 결과까지 확인한 뒤 구현을 판단합니다.
검증 범위
본문 코드의 N=4 에지표, N=100 갱신 간격, 누산기 100만 주기의 사건 수·나머지·3/4 간격을 자동 검사했습니다. 이 검사는 JavaScript 정수·에지 모델이며 실제 RTL 시뮬레이션, FPGA 합성·타이밍 분석, 클럭 지터·전력·보드 측정은 수행하지 않았습니다. 소프트웨어 모델을 통과했다고 해서 timing closure가 된 것은 아닙니다.
English summary (not a full translation)
A registered enable and its consumer use pre-edge state. In the divide-by-four model, enable becomes high after edge four and the consumer first updates at edge five. An accumulator gives an average event rate, not an evenly spaced low-jitter clock. Count enabled reference-clock edges, not event rising edges when adjacent events are possible. A real generated clock needs device-specific routing, constraints and domain analysis. Tests cover a numerical edge model only.
근거
- ZipCPU, Controlling Timing within an FPGA, 2017-06-02. enable·누산기 주제의 출발점이며 원문 RTL을 복제하지 않았습니다.
- AMD Avoiding Local Clocks, Creating Clock Enables, Clock Primitives, UG949 2026.1, 2026-06-23 발행본을 대조했습니다.