Altifigence Academy

50 / 52 · 概念

A stallable arithmetic pipeline

단계별 ready를 계산해 정지와 동시 이동 중에도 데이터의 손실·중복·재계산을 방지합니다.

尚無譯文,以下顯示課程原文。 (한국어)

수신 측이 매번 받을 수 없다면

선수 지식: 1칸 ready/valid 버퍼와 파이프라인의 데이터 정렬.

고정 속도 파이프라인에 out_ready만 추가해서 출력을 막아서는 부족합니다. 마지막 단계가 가득 차서 멈추면 앞 단계도 덮어쓰면 안 됩니다. 정지 요청이 입력 방향으로 전달되는 backpressure를 설계해야 합니다.

두 단계를 각각 데이터 한 개와 valid 한 비트로 표현하겠습니다. 2단계는 비어 있거나 현재 출력을 내보낼 수 있을 때 새 값을 받을 수 있습니다. 1단계에도 같은 규칙을 적용합니다.

r2=¬v2out_ready,r1=¬v1r2r_2=\neg v_2\lor\mathrm{out\_ready},\qquad r_1=\neg v_1\lor r_2

외부 in_ready는 r1입니다. r2=0이라도 1단계가 비어 있다면 새 입력 한 개를 받을 수 있습니다. ‘출력이 멈추면 모든 입력을 무조건 거부’하는 것보다 저장 공간을 잘 활용합니다.

각 단계는 이동 허가가 있을 때만 갱신합니다

아래 예제는 unsigned 8비트 x에 대해 y=2(x+1)을 계산합니다. 1단계는 x+1을 9비트로 저장하고, 2단계는 10비트로 한 비트 왼쪽 이동합니다. 최대 입력 255의 결과 512까지 정확하게 표현합니다.

SystemVerilog
module stallable_pipeline (
    input  logic       clk, rst,
    input  logic       in_valid,
    output logic       in_ready,
    input  logic [7:0] in_data,
    output logic       out_valid,
    input  logic       out_ready,
    output logic [9:0] out_data
);
    logic v1, v2, r1, r2;
    logic [8:0] d1;
    logic [9:0] d2;
    assign r2 = !v2 || out_ready;
    assign r1 = !v1 || r2;
    assign in_ready  = r1;
    assign out_valid = v2;
    assign out_data  = d2;

    always_ff @(posedge clk) begin
        if (rst) begin
            v1 <= 1'b0;
            v2 <= 1'b0;
        end else begin
            if (r2) begin
                v2 <= v1;
                if (v1) d2 <= {d1, 1'b0};
            end
            if (r1) begin
                v1 <= in_valid;
                if (in_valid) d1 <= {1'b0, in_data} + 9'd1;
            end
        end
    end
endmodule

nonblocking 대입이므로 2단계는 같은 에지에 새로 계산한 d1이 아니라 이전 d1을 받습니다. r1=0이면 v1·d1이 유지되고, r2=0이면 v2·d2가 유지됩니다. valid만 유지하고 데이터는 계속 갱신하는 구현은 잘못입니다.

두 단계가 모두 찼을 때의 추적

처음 v2에 A의 결과, v1에 B의 중간값이 있고 입력 C가 대기한다고 합시다.

out_readyin_ready에지에서의 동작
00A·B 유지, C 미수락
00A·B 유지, C 미수락
11A 전달, B가 2단계로 이동, C 수락

송신자는 C를 수락받을 때까지 C와 in_valid를 유지합니다. 첫 정지 에지에서 C를 보냈다고 생각하고 다음 데이터를 내면 C가 사라집니다.

각 열은 상승 에지 직전 값입니다. 시작할 때 마지막 단계에 A, 첫 단계에 B가 있으며 C가 입력에서 대기합니다. E2에서 A를 전달하고 C를 수락한 뒤, E3 직전 출력은 B로 바뀝니다.

두 단계가 모두 찬 상태의 backpressure
View waveform data
Wave data: each character is one interval; a dot holds the previous state; p is a clock cycle.
SignalWaveBus values
edge2345E0 → E1 → E2 → E3
out_ready0.1.
out_valid1...
out_data2..3A → B
in_valid1...
in_ready0.1.
in_data2..3C → D

검증할 보존 법칙

리셋 이후 입력 수락 수를 Nin, 출력 전달 수를 Nout이라고 하면 저장량은 다음과 같습니다. reset 에지에서는 전송을 세지 않습니다.

NinNout=v1+v2,0NinNout2N_{\mathrm{in}}-N_{\mathrm{out}}=v_1+v_2,\qquad 0\le N_{\mathrm{in}}-N_{\mathrm{out}}\le2

카운트만 맞아도 A를 두 번 내보내고 B를 버린 오류를 놓칠 수 있으므로, 참조 큐에서 값과 순서도 검사합니다. 입력 valid와 출력 ready를 독립적으로 변하게 하고, 장시간 정지·연속 처리·리셋 도중 비우기를 포함하세요.

ready 경로도 타이밍 경로입니다

단계를 길게 연결하면 r2→r1 같은 역방향 조합 경로도 길어집니다. 레지스터 하나로 ready를 지연시키면 그 지연 동안 이미 약속한 입력을 보관할 추가 공간이 필요할 수 있습니다. 저장 공간과 프로토콜을 고려하지 않고 ready에 플립플롭만 넣는 것은 안전한 타이밍 최적화가 아닙니다.

自己試試看

v1=0, v2=1이고 out_ready=0입니다. in_valid=1인 입력을 받을 수 있습니까? 그 다음 사이클에도 out_ready=0이면 추가 입력을 계속 받을 수 있습니까?

查看解說

처음 r2=0이지만 r1=1이므로 한 개를 받아 1단계를 채울 수 있습니다. 에지 이후 v1=v2=1이면 r1=r2=0이므로 더 이상 받지 못합니다. 이 차이가 두 칸 저장 공간을 실제로 활용하는 조건입니다.

此選擇適用於本瀏覽器,隨時可從頁尾變更。