들어가며
이 페이지에서는 소스 동기식(source-synchronous) 데이터 출력을 다룹니다. 이 기법은 데이터 출력이, FPGA 가 이 출력들과 함께 생성하는 클록에 동기화되는 방식을 말합니다.
외부 부품과의 인터페이스가 FPGA 의 출력 포트로만 이루어져 있다면 이 방식이 당연한 선택입니다. I/O 가 양방향인 경우에도 이 방식은 적합하며, 이에 대해서는 이 페이지 맨 아래에서 설명합니다. 클록과 데이터의 관계 전반은 별도 페이지에서 다룹니다.
기본적인 응용
다음 Verilog 예제를 살펴보겠습니다.
module top (
input clk,
output reg [7:0] data_out,
output reg sync_clk_out
);
always @(posedge clk)
begin
sync_clk_out <= !sync_clk_out;
if (sync_clk_out)
data_out <= data_out + 1;
end
endmodule
여기서 주의할 점은 @data_out 의 값이 @sync_clk_out 의 하강 에지와 동시에 바뀐다는 것입니다. @sync_clk_out 가 low 이면 @data_out 은 변하지 않고, @sync_clk_out 가 high 이면 @clk 의 상승 에지에 맞춰 @data_out 이 새 값으로 바뀝니다.
@data_out 과 @sync_clk_out 모두에 IOB 레지스터를 사용하면, 이 출력 신호들은 모두 실질적으로 같은 시각에 값을 바꿉니다. 따라서 이 신호들을 받는 외부 부품은 @sync_clk_out 을 자기 클록으로 사용할 수 있습니다. 이렇게 하면 외부 부품의 타이밍 요구사항을 충족하기가 대체로 쉽습니다. 단, @data_out 의 샘플링(sampling)이 @sync_clk_out 의 상승 에지와 동기화되어 있다고 가정할 때입니다.
DDR 레지스터 사용
위 예제에는 중요한 단점이 있습니다. @sync_clk_out 의 주파수가 @clk 주파수의 절반이라는 점입니다. 따라서 @data_out 의 데이터 전송 속도도 @clk 주파수의 절반으로 제한됩니다. 예외는 외부 부품이 @sync_clk_out 의 양쪽 클록 에지에 모두 반응하는 경우, 즉 DDR 입력을 갖는 경우뿐입니다. 그러나 대개는 그렇지 않습니다.
데이터 출력과 정렬된 출력 클록을 만들어 내기 위해 출력 DDR 레지스터를 사용할 수 있습니다. 아이디어는 양쪽 클록 에지에서 값을 바꾸는 플립플롭을 사용하는 것입니다. 즉, 이런 플립플롭은 다음과 같이 동작합니다.
always @(posedge clk or negedge clk)
if (clk)
sync_clk_out <= 0;
else
sync_clk_out <= 1;
@sync_clk_out 은 @clk 의 상승 에지에 반응하여 low 로 바뀌고, 하강 에지에 반응하여 그 반대가 됩니다. 그 결과 출력 클록은 @clk 와 같은 주파수를 갖게 됩니다.
하지만 이 Verilog 코드는 대부분의 합성 도구(synthesizer)에서는 동작하지 않습니다. 로직 패브릭 안의 플립플롭은 보통 양쪽 클록 에지에 모두 반응하도록 만들 수 없기 때문입니다. 이 기능을 갖는 것은 IOB 레지스터뿐인데, 합성 도구가 그런 가능성을 스스로 알아낼 만큼 영리한 경우는 드뭅니다.
따라서 논리 프리미티브(primitive)의 인스턴스화(instantiation)가 필요합니다. 프리미티브는 사용하는 FPGA 에 따라 다릅니다. 아래 예는 Kintex Ultrascale 에서 이 작업을 수행하는 방법을 보여 줍니다.
ODDRE1 ODDR_ins
(.C(clk), .Q(sync_clk_out),
.D1(1'b0), .D2(1'b1),
.SR(1'b0));
하지만 이제 클록은 출력 DDR 레지스터로 생성되고 데이터 신호는 일반 IOB 레지스터로 생성되므로, 데이터와 클록 사이의 정렬이 앞선 경우처럼 명확하지 않습니다. 따라서 모든 출력에 대한 타이밍 리포트를 읽고, 지연 간 차이가 충분히 작은지 확인하는 것이 중요합니다.
데이터 출력에도 출력 DDR 레지스터를 사용할 수 있습니다. D1 과 D2 에 같은 값을 넣으면 출력은 클록 한 주기마다 한 번씩만 바뀝니다.
module top (
input clk,
output [7:0] data_out,
output sync_clk_out
);
reg [7:0] data;
ODDRE1 ODDR_ins
(.C(clk), .Q(sync_clk_out),
.D1(1'b0), .D2(1'b1),
.SR(1'b0));
ODDRE1 ODDR_data_ins [7:0]
(.C(clk), .Q(data_out),
.D1(data), .D2(data),
.SR(1'b0));
always @(posedge clk)
data <= data + 1;
endmodule
이 방법을 쓰면 데이터와 클록의 정렬이 보장됩니다. 또한 출력 DDR 레지스터를 명시적으로 인스턴스화했기 때문에 IOB 레지스터가 사용된다는 것도 보장됩니다. 이 방법의 유일한 단점은 FPGA 제품군마다 코드가 다르다는 점입니다.
출력 DDR 레지스터의 동작은 예상 밖일 수 있고 혼란스러울 수도 있으니 주의해야 합니다. 예를 들어 @data 는 @clk 의 상승 에지에 동기화되지만, ODDRE1 은 양쪽 클록 에지에서 모두 동작합니다. 두 데이터 입력이 언제, 어떻게 샘플링되는지는 사용하는 FPGA 의 문서를 반드시 확인하기 바랍니다.
또한 이 예제에서는 리셋을 사용하지 않았습니다. 특히 정교한 FPGA 의 경우 이것은 안전하지 않을 수 있습니다. 출력 DDR 레지스터가 IOB 내부의 더 복잡한 논리 요소에 포함되어 있을 수 있기 때문입니다. 그런 논리 요소는 리셋 없이는 제대로 동작하지 않을 수 있습니다.
타이밍 제약 조건
그렇다면 이 방법에도 타이밍 제약 조건(timing constraints)이 꼭 필요할까요? IOB 레지스터 덕분에 클록 출력과 데이터 출력이 거의 완벽하게 정렬되는데, 그것만으로는 부족한 것일까요?
대답은, 타이밍 제약 조건이 없어도 이 방법이 아주 잘 동작할 수 있다는 것입니다. 그럼에도 불구하고 타이밍 제약 조건을 활용하는 것이 좋습니다. 그 이유는 IOB 레지스터 페이지에서 설명한 것과 같습니다.
기타 고려 사항
하지만 IOB 레지스터 사용만이 유일한 관건은 아닙니다. 출력 포트들이 물리적으로 서로 가까이 배치되어야 한다는 점에도 주의하십시오. 출력 포트들이 서로 멀리 떨어져 있으면, 이 물리적 거리가 FPGA 내부의 클록 스큐(clock skew)에 나쁜 영향을 줄 수 있습니다. PCB 의 배선(트레이스) 길이 차이도 부정적인 영향을 줄 수 있습니다. 또한 전압, I/O 표준, 슬루율(slew rate), 구동 전류 등 전기적 파라미터도 모든 출력에서 동일해야 합니다.
FPGA 에 IOB 레지스터가 없다면 타이밍 제약 조건이 훨씬 중요해집니다. 소스 동기식 출력을 사용할 때의 기본 전제는 관련된 모든 출력 포트 사이에서 낮은 스큐를 보장할 수 있어야 한다는 것입니다. 보통 플립플롭과 I/O 핀 사이의 지연을 조절하는 것만으로 충분합니다. 이 지연이 해당 FPGA 에서 가능한 최솟값에 가깝게 유지된다면, 출력 간 차이는 대부분의 용도에 충분할 만큼 작아지기 때문입니다.
양방향 I/O
소스 동기식 출력의 핵심적인 특징은 관련 클록을 FPGA 가 생성한다는 것입니다. 모든 데이터 신호가 외부 부품 방향으로 나가는 경우라면 당연히 적합합니다. 하지만 데이터 신호가 양방향으로 존재하는 경우에도 FPGA 가 생성한 클록에 의존하는 것이 합리적일 수 있습니다.
그러나 데이터 입력은 FPGA 칩 내부의 클록이 아니라 PCB 상의 클록에 동기화된다는 점에 유의하십시오. 물론 두 클록의 주파수는 정확히 같습니다. 하지만 출력 포트의 클록-출력 지연(clock-to-output delay)에 따라 차이가 생길 수 있으며, 이 차이는 수 나노초에 이를 수 있습니다.
따라서 PCB 에 루프백(loopback)을 구성하는 것이 좋습니다. FPGA 의 클록 출력을 입력 포트에 연결하는 것입니다. 이 입력 포트는 마치 시스템 동기 클록(system synchronous clock)인 것처럼 취급할 수 있습니다. 그러면 외부 부품은 자신의 클록이 FPGA 가 아니라 전용 오실레이터에서 나온 것처럼 동작합니다. FPGA 와 외부 부품이 PCB 상의 동일한 물리적 신호에 의존하기 때문에, 이것은 시스템 동기 클록과 유사한 상황입니다.
데이터 입력을 소스 동기식 입력(source-synchronous inputs)으로 취급할 수도 있습니다. 특히 위상 이동(phase shifting) 기법을 사용한다면 클록 루프백이 필요 없습니다. 실제로 이것은 DDR SDRAM 메모리와 인터페이스할 때 일반적인 방법입니다.
중요한 결론은 PCB 제작 전에 입력 신호의 타이밍을 신중하게 계획하고, 필요하다면 클록 루프백을 추가하는 방안을 검토하라는 것입니다.

