FPGA圖像處理系列——基於ZEDBoard構建圖像處理通路(Block Ram版本)

注:本博文的工程文件位於:http://download.csdn.net/detail/lzy272942518/8845415

對於集FPGA和ARM於一體的Zynq系列平臺來說,圖像處理是Zynq平臺主要的應用方向之一。圖像採集部分是圖像處理系統的重要組成部分,它通過圖像傳感器將外部的圖像信息採集進來,轉換爲數字信號存儲到系統的幀存儲器中。目前在工業圖像採集領域,人們常用的兩種圖像傳感器爲CCD與CMOS圖像傳感器。CCD一般輸出帶制式的模擬信號,需要經過視頻解碼器得到數字信號才能傳入控制器中,而CMOS圖像傳感器直接輸出數字信號,可以直接與控制器進行連接。隨着集成電路設計技術和工藝水平的提高,CMOS圖像傳感器像素單元的數量和採集速度都不斷增大。由於CMOS器件的高速性,近年來,越來越多的高速圖像採集系統採用CMOS圖像傳感器作爲圖像採集器件。

常用CMOS傳感器品牌以及選擇:

Sony: 日產CMOS,高靈敏度和低噪聲,偏重於攝影拍照,但開發的參考資料比較少;

Aptina:CMOS系統按拍照架構設計,開發流程較爲繁瑣,且價格偏高,成像品質性價比略高;

OmniVision:CMOS系統架構最適合圖像採集,開發資料較充足,各系列間兼容性好。

 數字圖像採集平臺架構如圖所示。系統通過CMOS傳感器OV7725將圖像高速採集進Zedboard並存儲到BRAM,然後通過VGA控制模塊將圖像顯示出來。


我們要在Vivado中實現以下功能:

l  驅動CMOS圖像傳感器OV7725,實現圖像採集;

l  將圖像存放到Block Ram中;

l  圖像的VGA顯示;

該實例將會涉及CMOS傳感器的接口及驅動、CMOS圖像傳感器的寄存器參數配置、BRAM存放策略等方面。

1.OV7725的引腳以及驅動

   OV7725的引腳很多,但本系統中用到的OV7725模塊只包含以下一些引腳:

D0~D9: CMOS輸出的10位數據口.本實例只用到D2~D9。

RESET: CMOS輸入信號,復位引腳,低電平有效。本實例將其置空

PWDN: CMOS輸入信號,休眠模式選擇,0爲正常模式,1爲休眠模式。本實例將其置空

PCLK:  CMOS輸出的像素時鐘

XCLK:  CMOS輸入的時鐘信號,本實例採用25MHz。

HREF:   CMOS輸出的行同步信號

VSYNC: CMOS輸出的幀同步信號

SIOC:   CMOS寄存器的IIC時鐘輸入

SIOD:   CMOS寄存器的IIC數據輸入/輸出

因爲用到的引腳數量並不多,因此我們選擇用Zedboard上JA,JB兩組Pmod接口與OV7725模塊相連。OV7725的驅動包含兩個操作:1.配置寄存器 2.根據傳入的時序信號(PCLK,HREF,VSYNC),對傳入數據進行拼接,組合成RGB像素。

n  配置寄存器

OV7725的正常工作需要寄存器的正確配置。寄存器的配置遵從IIC協議,在PL提供的IIC時鐘驅使下,向不同功能的寄存器地址寫入數據。本實例構建了一個IIC的主模塊,寄存器配置指令只需要兩條即可:

0x1100;//11爲CLKRC寄存器,設置爲00值,採用內部時鐘

0x1206;//分辨率設置爲VGA 640x480,像素輸出格式設置爲RGB565

n  拼接數據得到像素RGB565

 OV7725像素格式爲RGB565時,時序圖如下:


當幀同步信號VSYNC出現有效邊沿之後,在HREF爲高電平時,第一個PCLK上升沿讀取第一個byteD7~D0)。此時要注意,這個byte並不代表第一個像素,而是第一個像素的R[4:0]以及G[5:3],第二個PCLK上升沿讀取的byte則是第一個像素的G[2:0]以及B[4:0]。當第二個PCLK上升沿到來時,將這兩個byte組合成一個完整的像素,就得到了第一個像素。以此類推,採集一行數據(640x2個數據),就得到640個像素值。當採集完480行的時候,就完成了一幀數據的採集。


OV7725VGA時序可知,每一行有效時間爲640x2pclk,無效時間爲144x2pclk,每一行花費時間爲784x2PCLK時鐘;而每一幀總行數是510(有效行數是480);因此採集一幀數據的時間是784*510x2pclk的時間。

2.幀緩存(FrameBuffer)的實現

    爲了方便進行顯示,以及後續的圖像處理,需要存儲採集的圖像。在vavadoIP catalog界面,在search 欄輸入block mem,下方ip列表會顯示出block memorygenerator,如圖所示:


雙擊上圖的藍色區域,打開ip覈定制界面。在Basic板塊的Memory Type選項設置成Simple dual portram,然後在port A options port A width 設置成48bit,depth設置成76800.enable port type設置成 always enabled。在port B options port B width 設置成12bit,此時dept會自動設置成307200.同樣,“enable port type設置成 always enabled

