50 / 52 · अवधारणा
A stallable arithmetic pipeline
단계별 ready를 계산해 정지와 동시 이동 중에도 데이터의 손실·중복·재계산을 방지합니다.
पाठ पढ़ना मुफ़्त है। प्रगति सेव करने के लिए नामांकन करें।
अनुवाद अभी उपलब्ध नहीं है। मूल पाठ दिखाया गया है। (한국어)
수신 측이 매번 받을 수 없다면
선수 지식: 1칸 ready/valid 버퍼와 파이프라인의 데이터 정렬.
고정 속도 파이프라인에 out_ready만 추가해서 출력을 막아서는 부족합니다. 마지막 단계가 가득 차서 멈추면 앞 단계도 덮어쓰면 안 됩니다. 정지 요청이 입력 방향으로 전달되는 backpressure를 설계해야 합니다.
두 단계를 각각 데이터 한 개와 valid 한 비트로 표현하겠습니다. 2단계는 비어 있거나 현재 출력을 내보낼 수 있을 때 새 값을 받을 수 있습니다. 1단계에도 같은 규칙을 적용합니다.
외부 in_ready는 r1입니다. r2=0이라도 1단계가 비어 있다면 새 입력 한 개를 받을 수 있습니다. ‘출력이 멈추면 모든 입력을 무조건 거부’하는 것보다 저장 공간을 잘 활용합니다.
각 단계는 이동 허가가 있을 때만 갱신합니다
아래 예제는 unsigned 8비트 x에 대해 y=2(x+1)을 계산합니다. 1단계는 x+1을 9비트로 저장하고, 2단계는 10비트로 한 비트 왼쪽 이동합니다. 최대 입력 255의 결과 512까지 정확하게 표현합니다.
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
endmodulenonblocking 대입이므로 2단계는 같은 에지에 새로 계산한 d1이 아니라 이전 d1을 받습니다. r1=0이면 v1·d1이 유지되고, r2=0이면 v2·d2가 유지됩니다. valid만 유지하고 데이터는 계속 갱신하는 구현은 잘못입니다.
두 단계가 모두 찼을 때의 추적
처음 v2에 A의 결과, v1에 B의 중간값이 있고 입력 C가 대기한다고 합시다.
| out_ready | in_ready | 에지에서의 동작 |
|---|---|---|
| 0 | 0 | A·B 유지, C 미수락 |
| 0 | 0 | A·B 유지, C 미수락 |
| 1 | 1 | A 전달, B가 2단계로 이동, C 수락 |
송신자는 C를 수락받을 때까지 C와 in_valid를 유지합니다. 첫 정지 에지에서 C를 보냈다고 생각하고 다음 데이터를 내면 C가 사라집니다.
각 열은 상승 에지 직전 값입니다. 시작할 때 마지막 단계에 A, 첫 단계에 B가 있으며 C가 입력에서 대기합니다. E2에서 A를 전달하고 C를 수락한 뒤, E3 직전 출력은 B로 바뀝니다.
View waveform data
| Signal | Wave | Bus values |
|---|---|---|
| edge | 2345 | E0 → E1 → E2 → E3 |
| out_ready | 0.1. | |
| out_valid | 1... | |
| out_data | 2..3 | A → B |
| in_valid | 1... | |
| in_ready | 0.1. | |
| in_data | 2..3 | C → D |
검증할 보존 법칙
리셋 이후 입력 수락 수를 Nin, 출력 전달 수를 Nout이라고 하면 저장량은 다음과 같습니다. reset 에지에서는 전송을 세지 않습니다.
카운트만 맞아도 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이므로 더 이상 받지 못합니다. 이 차이가 두 칸 저장 공간을 실제로 활용하는 조건입니다.