1. 요구사항을 먼저 포트로 옮깁니다
이 장에는 실행할 코드가 없습니다. 채점 문제가 제시하는 것과 같은 요구사항에서 모듈을 직접 씁니다.
4비트 카운트
q. 매 상승 에지에서,clear가 1이면q는 0이 됩니다. 아니면enable이 1일 때q는 1 증가하고 15 다음에는 0입니다. 그 밖에는q가 그대로입니다. 모듈의 암묵적 동기 리셋 뒤에q는 0입니다.
글의 명사는 모두 포트 또는 레지스터이고, "에지에서 … 이면"은 모두 레지스터의 다음 값에 붙는 조건입니다. 무엇보다 먼저 포트를 적으세요.
| 글에서 | 모듈에서 |
|---|---|
clear, enable을 검사 | 각각 Input(Bool()) |
q는 4비트, 밖에서 읽음 | Output(UInt(4.W)) |
q는 사이클을 넘어 값을 유지, 리셋 뒤 0 | RegInit(0.U(4.W))를 출력에 연결 |
레지스터·RegInit·클록 진행 장에서 말한 대로 리셋 값에 폭을 적으세요. RegInit(0.U)는 연결된 것에서 폭이 추론되고,
자기 값에 1비트 리터럴을 더해 되먹임하는 카운터는 1비트로 정해집니다. 채점 문제의 시작 코드에는 포트, 이 레지스터,
io.q := q가 이미 있습니다. 남겨진 것은 다음 값이며, 이 장의 나머지가 그 내용입니다.
2. 우선순위는 사슬의 순서입니다
요구사항은 경우 셋을 나열하고 "아니면"이라는 말로 어느 쪽이 이기는지 말합니다. 그 순서가
when/.elsewhen 사슬이고, 사슬이 말하지 않는 경우에 레지스터는 유지합니다. 레지스터에는
.otherwise가 필요하지 않습니다. wire에는 필요하고 레지스터에는 필요하지 않은 이유는
조건부 갱신·유지·리셋 장에서 설명했습니다.
| 경우 | 분기 | q의 다음 값 |
|---|---|---|
clear가 1 | when (io.clear) | 0 |
clear가 0이고 enable이 1 | .elsewhen (io.enable) | q + 1, 되돌아감 |
| 둘 다 0 | 분기 없음 | q 유지 |
확인 문제
어느 에지에서 clear와 enable이 모두 1입니다. 에지 뒤 q는 무엇입니까?
3. 되돌아감은 폭이 하는 일이며 +%로 씁니다
4비트 UInt에서 q + 1.U는 이미 4비트입니다. +는 피연산자 폭을 유지하므로 15 + 1은 16의 하위 네
비트인 0이 됩니다. Chisel에는 명시적으로 확장하지 않는 덧셈 +%도 있습니다. UInt에서는 +와 같은
뜻이고, 되돌아감이 의도임을 밝힙니다. +&는 5비트 값을 만들고 4비트 레지스터로의 연결이 다시
절단합니다. 숫자는 같게 나오지만 잃은 비트가 의도였는지 읽는 사람이 알 수 없습니다. q +% 1.U로
쓰세요. 문제의 힌트처럼 q + 1.U로 써도 됩니다. 최댓값이 2의 거듭제곱보다 1 작으므로 15와의 비교는
필요하지 않습니다.
확인 문제
q가 15이고 clear는 0, enable은 1입니다. 에지 뒤 q는 무엇입니까?
4. clear는 포트이고 reset은 모듈의 암묵적 신호입니다
clear와 리셋은 모두 q를 0으로 만들지만 서로 다른 장치를 거치며, 문제는 둘을 구분합니다. 문제의
글은 q가 모듈의 암묵적 동기 reset 뒤에 0이라고 말하고, clear는 다른 신호, 즉 다음 에지에서
카운트를 0으로 만드는 보통 입력이며 reset이 0인 동안 동작해야 한다고 말합니다. 완료 조건에는
reset이 1인 동안 enable이 1이어도 q가 매 에지에서 0이라는 항목이 있습니다. 리셋에 관한 문장의
구현은 RegInit(0.U(4.W))가 전부입니다. RegInit은 조건부 갱신·유지·리셋 장에서 설명한 암묵적 리셋에 응답하고,
chiseltest는 본문 전에 그 리셋을 인가하며, 리셋이 1인 동안 레지스터는 다음 값 대신 0을 저장합니다.
clear는 when 사슬의 첫 분기이고 그 밖의 무엇도 아닙니다. clear를 리셋에 연결하거나
withReset을 쓰지 마세요. 채점기는 clear를 보통 입력으로 구동하고 q가 사슬을 따르기를
기대합니다.
5. 쓰기 전에 설계를 예측합니다
요구사항이 설명하는 카운터의 표를 채우세요. 각 행이 사이클 하나이고, clear와 enable은 그 사이클
동안의 입력이며, 그 사이클을 끝내는 에지 뒤의 q를 적습니다. 브라우저 모델의 계약도 같습니다.
clear가 이기고, enable은 16을 주기로 세고, 그 밖에는 유지합니다.
예측한 뒤 비교 · counter4
비교하기 전에 모든 칸을 채우세요. 빈칸도 불일치로 처리합니다.
| 사이클 | clear에지에서 샘플링한 입력 | enable에지에서 샘플링한 입력 | q에지 직후 |
|---|---|---|---|
| 0 | 0 | 1 | |
| 1 | 0 | 1 | |
| 2 | 0 | 1 | |
| 3 | 1 | 1 | |
| 4 | 0 | 1 | |
| 5 | 0 | 0 | |
| 6 | 1 | 0 | |
| 7 | 0 | 1 |
6. 경계에서 나온 테스트벤치 계획
문제의 공개 테스트벤치는 출력을 보여 주고, 채점기는 비공개 테스트를 실행합니다. 실행을 누르기
전에, 올바른 설계와 거의 올바른 설계를 가르는 경우마다 기대값을 직접 적으세요.
| 경우 | 확인할 것 |
|---|---|
| 리셋만 | 어떤 poke도 전에 q가 0으로 읽힘 |
| 유지 | 두 입력이 모두 0인 여러 step 동안 q가 움직이지 않음 |
| 카운트 | enable이 1인 열여섯 step 동안 q가 15를 지나 다시 0으로 읽힘 |
| clear 우선 | clear와 enable이 함께 1이면 다음 에지에서 0 |
| clear 시점 | clear를 1로 넣어도 step 전에는 아무것도 바뀌지 않음. q는 에지 뒤에만 0 |
확인 문제
q가 7입니다. 테스트벤치가 clear를 1로 넣고 step 없이 q를 peek합니다. 무엇이 읽힙니까?
7. 문제 둘, 방법 하나
아래 채점 문제가 이 장의 카운터입니다. 공개 실행은 사이클마다 한 줄씩, 그 사이클의 에지 전의
q를 출력하므로 비교할 때는 에지 뒤 열을 한 줄 아래로 밀어 맞추세요. 둘째 문제 select-op은 조합
회로입니다. 2비트 sel이 a와 b에 적용할 비트 연산 넷 가운데 하나를 고르고, y는 레지스터 없이
같은 사이클에 그 결과를 전달합니다. 같은 방법을 쓰세요. 표를 포트로 옮기고, 결과 넷을 각각 식으로
만들고, 선택 유틸리티 장에서 본 선택 도구 가운데 키 하나를 상수들과 비교하는 도구로 sel 값마다 항목
하나와 올바른 타입의 기본값을 나열해 고릅니다. 쌍 안의 연산에는 괄호를 치세요. ->가 비트
연산자보다 먼저 결합합니다. 두 문제 모두 기대 출력을 먼저 적고 출력된 줄과 한 줄씩 비교하세요.
8. 정리
| 단계 | Chisel |
|---|---|
| 요구사항의 명사 | 폭을 명시한 Input, Output |
| 유지되는 값 | 폭을 적은 v로 RegInit(v) |
| "이면 … 아니면 …" | 그 순서의 when/.elsewhen. 레지스터는 .otherwise 없이 유지 |
| "되돌아간다" | 레지스터 폭에서의 +% |
| "리셋 뒤" | 리셋 값. 기능상의 clear는 포트로 둠 |
| 채점 전 | 사이클 표와 경계 사례 |
이 경로가 다루지 않은 내용은 장이 레퍼런스입니다. 리셋 타입과 withReset은
순차 회로 장에, 선택 도구들은
멀티플렉서와 입력 선택 장에, 폭 규칙은
데이터 타입 장에 있습니다.