반응형

이전 포스팅에서 SCCB 통신, 카메라 모듈의 동작, Verilog 예제 코드로 기술된 카메라 통신 등을 작성 했었다.

 

이번에는 실제로 FPGA 보드를 사용해 디스플레이에 카메라 화면을 띄우는 것 까지를 목표로 해 본다.

 

사용 환경

보드 : DE2-115

디스플레이 : 삼성 27인치 모니터

툴 : Quartus II 13.1

기타 필요 도구 : VGA 케이블

 


 

먼저, OV7670 은 내부 register 를 가지고 있고, 이를 조절함에 따라 해상도 등과 같은 값들에 영향을 미친다.(VGA, QVGA, QQVGA, CIF, ...)

 

그리고 이 내부 register 들을 조절하기 위한 프로토콜이 SCCB 인데, 이는 I2C 와 비슷한 프로토콜이다. 

그리고, 다른 아두이노에서 OV7670 카메라를 연결할 때 보면 알겠지만, 오픈 컬렉터 방식(default high)이라 코드 상에서는 

High 신호를 보내려면 내부 코드를 0으로 만들어야 하고, LOW 신호를 보내기 위해서는 High-impedance 신호를 보내줘야 한다.

 

wire o_SCL;
assign o_SCL = SCL_en ? 1'b0 : 1'bZ;

 

 


OV7670 카메라, 보드, 디스플레이의 구조는 다음과 같다.

 

1) OV7670 과 보드가 initial register setting 을 SCCB bus 를 통해 통신한다.

2) 카메라에서 설정한 해상도에 맞게 데이터가 나온다.

2-1) 해당 데이터를 보드의 메모리 상에 저장한다.

3) 메모리에 있는 데이터를 화면으로 보여준다.

 

하지만 DE2-115 내부 block ram은 12-bit color 640*480 이미지를 담지 못한다.(3,686,400 bits, place & route 단계에서 불가능하다고 나옴)

따라서 320*240 (qvga) 해상도를 사용하던지, 640*480 에서 일정 부분에서 화면을 잘라서 사용하는 방법을 우회적으로 사용해야 되겠다. 화면을 자르는 경우에는 타이밍 관련해서 코드를 좀 더 자세히 수정할 필요는 있다.

 

아두이노 예제 코드를 보면, QVGA initial register setting 코드들이 나와 있다.

Visual Capturing with OV7670 on Arduino - Hackster.io

 

Visual Capturing with OV7670 on Arduino

This is an Arduino camera module, using the surveillance camera's digital image processing chip-OV0706. By Naman Chauhan.

www.hackster.io

해당 사이트에 코드와 schematic 이 나와 있다.

 

이미지 캡처를 QVGA 사양에서 진행하니, 내부 레지스터 값은 저것과 동일하게 설정한다.

 

하지만 저대로 하면 아마 흑백 사진이 나올 것으로 알고 있다.

OV7670 color settings - Page 1 (eevblog.com)

 

OV7670 color settings - Page 1

Outputting from OV7670 in VGA@30FPS in YUV 4:2:2 (through a frame buffer to a VGA monitor 640x480@60FPS) The only register I changed is 0x11 setting it to 0x00 to enable the PLL with the multiplier of 1 which gives a MUCH better image in terms of noise. Th

www.eevblog.com

그래서 이 VGA color register 를 QVGA 로 재설정 해준다.

참고) Slave address : OV7670 문서에 Write register address = 0x42, Read register address = 0x43 이라 나와 있음

 

 

---

내부 레지스터 설정

---

 

 

 

 

그리고 4-bit 컬러 대역폭에 대해 한 번 짚고 넘어간다. 

List of monochrome and RGB color formats - Wikipedia

 

List of monochrome and RGB color formats - Wikipedia

From Wikipedia, the free encyclopedia This list of monochrome and RGB palettes includes generic repertoires of colors (color palettes) to produce black-and-white and RGB color pictures by a computer's display hardware. RGB is the most common method to prod

