UART Rx Verilog Module 살펴보기 프로젝트
목차
- UART verilog Testbench 살펴보기
- UART Tx Verilog Module 살펴보기
- UART Rx Verilog Module 살펴보기(현재 포스팅)
- APB Bus 살펴보기
- APB Register 설계하기
- Vivado UART 모듈 설정 하기
- Xilinx Zynq Firmware Code 짜보기
이번에는 Rx 모듈 편이다. 테스트벤치 상 구현되어 있는 내용을 간단하게만 보면 아래와 같다.
- Tx 모듈에다 보낼 데이터(byte)를 DV와 함께 보내준다.
- 시리얼로 데이터를 보낸다.
- Rx 모듈에서 시리얼로 데이터를 수신한다. (Testbench 상에서는 Rx와 Tx 모듈이 서로 물려있다.)
- 데이터가 모이면 DV와 함께 데이터를 뱉는다.
이번 포스팅에서는 각 모듈을 살펴보기로 한다.
이번에도 참고할 코드는 깃허브에 있다.
UART Rx Verilog Module
먼저 수신단부터 확인해보자.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-8.png)
input으로는 리셋, 클럭, 수신한 시리얼 데이터
output으로는 데이터 valid, 송신할 데이터(8비트) 이다.
내부에 선언되어 있는 변수들은 아래와 같다.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-9.png)
localparam은 state machine 용으로 선언되어 있다. `define 형태로 정의해도 되지만, 타 모듈에도 영향을 끼치지 않게 하려면 localparam이 적합하다.
r_SM_Main은 state machine이고, 클럭 카운트도 선언되어 있다. CLKS_PER_BIT을 log_2형태로 취하는 것을 볼 수 있는데, n비트 수가 취할 수 있는 범위는 2^n이기 때문이다.
range \quad of \quad 2^n => [n - 1\, :\, 0]\, count; \quad 0 \sim 2^{(n-1)}
range \quad of \quad num => [\log_2(num)\, :\, 0]\, count;
아래 always 문에서는 state machine으로 동작하는 것을 볼 수 있다.
아래 state machine을 확인할 때 전 포스팅에서 첨부했던 그림을 참고하는 것이 좋다.
![](https://dkeemin.com/wp-content/uploads/2022/06/uart_byte_sampling.png)
State Machine
![](https://dkeemin.com/wp-content/uploads/2022/06/image-10.png)
UART Rx Module 도 마찬가지로 UART Tx Module처럼 모두 state machine으로 동작하는 것을 확인할 수 있다. 먼저 reset이 발생했을 때 스테이트 머신먼저 초기화를 해준다.
정상 동작할 때는 아래와 같이 case문으로 머신이 동작하게된다.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-11.png)
IDLE 상태일 경우 Tx와는 좀 다르다. Data Valid, Clock count, Index가 0으로 초기화하고 Start Bit가 발견되면 START_BIT로 넘어간다.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-12.png)
START BIT 상태의 경우 0의 상태를 1bit 유지를 해야한다. 중간 쯤에서 읽어서 0이 유지되면 START_BIT가 잘 동작하는 것이고, 아니면 노이즈인 것으로 판단하고 다시 IDLE로 돌아간다. 노이즈인게 좀 걱정이 된다면 가운데 쯤 8비트 정도 읽어서 1이 계속 유지되는 지를 판단하는 것도 나쁘지 않겠다.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-13.png)
시리얼 데이터를 수신할 때 UART는 Index가 0 부터 송신하게 되어 있다.
Index가 0부터 시작해서 6이 되면 마지막으로 index를 1 더 올려서 7인 상태로 RX_DATA_BITS가 동작한다.
모든 8비트의 데이터를 송신하면(index가 7이 되면) RX_STOP_BIT로 넘어가서 송신을 마무리할 준비를한다.
주목할 점은 o_RX_Byte에 1비트씩 수신한 데이터를 넣어준 다는 것이다.
![](https://dkeemin.com/wp-content/uploads/2022/06/image-14.png)
RX_STOP_BIT에서는 1인 상태를 CLKS_PER_BIT까지 기다려준다음에 IDLE로 넘어가게 된다.
예제에서는 1cycle 정도 여유를 주었다.
해당 과정이 모두 끝나면 IDLE로 넘어가서 계속 진행한다.
Rx 포스팅 끗!
안녕하세요. 코드를 보다 보니 이해가 안되는 부분이 있어서요.
STATE == START 일때 0 상태를 1bit 유지해야한다고 하셨는데요. 코드를 보면 이를 유지하는 코드가 없지 않나요?
1bit 중간에 data를 검사하는 부분만 있는것 같아서요.
안녕하세요. 유지하는 코드는 Tx쪽에 있습니다.
Rx에는 Serial Read 파트이기때문에 1비트를 유지시키지 않습니다.
그 clock counter가 싱크가 안맞지 않나요??
예를들면 tx에서 clk counter가 500일 때 rx의 clk counter가 498이라던지
async인데 sync를 맞춰야하나요?