본문으로 건너뛰기
code0.HDL

38구현 문제

FSM 단계 두 개를 순서대로 실행하기

1. 문제와 수정 범위

orderedSteps는 서로 의존하는 동작 두 개를 담은 Stmt를 반환해야 합니다. 첫 단계는 레지스터를 3으로 만들고, 다음 단계는 반영된 3에 4를 더합니다. starter의 seq에는 noAction만 있어 상태가 바뀌지 않습니다. 그래서 controller가 끝나도 value는 초깃값 0입니다.

컴파일에 성공했다고 해서 의도한 과정이 실행된 것은 아닙니다. orderedSteps 안의 noAction만 바꾸세요. 함수 시그니처와 mkTop은 실행과 관찰을 맡으므로 그대로 둡니다.

2. starter 읽기와 실행 전 예측

starter/Main.bsv를 다음 순서로 읽어 보세요.

  1. orderedSteps의 Reg#(UInt#(8)) 인자와 반환 타입 Stmt를 확인합니다.
  2. seq ... endseq의 범위와 그 안의 noAction을 표시합니다.
  3. 반환된 Stmt가 mkTop의 mkFSM에 전달되는 경로를 따라갑니다.
  4. start는 FSM을 한 번만 시작하고, finish는 controller.done이 참이 된 뒤에만 value를 출력한다는 점을 확인합니다.

실행 전에 finish가 출력할 값을 예측해 보세요. noAction 단계는 아무것도 쓰지 않으므로 value = 0이 출력됩니다.

3. 최소 수정과 완료 조건

두 연산은 서로 의존합니다. 더하기가 3을 읽으려면 3을 쓰는 동작이 먼저 클록 경계에서 반영되어야 합니다. 기존 seq 구조를 유지한 채 noAction을 동작 문장 두 개로 바꾸면 반영 시점이 두 번 생깁니다. 최종값 7을 한 번에 쓰면 출력은 맞아도 순서 있는 FSM 동작을 보여 주지 못합니다.

수정한 뒤 실행을 누르기 전에 상태를 순서대로 적어 보세요.

시점valueFSM 상태
시작 전0대기
첫 동작 반영 뒤3남은 단계 있음
둘째 동작 반영 뒤7완료

공개 실행은 value = 7을 출력하고 끝나야 합니다. 7은 서로 다른 FSM 단계 두 개를 거쳐 만들어져야 하고, 둘째 동작은 첫 동작이 반영한 레지스터 값을 읽어야 합니다. controller는 두 쓰기가 모두 반영되기 전에 완료를 알리거나 중간에 멈추면 안 됩니다. 결과를 확인한 뒤 두 단계 사이에 경계가 필요한 이유를 설명해 보세요.

4. 단계형 힌트

힌트 1: seq의 규칙

seq 안의 서로 다른 동작 문장은 소스 순서대로 실행되며, FSM 단계 사이에서 레지스터 쓰기가 반영됩니다.

힌트 2: 수정 위치

orderedSteps의 noAction만 바꾸면 됩니다. mkFSM, start, finish는 이미 알맞은 시점에 값을 관찰합니다.

힌트 3: 두 동작의 관계

먼저 기준값을 쓰는 대입이 필요합니다. 뒤의 대입은 최종 상수를 쓰지 않고, 레지스터를 읽어 값을 계산합니다.

5. 추가 실험

필수 수정을 확인한 뒤 두 대입의 식은 그대로 두고 순서만 잠시 바꿔 보세요. 중간 상태와 최종 상태를 먼저 계산한 다음 실행합니다. 식이 같아도 순서가 바뀌면 상태 변화가 달라집니다. 채점하기 전에는 요구된 순서로 되돌리세요.

개념 다시 보기
준비
Main.bsv