en.wikipedia.org

 

12-bit RGB 를 보면 RGB444에 대해 볼 수 있다.

물론, 레지스터 세팅을 변경해서 RGB565 로도 변경할 수 있다.

하지만 RGB444로도 충분한 색 표현이 가능하다. 2^12 = 4096

 

그럼 위에서 세팅한 레지스터 설정값을 camera rom 데이터로 사용한다.


전 포스팅에서 Verilog 코드로 SCCB 및 카메라 세팅까지 적혀 있을 것이다.

[Verilog] OV7670 - more2 :: 블러그 (tistory.com)

 

[Verilog] OV7670 - more2

기존 파일에서 이어서 간다.GitHub - westonb/OV7670-Verilog: Verilog modules required to get the OV7670 camera working GitHub - westonb/OV7670-Verilog: Verilog modules required to get the OV7670 camera workingVerilog modules required to get the O

hipenhw.tistory.com

 

이렇게 카메라 설정을 다 했다면, 다음은 카메라에서 나오는 출력 값을 받아서 메모리로 넣는 작업을 해 줄 차례이다.

 

대략적으로 보면,

 

1) OV7670 카메라의 PCLK 을 기반으로 함.

 

2) 타이밍도에서 VSYNC 가 High 일 때 새 프레임으로 판단

 

3) VSYNC 가 LOW, HREF 가 HIGH 일 때 한 ROW의 시작이라고 판단

 

4) HREF 가 HIGH 인 동안 posedge clk move 에 따라 한 row의 color data[7:0] 값을 메모리에 넣는다.

4-1) 레지스터 세팅으로 값을 바꿔서 RGB 값을 출력하는 경우 2 클럭에 한 pixel data 를 받을 수 있으므로(RGB565, RGB444, ... ) 한 row가 2배의 clock cycle 를 가진다. ex) 640*480 --> grayscale 의 경우 한 row가 640, RGB의 경우 한 row가 1280.

 

5) 다시 VSYNC 가 HIGH 가 될 때 까지 반복한다.

 

 

 

+) 만약 640*480 이미지를 잘라서 넣고 싶은 경우, 카운터를 별도로 둬야 한다.

+) 메모리에 저장을 위해, MEM_i_Addr 과 같은 address input 값을 추가로 필요로 하는데, 이는 posedge PCLK 에 의존해서 1씩 상승하는 카운터인데, RGB의 경우에는 >> 2 를 취해준다.

마우스로 그린 그림

 

이렇게 1차원 배열 메모리에 데이터를 넣었다면, 다음은 이를 다시 가져와서 출력해야 한다.

 


출력은 VGA@60Hz가 기준이다.

+) 카메라 데이터를 바로 디스플레이로 출력 할 수는 없다. 디스플레이가 요구하는 VSYNC, HSYNC 는 카메라에서 나오는 값들로는 애초에 만족이 불가능하고, 타이밍조차 맞지 않는다. 그래서 디스플레이 컨트롤러에 규격화된 신호를 넣어서 출력을 하게 된다.

 

VGA@60Hz (640*480, 60Hz) 는 디스플레이 컨트롤러에 25Mhz 의 clock input 을 요구하고,

Front porch, sync pulse, back porch, visible area 로 구성되어 있다.(x축, y축 모두) (다음 글을 참고하자)

Video Timings: VGA, SVGA, 720p, 1080p - Project F

 

Video Timings: VGA, SVGA, 720p, 1080p

