Altifigence Academy

9 / 24 · 개념

파이프라인 레지스터에 거래 전체 저장하기

합·곱 연산을 두 단계로 나누고 valid, tag와 수치 폭을 함께 이동시킵니다.

레지스터는 숫자와 의미의 경계다

계산 f(a,b)=3(a+b)를 두 단계로 나누겠습니다. 1단계는 unsigned 8비트 입력 둘을 더해 9비트 sum을 저장합니다. 2단계는 sum을 세 배 하여 11비트 wide 결과를 만든 뒤 하위 8비트를 저장합니다. 최대값은 3×(255+255)=1530입니다. 먼저 sum을 8비트로 잘라도 마지막 modulo 256 결과는 이 특정 정수 곱셈에서 같지만, 중간 overflow나 다음 비교가 필요하면 정보를 잃습니다. 여기서는 넓은 중간값을 유지해 연산 계약을 분명히 합니다.

각 단계는 data 외에 valid와 tag도 저장합니다. valid=0인 단계는 비어 있는 bubble입니다. 비어 있는 단계의 데이터 비트는 예전 값이어도 괜찮지만 출력 거래로 세면 안 됩니다. tag는 계산할 필요가 없더라도 같은 개수의 레지스터를 통과해야 합니다. 데이터만 두 단계 지연하고 tag는 한 단계 지연하면 연속 입력에서 출력 A에 tag B가 붙습니다.

아래 코드는 정지 없는 두 단계의 핵심입니다. 입출력의 ready는 항상 1이라고 가정합니다. wide를 만들 때 11비트로 확장하고 11비트 상수를 써 폭을 의도대로 맞춥니다. 2단계가 읽는 s1과 t1은 이번 에지 전 값입니다. 따라서 처음 입력이 수락된 에지에 결과가 곧바로 s2까지 통과하지 않습니다.

SystemVerilog
logic [8:0] s1;
logic [7:0] s2, t1, t2;
logic v1, v2;
logic [10:0] scaled;
assign scaled = {2'b00, s1} * 11'd3;
always_ff @(posedge clk) begin
  if (rst) begin
    v1 <= 1'b0;
    v2 <= 1'b0;
  end else begin
    v1 <= in_valid;
    v2 <= v1;
    if (in_valid) begin
      s1 <= {1'b0, a} + {1'b0, b};
      t1 <= in_tag;
    end
    if (v1) begin
      s2 <= scaled[7:0];
      t2 <= t1;
    end
  end
end

에지 0에서 A=(1,2)를 받으면 그 뒤 s1=3,v1=1입니다. 에지 1에서 B=(250,10)를 받으며 s1=260이 되고, 동시에 s2는 이전 A의 3×3=9를 저장합니다. 결과 A가 에지 1 뒤에 유효해지고 소비자는 에지 2에서 이를 수락할 수 있습니다. B의 값 780을 8비트로 줄인 12는 다음 에지에서 같은 방식으로 전달됩니다.

정지 없는 구조에서 in_valid=0이면 매 사이클 valid=0도 앞으로 이동시켜야 합니다. v1을 예전 1로 유지하면 이전 거래를 다시 계산해 중복 출력할 수 있습니다. reset은 valid를 비워 오래된 데이터가 새 거래처럼 나오지 않게 합니다. 데이터 레지스터까지 0으로 지워야 할지는 계약과 자원 추론에 따라 별도 판단합니다.

단계를 나눌 때는 조합 지연뿐 아니라 거래 구성요소 목록을 같이 작성하세요. op, tag, 예외 비트, 주소, 마지막 항목 표시까지 결과를 해석하는 데 필요한 정보는 모두 동반 데이터입니다. '원래 숫자는 맞다'는 관찰보다 결과·tag·valid가 한 거래를 이루는지 확인하는 것이 파이프라인 검증의 시작입니다.

직접 생각해 보기

A=(1,2,tag=10), B=(250,10,tag=11)가 연속 수락됩니다. t2<=in_tag로 잘못 작성하면 A 결과가 보이는 순간 어떤 tag가 붙나요? 올바른 연결도 쓰세요.

해설 보기

에지 1에서 s2는 이전 A를 계산하지만 현재 in_tag=11을 저장하므로 결과 9에 tag=11이 붙습니다. t2<=t1로 이전 1단계 tag=10을 저장해야 결과와 맞습니다.

선택은 이 브라우저에만 적용됩니다. 언제든 푸터에서 변경할 수 있습니다.