모든 이야기

FSM 추출을 못 했다는 로그가 기능 오류를 뜻하지는 않는다

합성 로그에 FSM을 찾지 못했다는 메시지가 나왔는데 회로는 정상 동작한다. 상태 레지스터도 있고 상태별 case 문도 있다. 왜 합성기는 이것을 상태 기계로 다루지 않았을까? FSM 추출은 상태가 존재하는지뿐 아니라, 그 상태를 별도의 전이 표와 재인코딩 가능한 구조로 바꿔도 되는지 판단하는 과정이다.

유한한 상태가 있다고 모두 같은 후보는 아니다

모든 비트 레지스터는 가능한 값의 수가 유한하다. 하지만 합성기의 FSM 추출은 그 전체 공간을 언제나 상태 표로 펼치는 기능이 아니다. 상태값이 어떻게 갱신되고 어디에 쓰이는지를 보고, 제어용 상태 기계로 처리할 만한 구조를 선택한다.

Yosys의 FSM 설명은 다음 상태가 상수 상태값 또는 현재 상태를 잎으로 갖는 mux 트리로 표현되고, 상태값이 그 갱신 경로나 상수와의 비교 등에 쓰이는 경우를 대표 후보로 설명한다. 모듈 출력으로 상태값이 직접 나가는 경우는 자동 인식의 대상에서 제외하는 조건도 있다. Yosys FSM detection·extraction 설명

같은 2비트 레지스터라도 state <= state + 1로 다음 값을 계산하는 카운터와, Idle·Run·Done 상수 중 하나를 고르는 제어기는 구조가 다르다. 카운터 역시 유한 상태를 갖지만, 그 산술 갱신을 위 mux 잎 조건과 똑같이 취급할 수는 없다. 추출되지 않았다는 메시지를 “하드웨어를 만들지 못했다”는 뜻으로 읽으면 안 된다.

세 상태의 의미와 비트값을 분리하기

가상 제어기를 Idle=00, Run=01, Done=10으로 표현해 보자. 리셋하면 Idle이다. Idle에서 start=1이면 Run으로 가고, Run에서 finish=1이면 Done으로 간다. 그 밖에는 상태를 유지하며, Done은 다음 에지에 Idle로 돌아간다. busy는 Run일 때만 1이고 done은 Done일 때만 1이다.

이 회로를 전이 표로 추출하면 필요한 내용은 상태 이름, start·finish 조건, 다음 상태와 두 출력의 관계다. Idle의 값이 00이라는 사실은 내부 표현일 수 있다. 예를 들어 Idle=001, Run=010, Done=100이라는 다른 표현에서도 같은 조건으로 이동하고 같은 busy·done을 내보내면 정상 도달 상태의 외부 동작은 같다.

리셋 뒤 첫 에지에 start=1을 넣고, Run에서 finish=0과 finish=1인 에지를 차례로 준 뒤 한 에지를 더 진행하면 상태는 Idle→Run→Run→Done→Idle이다. 각 상태의 busy/done은 0/0, 1/0, 1/0, 0/1, 0/0이다. 두 인코딩의 비트열은 달라도 이 출력열은 일치한다. 이는 상태 표현의 변경을 설명하는 가상 예이며, 특정 Yosys 설정의 실제 선택 결과가 아니다.

2비트 표현과 3비트 표현 사이에는 레지스터 수와 출력 디코딩 비용의 교환이 생긴다. 따라서 추출과 재인코딩이 가능하다고 해서 면적이나 속도가 항상 좋아지는 것은 아니다. 어떤 표현이 적합한지는 목표 셀, 전이 논리와 출력 경로를 포함한 결과로 판단해야 한다.

디버그 출력이 바꾸는 재인코딩의 자유

원래 회로에 debug_state = state라는 출력 포트를 추가했다고 하자. 외부는 Run일 때 01을 읽고 Done일 때 10을 읽는다. 이제 상태값은 내부의 임의 표현을 넘어 관측할 인터페이스의 일부가 됐다.

상태를 010과 100으로 바꿔 그대로 debug_state에 내보내면 출력 폭이나 값이 달라진다. 재인코딩을 하려면 내부 상태를 원래 외부 코드로 바꾸는 변환도 필요하다. 단순히 더 빠른 상태 비트 구조로 바꾸는 것만으로는 동작 보존이 끝나지 않는다. 자동 인식이 출력 연결을 보수적으로 다루는 이유를 이 사례에서 이해할 수 있다.

실제 fsm_detect 구현도 상태 신호가 모듈 포트와 연결되는지, 다음 상태 트리와 사용 형태가 적합한지 확인한다. 초기값이나 스스로 초기 상태로 수렴하는 구조 등 추가 판단도 있다. 특정 속성으로 인식을 강제하면 경고가 발생할 수 있으므로, 로그를 읽고도 단지 FSM 수를 늘리려고 auto 속성을 붙이는 것은 좋은 기준이 아니다. fsm_detect의 실제 판단과 경고

추출 뒤에는 제어 입력과 출력, 전이 표가 올바른지도 확인해야 한다. 상태 인코딩이 달라지면 내부 state 비트끼리 같은 값인지 비교하는 검증은 더 이상 적절하지 않을 수 있다. 상태 의미의 대응과 외부 출력 관계를 검사하는 쪽이 맞는다. 불법 상태에서의 복구가 요구 사항이라면 정상 상태 전이 표만 확인해서 끝내지 말고 그 요구도 따로 보존해야 한다.

FSM 인식 실패를 만났을 때는 상태를 읽는 모든 경로부터 살펴보면 된다. 외부로 비트값을 내보내는지, 산술 데이터처럼 사용하는지, 다음 상태가 어떤 셀 형태로 남았는지에 따라 추출의 자유가 달라진다. 기능을 정상 합성하는 것과 FSM 전용 최적화를 적용하는 것은 별도의 판단이다. 그 구분을 알면 로그 한 줄을 쫓기보다 실제로 보존해야 할 상태 의미와 구현 비용에 집중할 수 있다.