To work with standard monitors and TVs, you need to use the correct video timings. This how to includes the timings for five standard display modes using analogue VGA, DVI, HDMI, or DisplayPort: 640x480 (VGA), 800x600 (SVGA), 1280x720, and 1920x1080 (30 Hz

projectf.io

 

그래서 실제로 640*480 화면을 띄우기 위해서는 저 값들을 모두 더해 800*525 만큼의 카운터를 사용하게 된다.

Making My Own VGA Driver In SystemVerilog — AsyncBit

 

Making My Own VGA Driver In SystemVerilog — AsyncBit

This is a continuation of my posts about my final project for EE271, continued from the Project selection process here , here , and here . The first thing I wanted to get working in this design was the VGA output, as the whole design rests on being able to

www.asyncbit.com

 

 

간단하게 말로 구현을 해 보자면,

출력에 사용하는 25Mhz 로 input clock 을 맞춰 준다.

vsync, hsync 는 모두 보드의 기준에서는 output 인 값이기 때문에, 규칙에 맞게 만들어 주면 된다.

먼저 한 row를 담당하는 hsync의 경우, 

크기가 800인 hcounter 를 생성한다.

hsync 가 0인 경우는 sync pulse 인 경우밖에 없으므로, 나머지 경우는 모두 1이 된다.

hsync = 1, 0~639 픽셀 visible area
hsync = 1, 640 ~ 655 픽셀 front proch
hsync = 0, 656 ~ 751 픽셀 sync pulse
hsync = 1, 752 ~ 799 픽셀 back porch

 

vsync 의 경우, hsync 가 max 값에 다다랐을 때 한 줄 올라가면 된다.

따라서 vsync 는 내부 모듈의 클럭으로 hcounter 에서 나오는 hsync_line_max 값을 사용한다.

table 형태로 보면 조금 더 쉽게 이해 가능하다.

그리고 vsync 내부에도 vcounter 를 둬서 hsync 와 동일하게 설정해준다.(sync pulse에는 vsync 0인 것도 동일)

이제 우리는 각 픽셀을 가리키는 카운터를 얻게 되었다.([9:0] hcounter, [9:0] vcounter)

이걸로 메모리 참조 값을 결정한다.(read address)

 

위 table 에서 연장해서 설명하자면,

hcounter + (length of row pixels)*vcounter 를 하면 1차원 배열에서 불러올 수 있다는 것 정도는 쉽게 파악이 가능하다.

메모리 address 값이 정해졌으니, 클럭에 따라 12bits 픽셀 데이터를 가져와서 R[7:0], G[7:0], B[7:0], hsync, vsync 값을 output 으로 빼 주면 컬러 출력이 가능하다.

 

 


3.5_640x200_cam_final.zip
0.01MB

 

Verilog 파일, DE2-115용 qsf 를 첨부했다.

OV7670-Verilog/src at master · westonb/OV7670-Verilog (github.com)

 

OV7670-Verilog/src at master · westonb/OV7670-Verilog

Verilog modules required to get the OV7670 camera working - westonb/OV7670-Verilog

github.com

이 코드를 참고하여 일부 변형해 사용하였고, 640*480은 bram이 크기가 그만큼 되지 않기 때문에 640*200 크기로 출력 테스트만 진행해 보았다.

 

 

정확한 색상을 나타내지는 않지만, 그럼에도 출력 자체는 정상적으로 동작한다.

 

 


나는 레지스터 값을 어떻게 바꿔야 되는지 솔직히 잘 모르겠어서 일반 640*480 캡처 타이밍을 그냥 줄여서 메모리에 넣어 출력을 해 봤다. (320*240으로 만들었음)

3.6_320x240_cam_final.zip
0.01MB

그리고 이것도 잘 출력 되는 것을 볼 수 있다.

반응형

'Verilog' 카테고리의 다른 글

[Verilog] maxpool2d w. line buffer  (0) 2024.10.31
[Verilog] Conv2d w. line buffer  (0) 2024.10.30
[Verilog] OV7670 - more2  (0) 2024.05.28
[Verilog] SCCB & OV7670 - more1  (0) 2024.05.28
[Verilog] SCCB Interface & OV7670  (0) 2024.04.16

+ Recent posts