본문 바로가기
[Nexys4 DDR]

[Nexys4DDR 프로젝트] SPI Interface (SPI 통신)

by choice1219 2019. 5. 18.

SPI_ADXL362.zip
0.00MB

안녕하세요. VeriLog입니다. 

 

오늘은 Verilog를 사용해서, SPI 모듈을 설계해보겠습니다.

 

SPI 통신은 Serial 통신의 한 종류로, 최근에 많이 사용되는 방법입니다.

 

SPI는 간단하면서 UART보다 빠르게 통신할 수 있는 방법입니다. 

 

SPI의 특징을 간단하게 살펴보면 아래와 같습니다.

 

- 대게 UART보다 빠른 통신을 지원한다. (MHz 단위)

- 전이중 방식 통신 (Tx, Rx를 동시에 수행할 수 있다)

- 여러 Slave를 가질 수 있다. 

- 포트:

   - Serial Clock (SCLK)

   - Master Out Slave In (MOSI, or SDO)

   - Master In Slave Out (MISO, or SDI)

   - Chip Select (CS', or CE')

SPI Interface Port Example

 

이번 포스팅에서는 Nexys4DDR에 내장되어 있는 가속도계 센서 (ADXL362) 모듈과 SPI 통신을 통해서, Data를 읽어오는 모듈을 구현해보겠습니다. 

 

 

먼저, 가속도계 (ADXL352)의 SPI 통신 Protocol을 살펴보도록 하겠습니다.

 

자세한 내용은 첨부파일로 올려드린 Datasheet를 참고해주세요.

 

<가속도계 Register Read 프로토콜>

1. CS High -> Low

2. 8 비트 Instruction 송신

3. 8 비트 Address 값 송신

4. 8 비트 데이터 수신

5. CS Low -> High

 

ADXL362 Data Read Timing Diagram

 

ADXL362 Datasheet를 보시면,

 

- Data Read Instruction: 0x0B

- Data Write Instruction: 0x0A

 

Register Map은 아래 그림과 같이 되어 있는 것을 확인할 수 있습니다.

ADXL362 Register Map

 

우리는 이번 시간에, Y축 Data로부터 Data Read 하는 모듈을 작성할 예정입니다.

 

따라서, Instruction: 0x0B / Address: 0x09로 설정해주시면 됩니다.

 

ADXL Axis

통신에서 가장 중요한 부분은 Timing 입니다. 

 

이미 만들어진 모듈을 사용할 때는 통신 속도, Databit 수, 등을 맞춰주면 알아서 통신이 되지만, 통신 모듈을 직접 만들어야 하는 단계에서는 Data 송신과 수신이 Clock의 어떤 부분에서 이뤄지는지에 대한 이해가 있어야 합니다. 

 

UART 통신은 비동기식 통신이기 때문에, Data 손실을 막기 위해, Read를 아래 그림처럼 Clock의 중간에서 합니다. 

출처: https://shek.tistory.com/41

 

UART 통신 이론

UART(범용 비동기화 송수신기: Universal asynchronous receiver/transmitter)는 병렬 데이터의 형태를 직렬 방식으로 전환하여 데이터를 전송하는 컴퓨터 하드웨어의 일종이다. UART는 일반적으로 EIA RS-232, RS..

shek.tistory.com

하지만, SPI통신의 경우, 동기식 통신이기 때문에, Master에서는 Data 송신을 SCLK의 Rising Edge에 합니다. 

 

Slave의 경우는, 반대로, SCLK의 Falling Edge에 Data 송신을 수행합니다.

 

이 점을 유의해서 Verilog 코딩을 하면 아래와 같이 코딩을 할 수 있습니다.  

 

SPI Interface Module Port Declaration

 

1. Clock Divider를 통해 SCLK의 속도를 정해줍니다.

 

2. SCLK의 Falling Clock에 CS Value를 'High' -> 'Low'로 바꿔줌으로, 통신 시작을 알립니다.

 

3. 위에서 언급한대로, Master에서 Data 송신은 Rising Edge에서 이루어지므로, 미리 Buffer에 있는 값을 Shift 해줘야 올바른 값이 전송 됩니다. 따라서, Falling Edge에서 미리 전송할 데이터 준비를 합니다.

 

4. 위에서 언급한대로, Slave에서 Data 송신은 Falling Edge에서 이루어지므로, Rising Edge에서 Data를 읽어오면 Data 손실을 막을 수 있습니다. 

 

5. 한 패킷의 데이터 통신이 끝나면, Read Buffer에 있는 데이터를 output 포트로 보내줍니다. 

 

위의 과정을 반복하면 SPI 통신을 통해서 ADXL362와 통신을 할 수 있습니다.

 

 

위의 모듈은 다른 모듈에서 적용할 시, 프로토콜에 맞게 약간의 수정을 통해서 사용 할 수 있습니다. 

 

저는 ADXL로부터 받은 Data를 LED로 출력하도록 코드를 작성하였고, 그 결과는 아래 첨부된 영상과 같습니다. 

 

 

 

8비트의 Signed Data가 들어오기 때문에, Y-축 방향에 따라서 (+) 또는 (-) 값이 증가하는 것을 확인하실 수 있습니다.

 

전체 코드는 첨부합니다. 질문이 있으실 경우,

 

seontaekoh1219@gmail.com로 연락 주시면 답해드리겠습니다.