본문으로 건너뛰기
code0.HDL

11구현 문제

1인 사이클이 아니라 상승 에지 세기

1. 요구 동작

EdgeCounter의 rise는 in이 이전 사이클에 0이었고 현재 사이클에 1일 때만 참입니다. 따라서 in이 1인 구간이 아무리 길어도 rise는 그 구간의 첫 사이클에 한 번만 1이 됩니다. count는 rise가 1일 때마다 1씩 증가하고 255 다음에는 0으로 돌아갑니다.

리셋은 이전 입력을 0으로 정의합니다. 리셋이 끝날 때 in이 이미 1이면 그 첫 사이클도 상승 에지 하나로 셉니다.

2. 시작 코드의 문제

시작 코드의 rise는 in을 이름만 바꿔 연결한 값입니다. 모듈에는 이전 사이클의 입력을 저장하는 레지스터가 없습니다. 따라서 새로 시작한 1 구간과 계속 이어지는 1 구간을 구별할 수 없고, count는 에지 수가 아니라 in이 1인 사이클 수를 셉니다.

TODO 줄을 현재 입력과 한 사이클 전 입력을 비교하는 rise 정의로 바꾸세요. 포트, 카운터, Main의 테스트벤치는 그대로 둡니다.

3. 실행 전 예측

공개 테스트벤치는 1 1 0 1 1 1 0 0 1 0 순서로 입력을 인가하고, 사이클마다 rise와 count를 출력한 뒤 클록을 진행합니다. 각 줄의 count는 그 사이클의 클록 에지 이전 값입니다.

시작 코드를 실행하기 전에 그 코드의 rise 열과 마지막 count를 적어 보세요. 이어서 올바른 에지 카운터의 결과를 예측해 보세요. rise는 정확히 세 줄에서 1이고 마지막 줄은 count=3입니다. 리셋으로 이전 입력을 저장하는 레지스터가 0이 되므로 사이클 0도 그 세 줄에 포함됩니다.

4. 수정 방향

rise를 계산하려면 현재 in과 한 사이클 전 in이 모두 필요합니다. 한 사이클 전 값은 상승 에지마다 in을 저장하는 레지스터에서 얻습니다. 이 레지스터의 리셋 값도 1절의 계약에 포함됩니다.

수정한 뒤 다시 실행해 예측과 비교하세요. 네 사이클 동안 1이 이어지는 구간도 펄스는 하나만 만들어야 하고, count는 각 펄스 다음 줄에서 증가해야 합니다.

5. 완료 조건

  • 0에서 1로 바뀔 때마다 rise가 정확히 한 사이클 동안 1입니다. 그 뒤 입력이 얼마나 오래 1을 유지하든 같습니다.
  • 리셋이 끝날 때 이미 1인 입력은 에지 하나로 셉니다.
  • count는 에지마다 1씩 증가하고, 255 다음에 0이 되며, 리셋하면 0이 됩니다.
  • 공개 입력 순서에만 맞춘다고 완료되지 않습니다. 임의의 입력 순서에서 같은 관계가 성립해야 합니다.

6. 힌트

힌트 1

조합 회로 식은 현재 사이클의 값만 봅니다. 시간에 따른 변화를 검출하려면 상태가 필요합니다.

힌트 2

순차 회로 장은 입력을 한 사이클 늦추는 생성자를 다룹니다. 그 생성자는 리셋 값도 인자로 받습니다. 현재 in과 늦춘 사본을 비교해 보세요.

개념 설명

에지는 두 사이클 사이의 관계입니다. 따라서 에지 검출기에는 이전 값을 보관하는 레지스터가 하나 필요합니다. 그 레지스터의 리셋 값은 리셋이 끝난 뒤 첫 비교에 쓸 이전 값을 정합니다. 리셋 값이 없으면 리셋 후 첫 비교 결과는 레지스터에 우연히 남은 값에 좌우됩니다.

7. 추가 실험

rise가 하강 에지를 검출하도록 바뀌었다고 가정해 보세요. 공개 입력 순서에서 펄스가 나오는 사이클과 마지막 count 값을 예측해 보세요.

개념 다시 보기
준비

CheerpJ로 브라우저에서 실행합니다. 첫 실행에는 Java 약 14.5 MB와 JAR 약 47 MB를 내려받습니다. 컴파일에 1분 정도 걸릴 수 있습니다. 라이선스

Main.scala