系統框圖
前面我們設計了基于FPGA的靜態圖片顯示,并對一幅彩色圖片提取了灰度,學習了RGB轉Gray算法。這是基于一幅靜態圖片的,那么后面我們要模擬一下一幅動態圖片的顯示,最終對動態數據進行濾波、邊緣檢測等算法,下來我們首先來建立一個基于FPGA的動態圖片顯示基礎框架,本實驗內容為:由PC端上位機軟件通過串口發送一幅圖像數據至FPGA,FPGA內部將圖像數據存儲,最后掃描到VGA屏幕上顯示。
從系統框圖上我們可以看到,可以劃分為三個部分進行設計,一個是串口接收部分,然后是RAM數據存儲部分,最后是VGA驅動顯示部分。這里串口接收部分只需要用到串口接收代碼,代碼很多書上都有,我這里就不貼出來了,
數據存儲部分需要使用的是雙口RAM IP Core,一端將數據寫入RAM中,一端將數據讀出來用VGA顯示,下面是基于Vivado的雙口RAM IP Core調用方法。
打開IP Catalog,選擇block memory Generater
這里按如圖所示選擇,我這里將寫使能信號去掉,wea也可以代表寫使能
設置寫數據位寬和深度,使能選擇always enable
設置讀數據參數
這里因為我們是往RAM里面寫數據,所以這里不需要添加初始化RAM文件
點擊OK
最后generate綜合完成。
雙口RAM IP調用完成以后,接下來是在用頂層文件把串口接收模塊和存儲模塊和VGA驅動模塊連接起來。這里需要注意的是,雙口RAM的讀地址和寫地址都是需要在其他模塊進行計數的,我這里把寫使能信號設置為標串口接收完成標志即rx_done,讀使能設置為always enable。對于VGA顯示圖片部分可以參考這個圖像處理系列文章第一篇基于FPGA的靜態圖片顯示。
按照系統流圖,還需要添加串口接收和發送模塊,這里我們可以把以前做過的串口代碼直接拿過來用,代碼都是可以移植的只需要稍微修改端口頂層例化即可。按照系統框圖把頂層例化好之后,接下來就是仿真了,真是慚愧我到現在才學會了串口的仿真技巧,其實是自己悟到的,如下圖,我這里的串口接收是以發送波特率的16倍進行接收的,在仿真時,波特率9600還是很慢,所以,我直接將接收波特率這里設置成50Mhz的兩個時鐘周期,那么發送也就是32個50Mhz的時鐘周期,這里是50Mhz的原因是因為但是寫串口接收發送這塊的時候,使用的板子的系統時鐘是50Mhz,這里移植的時候也要注意,最好使用PLL將系統時鐘分頻成50Mhz再給接收發送這兩個模塊。仿真圖我就不貼了,這里把testbench的核心代碼部分貼出來!
1 //串口接收模塊波特率查找表
2 always @(posedge mclk or negedge rst_n) begin
3 if(!rst_n)
4 bps_DR <= 0;
5 else begin
6 case(baud_set)
7 0: bps_DR <= 324;//bps_9600x16
8 //0: bps_DR <= 1;//bps_9600x16 just test
9 1: bps_DR <= 162;//bps_19200x16
10 2: bps_DR <= 80;//bps_38400x16
11 3: bps_DR <= 53;//bps_57600x16
12 4: bps_DR <= 26;//bps_115200x16
13 default: bps_DR <= 324;//bps_9600x16
14 endcase
15 end
16 end
17 //串口發送模塊波特率查找表DR_LUT
18 always @(posedge mclk or negedge rst_n)begin
19 if(!rst_n)
20 bps_DR <= 16'b0;
21 else begin
22 case(baud_set)
23 0: bps_DR <= 5207;//bps_9600
24 //0: bps_DR <= 31;//bps_9600 just test
25 1: bps_DR <= 2603;//bps_19200
26 2: bps_DR <= 1302;//bps_38400
27 3: bps_DR <= 867;//bps_57600
28 4: bps_DR <= 433;//bps_115200
29 default: bps_DR <= 5207;//bps_9600
30 endcase
31 end
32 end
那么參數調整小了,仿真這塊這么寫呢?在test_bench文件中,我直接調用上面的工程頂層和串口發送模塊,只需要將發送模塊的數據給頂層模塊,這樣就方便了查看接收模塊是否正確,
1 VGA_display_picture uut_VGA_display_picture(
2 .clk (clk),//50mhz
3 .rst_n (rst_n),
4 .lcd_data (lcd_data),
5 .lcd_hs (lcd_hs),
6 .lcd_vs (lcd_vs),
7 .baud_set (baud_set),//uart baud
8 .data_byte (data_byte),
9 .send_en (send_en)
10
11 );
12 always #4 clk = ~clk;
13
14 always #10 mclk = ~mclk;
15
16 UART_Byte_Tx uut_UART_Byte_Tx(
17 .mclk (mclk),
18 .rst_n (rst_n), 19 .send_en (send_en),//時鐘分頻使能
20 .baud_set (4'b0),//選擇波特率
21 .data_byte (data_byte),//需要發送的信號
22 .tx_done (),//標志串口結束信號
23 .rs232_tx (rs232_rx)//串口信號輸出
24 );
然后是寫激勵,在工程代碼中我們盡量少用for循環,但是在測試文件中便可以使用for循環來減少激勵的書寫量,提高仿真效率,這里的#7040是我在上面仿真的時候計算出來的,為什么是延時7040呢?這是因為上面串口發送模塊波特率設置的是32個50Mhz時鐘周期,那么它就是每隔7040ns會發送一次,同樣的接收模塊也是每隔7040ns接收一次,所以我這里每隔7040ns給一次數據,就可以實現仿真上連續發送了。
1 integer i;
2
3 initial begin
4 clk = 0;
5 mclk = 0;
6 rst_n = 0;
7 send_en = 0;
8 data_byte = 0;
9 #100; rst_n = 1'b1;
10 send_en = 1;
11 for(i = 1; i <= 100; i = i + 1)begin
12 #7040 data_byte = i;
13 end
14 end
這樣硬件部分其實就已經完成了,現在我們需要的是一幅圖片的像素數據然后通過上位機串口調試助手發送給FPGA開發板,首先找一幅200x200的圖像數據,因為我這里是開出的200x200的顯示區域(參考如上鏈接),使用MATLAB就可以直接生成你想要的這幅圖像的像素數據,這里的MATLAB代碼我給出鏈接:http://pan.baidu.com/s/1dFAMPjj 密碼:uu71,只需要修改下面如圖所示的imread(””)這里就好了,就可以直接轉化你想轉化的圖片。注意圖片必須和這個.m文件在同一個文件夾,最后生成一個txt文件,這個txt文件里面的數據就是我們所需要的圖像數據
其實這三個文件里面的數據是完全相同的,那為什么不直接用前面那兩個文件的數據呢?這里博主親身體驗過,那是絕對不行的,因為前面兩個文件的數據其實是有回車的,可能會被串口默認為一個字符,txt文件中是沒有的,空格的話這里被串口調試助手忽略了!如下圖,點擊發送就OK啦!
最后通過串口發送到開發板最終顯示的效果如圖所示,我們可以看到這里MATLAB代碼生成的就直接是彩色圖像,最終發送過程中其實是動態顯示的,因為串口波特率的速度比VGA的掃描速度是要慢很多的
串口發送小姐姐圖片用VGA顯示出來
最后經過測試我們的lena女神的顯示效果最好了,看來真不愧是我們圖像處理屆的模特鼻祖呀!最后看來,顯示效果還是不錯的呢!
評論
查看更多