那麼,讀者朋友們會注意到剛纔port A 的端口位寬是48bit。我們知道,要進行vga顯示,zedboardVGA部分RGB每個通道都是4bit,顯示一個像素需要12bit。因此,我們存儲一個像素採用的位寬也是12bit,一共存儲的像素數量爲640x480 = 307200個像素。既然這樣,那爲什麼存進RAM的位寬不是12bit呢?這是因爲,ip核的寫入端深度允許的範圍只有2-130172,而讀端口就沒有這種限制,爲了存儲一幀圖像,存儲的位寬就需要增加。我們需要另寫一個像素整合存儲到ram的機制,使連續的四個像素在存儲之前先整合成一個12x4bit的變量。

OV7725的採集模塊代碼如下:

 

module ov7725_capture(

input pclk,

input vsync,

input href,

input[7:0] d,

output[18:0] addr,

output[47:0] dout_48bit,

output reg we

);

reg [15:0] d_latch;

reg [18:0] address;

reg [18:0] address_next; 

reg [1:0] wr_hold;   

reg [47:0] dout_48bit_reg;

reg [1:0] cnt;

initial d_latch = 16'b0;

initial address = 19'b0;

initial address_next = 19'b0;

initial wr_hold = 2'b0;

initial dout_48bit_reg = 48'b0;    

initial cnt = 2'b0;       

assign addr =    address;

 

always@(posedge pclk)begin

 if(vsync ==1) begin

          address <=19'b0;

          address_next <= 19'b0;

          wr_hold <=  2'b0;

          cnt <=  2'b0;

          end

       else begin

          address <= address_next;

          we      <= wr_hold[1];

          wr_hold <= {wr_hold[0] , (href &&( ! wr_hold[0])) };

          d_latch <= {d_latch[7:0] , d};

 

          if (wr_hold[1] ==1 )begin

             

             address_next <=address_next+1;

             if(cnt >= 3)

                cnt <= 0;

             else

                cnt <= cnt + 1;

             

             case (cnt)

                 0 : dout_48bit_reg[11:0]  <= {d_latch[15:12] , d_latch[10:7] ,d_latch[4:1] };

                 1 : dout_48bit_reg[23:12]<= {d_latch[15:12] , d_latch[10:7] , d_latch[4:1] };

                 2 : dout_48bit_reg[35:24]<= {d_latch[15:12] , d_latch[10:7] , d_latch[4:1] };

                 3 : dout_48bit_reg[47:36]<= {d_latch[15:12] , d_latch[10:7] , d_latch[4:1] };

             endcase;        

          end

 

       end;

 end

 assign  dout_48bit =  dout_48bit_reg;     

endmodule    

3.VGA顯示的實現

本實例中實現的VGA模塊頂視圖如圖所示:


VGA部分除了產生VGA信號,將像素信號接到VGARGB三通道以外,還有一個比較重要的功能,就是產生讀frame buffer的地址信號frame_addr

利用vga的列計數器和行計數器,可以輕鬆產生frame_addr:當行計數器範圍在0-479,列計數器範圍在0-639時,每來一個vga時鐘信號,地址值加1。當行計數值等於480時,地址值清零。產生frame_addr的關鍵代碼如下:

           if(vCounter  >= 480)

                           frame_addr  <= 19'b0;

                    else begin

                               if (hCounter  < 640)

                                     frame_addr <= frame_addr +1;

                           end

4.具體實現步驟:

   (1)啓動Vivado2013.3,在工作目錄(例如D\xup\Zed)下創建新工程Cam_OV7725_ImageShow.

   (2)選擇RTL Project, target language選擇verilog, part orboard部分選擇xc7z020clg484-3,完成工程的創建

   3)添加verilog文件:在vivado主頁面左邊的project manager一欄,點擊Add Sources,,勾選Add Existing Block Design Source,選擇Add Files,添加/verilog_files文件夾下的所有v文件。記住勾選“Copy source into project,如圖所示:


添加幀緩存ip核:點擊IP Catalog,在search欄輸入block mem,添加Block Memory Generator ip核,按照以下3圖設置ip參數:





(4)添加時鐘ip核:在IP Catalog中的search欄輸入clock,選取clocking wizard ip,雙擊進入配置界面。元件名字改爲clk_gen,output clocks板塊增加兩個時鐘輸出:50MHz25MHz,並勾去下方的resetlocked。如圖所示:


(4)添加引腳配置文件:再一次點擊Add Sources,,勾選Add or Create Constraints,選擇Add Files,添加/constraints文件夾下的zed.xdc文件。

(5)保存,點擊Generate Bitstream,綜合、實現,生成bit文件。


系統調試及板級驗證

將OV7725模塊連接到Pmod轉接板,轉接板連上Zedboard的JA,JB口,上電,然後下載bit文件。可以看到紅色的LED[0]亮起,說明寄存器配置完畢,也可以按下BTNU按鍵再次進行寄存器配置。通過VGA顯示器,可以看到OV7725採集到的圖像,如圖所示。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章