Altifigence Academy

51 / 52 · 개념

레지스터 인터페이스와 부작용의 발생 시점

주소·바이트 쓰기·응답 정지를 명세하고, 요청 한 번이 정확히 한 번의 상태 변경으로 이어지게 만듭니다.

‘레지스터에 쓴다’는 동작을 정의합니다

선수 지식: 주소 디코더, ready/valid, enable과 상태 갱신 우선순위.

설정 레지스터를 외부 제어기에 연결하면 주소가 맞는지만 확인해서는 충분하지 않습니다. 요청이 수락된 시점, 응답이 대기하는 동안의 유지 조건, 읽기 전용 주소에 쓰는 경우까지 정의해야 합니다. 여기서는 같은 클록의 간단한 단일 요청·응답 인터페이스를 사용합니다.

accept=req_validreq_ready\mathrm{accept}=\mathrm{req\_valid}\land\mathrm{req\_ready}

아래 주소는 바이트 주소이며 32비트 정렬을 사용합니다. 요청 하나마다 성공 또는 오류 응답을 정확히 하나 만듭니다.

주소이름동작
0x0CONFIG읽기/쓰기, byte strobe 적용
0x4STATUS읽기 전용, 수락 시점 값을 반환
0x8COMMAND읽으면 0, byte 0의 bit 0을 쓰면 start pulse
기타미정의오류 응답, 상태 변경 없음

응답 슬롯이 비거나 비워지는 에지에 받습니다

SystemVerilog
module register_interface (
    input  logic        clk, rst,
    input  logic        req_valid, req_write,
    output logic        req_ready,
    input  logic [3:0]  req_addr,
    input  logic [31:0] req_wdata,
    input  logic [3:0]  req_wstrb,
    output logic        rsp_valid,
    input  logic        rsp_ready,
    output logic [31:0] rsp_rdata,
    output logic        rsp_error,
    input  logic [31:0] status_value,
    output logic [31:0] config_value,
    output logic        start_pulse
);
    assign req_ready = !rsp_valid || rsp_ready;
    always_ff @(posedge clk) begin
        if (rst) begin
            rsp_valid    <= 1'b0;
            config_value <= 32'd0;
            start_pulse  <= 1'b0;
        end else begin
            start_pulse <= 1'b0;
            if (req_ready) begin
                rsp_valid <= req_valid;
                if (req_valid) begin
                    rsp_rdata <= 32'd0;
                    rsp_error <= 1'b0;
                    case (req_addr)
                        4'h0: begin
                            if (req_write) begin
                                for (int i=0; i<4; i++)
                                    if (req_wstrb[i])
                                        config_value[8*i +: 8]
                                            <= req_wdata[8*i +: 8];
                            end else rsp_rdata <= config_value;
                        end
                        4'h4: begin
                            if (req_write) rsp_error <= 1'b1;
                            else rsp_rdata <= status_value;
                        end
                        4'h8: begin
                            if (req_write)
                                start_pulse <= req_wstrb[0] && req_wdata[0];
                        end
                        default: rsp_error <= 1'b1;
                    endcase
                end
            end
        end
    end
endmodule

응답이 막히면 req_ready=0이므로 config 쓰기와 command pulse도 다시 실행되지 않습니다. 이미 수락한 요청의 부작용은 발생했지만 응답만 대기할 수 있습니다. 응답 지연을 보고 요청을 무조건 재전송하면 명령이 중복 실행될 수 있습니다.

byte strobe의 의미를 계산합니다

CONFIG가 32'h11223344일 때 req_wdata=32'hAABBCCDD, req_wstrb=4'b0101을 쓰면 byte 0과 byte 2만 바뀝니다. 결과는 32'h11BB33DD입니다. 주소의 정렬, 비트 위치, 메모리의 byte 순서를 따로 확인해야 하며 wstrb=0000인 쓰기는 성공 응답을 만들되 값을 바꾸지 않습니다.

상태는 어느 시점의 값인가요?

STATUS 읽기 응답에는 요청 수락 시점의 status_value를 저장합니다. 이후 응답이 정지하는 동안 실제 status가 변해도 rsp_rdata는 유지됩니다. rsp_valid=1, rsp_ready=0인 상태에서 조합 status를 응답에 그대로 연결하면 응답 내용이 바뀌는 프로토콜 위반이 됩니다.

연속된 에지에 req_valid와 req_ready가 모두 1이면 서로 다른 두 요청입니다. 송신 측은 수락 후 valid를 내리거나 다음 요청으로 갱신해야 합니다. 같은 요청을 계속 유지하면서 한 번만 처리되기를 기대해서는 안 됩니다.

검증의 세 축

  1. 주소·접근 권한: 유효 주소, 비정렬 주소, STATUS 쓰기, 미정의 주소에서 오류와 부작용을 확인합니다.
  2. 데이터 선택: 네 strobe 비트를 전수 검사하고, 비활성 byte가 보존되는지 확인합니다.
  3. 흐름 제어: 응답을 여러 사이클 막아도 응답과 상태가 유지되고, 응답 소비와 다음 요청 수락이 겹쳐도 거래 수가 일치하는지 확인합니다.

직접 생각해 보기

req_wstrb[0]=1, req_wdata[0]=1인 COMMAND 쓰기가 수락된 뒤 rsp_ready=0이 3사이클 유지됩니다. start_pulse가 3사이클 동안 반복되어야 합니까? STATUS 쓰기는 config_value를 바꿔도 됩니까?

해설 보기

start_pulse는 요청 수락 직후 한 사이클만 1이고 이후 0입니다. 응답 정지는 명령 재실행 조건이 아닙니다. STATUS 쓰기는 오류 응답을 만들고 config_value를 포함한 다른 상태를 바꾸지 않습니다. 응답 완료 전 재시도 정책도 송수신 측이 합의해야 합니다.

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