四、VGA項目:聯合精簡幀+雙fifo+sobel算法 實現VGA顯示

前言:該項目實際上是在很多基礎的小練習上合成起來的,例如涉及到uart(rs232)的數據傳輸、雙fifo流水線操作、VGA圖像顯示,本次內容在此基礎上又增添了sobel算法,能實現圖像的邊沿監測并VGA顯示。

文章目錄

  • 1.項目描述
  • 2.sobel算法解析:
  • 3.模塊結構示意圖:
  • 4.sobel_ctrl模塊設計
    • 4.1波形設計
    • 4.2代碼
  • 5.VGA_shift模塊設計
    • 5.1 顯示效果示意圖:
    • 5.2 簡易波形示意圖:
    • 5.3 代碼
  • 6.uart_rx模塊設計(直接用之前的設計 略)
  • 7.頂層設計
  • 8.最終的顯示效果:

在這里插入圖片描述

1.項目描述

通過串口助手把 200 行 x200 列數據傳入 FPGA,對應三行三列的九個數進行 sobel算法,把邊緣檢測的結果(198x198的數據)通過 vga 來顯示,用兩種顏色來區分是否是邊界點(邊界用白色顯示,其他用黑色)。

2.sobel算法解析:

在這里插入圖片描述

  1. 把圖像每三行三列的數據分別乘上算子中對應位置的值再相加。然后進行如下運算,得到相應方向(x 和 y)的 Dx 和 Dy。
    Dx=(a3-a1)+(b3-b1)*2+c3-c1;
    Dy=(a1-c1)+(a2-c2)*2+a3-c3;

  2. 對上面求得的 Dx 和 Dy 做平方和的平方根,再取近似值 Dx 和 Dy 的絕對值的和得到 Dxy:

在這里插入圖片描述

  1. 如果 Dxy 的值大于一個閾值(這個閾值是多次嘗試試出來的,本次項目中設置為5),表示該點為邊界點,就讓 VGA 顯示一個白點,否則顯示黑點。

  2. 把計算的結果通過 vga 顯示,顯示器會把是邊界點的以白色像素顯示,不是邊界點的以黑色像素點顯示,于是得到了一幅圖像的輪廓

在這里插入圖片描述

3.模塊結構示意圖:

在這里插入圖片描述

其中:
uart_rx模塊在:手寫一個uart協議——rs232
sobel_ctrl模塊的核心是雙fifo的流水線操作參考(需在此基礎上進行改動):雙fifo流水線操作
VGA_shift模塊參考(原移動框為200x200這里變成198x198,且添加了ram方便rgb圖像的存儲與讀取):VGA接口驅動與圖像顯示動態移動

4.sobel_ctrl模塊設計

4.1波形設計

在這里插入圖片描述

4.2代碼

module sobel_ctrl(input wire clk,input wire rst,input wire [7:0] rx_data,input wire pi_flag,output reg [7:0] rgb,output reg po_flag);
reg[9:0] cnt_col,cnt_row;
reg wr_en1_r,wr_en2_r;
wire wr_en1,wr_en2;reg [7:0] data_in1_r;
wire [7:0] data_in1;
wire [7:0] dout1,dout2;reg [7:0] dout1_t,dout1_tt,dout2_t,dout2_tt;
reg [7:0] rx_data_t,rx_data_tt;
reg rd_en_r;
wire rd_en;reg shift_flag;reg flag_d;reg [7:0] Dx,Dy;reg flag_abs,flag_dxy,flag_rgb;
reg [7:0] abs_dx,abs_dy;
reg [7:0] dxy;parameter COL_MUX=199;
parameter ROW_MUX=199;
parameter VALUR=5;  //不斷調試得到一個合適的閾值// cnt_col
always @(posedge clk) begin if(rst==1'b1) begincnt_col <= 'd0;end else if (pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_col<='d0;endelse if (pi_flag==1'b1) begincnt_col<=cnt_col+1'b1;end
end// cnt_row
always @(posedge clk) begin if(rst==1'b1) begincnt_row <= 'd0;endelse if (cnt_row==ROW_MUX && pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_row<='d0;endelse if (pi_flag==1'b1 && cnt_col==COL_MUX) begincnt_row<=cnt_row+1'b1;end
end// wr_en1_r
assign wr_en1=wr_en1_r;
always @(posedge clk) begin if(rst==1'b1) beginwr_en1_r <= 'd0;endelse if (cnt_row=='d0) beginwr_en1_r<=pi_flag;endelse if (cnt_row>'d1 && cnt_row<ROW_MUX) beginwr_en1_r<=shift_flag;end
end// wr_en2_r
assign wr_en2=wr_en2_r;
always @(posedge clk) begin if(rst==1'b1) beginwr_en2_r <= 'd0;end else if (cnt_row>'d0 && cnt_row<ROW_MUX) beginwr_en2_r<=pi_flag;endelsewr_en2_r<='d0;
end// data_in1_r
assign data_in1=data_in1_r;
always @(posedge clk) begin if(rst==1'b1) begindata_in1_r<= 'd0;end else if (cnt_row=='d0) begindata_in1_r<=rx_data;endelse if (cnt_row>'d1 && cnt_row<ROW_MUX) begindata_in1_r<=dout2;end
end// rd_en_r
assign rd_en=rd_en_r;always @(posedge clk) begin if(rst==1'b1) beginrd_en_r<= 'd0;end else if (cnt_row>'d1) beginrd_en_r<=pi_flag;endelse rd_en_r<='d0;
end// shift_flag
always @(posedge clk) begin if(rst==1'b1) beginshift_flag <= 'd0;end elseshift_flag<=rd_en_r;
end// dout1_t,dout1_tt,dout2_t,dout2_tt,rx_data_t,rx_data_tt
always @(posedge clk) begin if (shift_flag==1'b1) begin{dout1_tt,dout1_t}={dout1,dout1_t};{dout2_tt,dout2_t}={dout2,dout2_t};{rx_data_tt,rx_data_t}={rx_data_t,rx_data};end
endalways @(posedge clk) begin if(rst==1'b1) beginflag_d <= 'd0;end else if (cnt_row>=2 && cnt_col>2) beginflag_d<=rd_en_r;end
endalways @(posedge clk) begin if(rst==1'b1) beginDx <= 'd0;Dy <= 'd0;end else if (flag_d==1'b1) beginDx<=(dout1_tt-dout1)+(dout2_tt-dout2)<<1+(rx_data_tt-rx_data);Dy<=(dout1_tt-rx_data_tt)+(dout1_t-rx_data_t)<<1+(dout1-rx_data);endendalways @(posedge clk) begin if (rst==1'b1) beginflag_abs<='d0;flag_dxy<='d0;flag_rgb<='d0;po_flag<='d0;endelse{po_flag,flag_rgb,flag_dxy,flag_abs}<={flag_rgb,flag_dxy,flag_abs,flag_d};
end// abs_dx
always @(posedge clk) begin if(rst==1'b1) beginabs_dx<='d0;end else if (flag_abs==1'b1 ) beginif (dx[7]==1'b1) beginabs_dx<=(~Dx)+1'b1;endelseabs_dx<=Dx;end
end// abs_dy
always @(posedge clk) begin if(rst==1'b1) beginabs_dy <= 'd0;end else if (flag_abs==1'b1) beginif (dy[7]==1'b1) beginabs_dy<=(~Dy)+1'b1;endelse abs_dy<=Dy;end
end// dxy
always @(posedge clk) begin if(rst==1'b1) begindxy<= 'd0;end else if (flag_dxy==1'b1) begindxy<=abs_dx+abs_dy;end
end// rgb
always @(posedge clk) begin if(rst==1'b1) beginrgb <= 'd0;end else if (flag_rgb==1'b1) beginif (dxy>VALUR) beginrgb<=8'hff;endelsergb<=8'h00;end
endsfifo_8X256 sfifo1_8X256 (.clk(clk),      // input wire clk.din(data_in1),      // input wire [7 : 0] din.wr_en(wr_en1),  // input wire wr_en.rd_en(rd_en),  // input wire rd_en.dout(dout1),    // output wire [7 : 0] dout.full(),    // output wire full.empty()  // output wire empty
);sfifo_8X256 sfifo2_8X256 (.clk(clk),      // input wire clk.din(rx_data),      // input wire [7 : 0] din.wr_en(wr_en2),  // input wire wr_en.rd_en(rd_en),  // input wire rd_en_r.dout(dout2),    // output wire [7 : 0] dout.full(),    // output wire full.empty()  // output wire empty
);
endmodule

5.VGA_shift模塊設計

5.1 顯示效果示意圖:

在這里插入圖片描述

5.2 簡易波形示意圖:

在這里插入圖片描述

5.3 代碼

module vga_shift(input wire sclk,//50mhzinput wire clk_25,input wire rst,input wire [7:0] rgb_in,input wire pi_flag,output reg hsync,output reg vsync,output reg [7:0] rgb);parameter HSYNC_END=95;
parameter CNT_H_END=799;parameter VSYNC_END=1;
parameter CNT_V_END=524;parameter RED=8'b11100000;
parameter GREEN=8'b00011100;
parameter BLUE=8'b00000011;
parameter WHITE=8'b11111111;parameter ADDR_MUX=16'd39203;
reg [9:0] cnt_h;
reg [9:0] cnt_v;reg [8:0] x;
reg [8:0] y;reg flag_x;
reg flag_y;reg [15:0] addra,addrb;
wire [7:0] doutb;// cnt_halways @(posedge clk_25) begin if(rst==1'b1) begincnt_h<= 'd0;end else if (cnt_h==CNT_H_END) begincnt_h<='d0;endelse cnt_h<=cnt_h+1'b1;end // hsyncalways @(posedge clk_25) begin if(rst==1'b1) beginhsync<= 'd1;endelse if (cnt_h==CNT_H_END) beginhsync<='d1;end else if (cnt_h==HSYNC_END) beginhsync<='d0;endend// cnt_v
always @(posedge clk_25) begin if(rst==1'b1) begincnt_v <= 'd0;end else if (cnt_v==CNT_V_END && cnt_h==CNT_H_END) begincnt_v<='d0;endelse if (cnt_h==CNT_H_END) begincnt_v<=cnt_v+1'b1;end
end// vsync
always @(posedge clk_25) beginif(rst==1'b1) beginvsync <= 'd1;end else if (cnt_v==VSYNC_END && cnt_h==CNT_H_END) beginvsync<='d0;endelse if (cnt_v==CNT_V_END && cnt_h==CNT_H_END) beginvsync<='d1;endend
// x
always @(posedge clk_25) begin if(rst==1'b1) beginx <= 'd0;end else if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && flag_x=='d0) beginx<=x+1'b1;endelse if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && flag_x=='d1) beginx<=x-1'b1;end
end// flag_x
always @(posedge clk_25) begin if(rst==1'b1) beginflag_x<= 'd0;end else if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && x=='d441 && flag_x=='d0) beginflag_x<='d1;endelse if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && x=='d1 && flag_x=='d1) beginflag_x<='d0;end
end//y
always @(posedge clk_25) begin if(rst==1'b1) beginy<= 'd0;end else if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && flag_y=='d0) beginy<=y+1'b1;end else if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && flag_y=='d1) beginy<=y-1'b1;end
end// flag_y
always @(posedge clk_25) begin if(rst==1'b1) beginflag_y <= 'd0;end else if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && y=='d281 && flag_y<='d0) beginflag_y<='d1;endelse if (cnt_h==CNT_H_END && cnt_v==CNT_V_END && y=='d1 && flag_y<='d1) beginflag_y<='d0;end
end// rgb 
always @(posedge clk_25) begin if(rst=='b1) beginrgb<= 'd0;end//注意198x198像素時,白框范圍需要改變else if (cnt_h>=144+x && cnt_h<=341+x && cnt_v>=35+y && cnt_v<=232+y) beginrgb<=doutb;endelse if (cnt_h>=144 && cnt_h<=783) beginif (cnt_v>=35 && cnt_v<=194) beginrgb<=RED;endelse if (cnt_v>=195 && cnt_v<=354) beginrgb<=GREEN;endelse if (cnt_v>=355 && cnt_v<=514) beginrgb<=BLUE;endend elsergb<='d0;end// addra  這里注意寫ram的時鐘為50mhz,讀ram的時鐘為25mhz(VGA的時鐘)
always @(posedge sclk) begin if(rst) beginaddra<= 'd0;endelse if (pi_flag==1'b1 && addra==ADDR_MUX) beginaddra<='d0;endelse if (pi_flag==1'b1) beginaddra<=addra+1'b1;end end// addrb 注意ram讀數據相對于讀地址有一拍延遲,所以地址要早一拍給出
always @(posedge clk_25) begin if(rst==1'b1) beginaddrb <= 'd0;end else if (cnt_h>=144+x-1 && cnt_h<=341+x-1 && cnt_v>=35+y && cnt_v<=232+y && addrb==ADDR_MUX) beginaddrb<='d0;endelse if (cnt_h>=144+x-1 && cnt_h<=341+x-1 && cnt_v>=35+y && cnt_v<=232+y) beginaddrb<=addrb+1'b1;end
endasblk_mem_8x198x198 your_instance_name (.clka(sclk),    // input wire clka.wea(pi_flag),      // input wire [0 : 0] wea.addra(addra),  // input wire [15 : 0] addra.dina(rgb_in),    // input wire [7 : 0] dina.clkb(clk_25),    // input wire clkb.addrb(addrb),  // input wire [15 : 0] addrb.doutb(doutb)  // output wire [7 : 0] doutb
);endmodule

6.uart_rx模塊設計(直接用之前的設計 略)

7.頂層設計

module top_sobel(input wire clk,//50mhzinput wire rst,input wire rx,output wire vsync,output wire hsync,output wire [7:0]rgb);wire clk_out25;
wire clk_out50;wire rx_data;
wire pi_flag_rx_to_sobel;
wire pi_flag_sobel_to_vga;wire [7:0] rgb_in;clk_wiz_gen25 instance_name(// Clock out ports.clk_out50(clk_out50),     // output clk_out50.clk_out25(clk_out25),     // output clk_out25// Clock in ports.clk_in50(clk));      // input clk_in50uart_rx inst_uart_rx (.clk     (clk_out50),.rst     (rst),.rx      (rx),.po_data (rx_data),.po_flag (pi_flag_rx_to_sobel));sobel_ctrl  inst_sobel_ctrl (.clk     (clk_out50),.rst     (rst),.rx_data (rx_data),.pi_flag (pi_flag_rx_to_sobel),.rgb     (rgb_in),.po_flag (pi_flag_sobel_to_vga));vga_shift inst_vga_shift (.sclk    (clk_out50),.clk_25  (clk_out25),.rst     (rst),.rgb_in  (rgb_in),.pi_flag (pi_flag_sobel_to_vga),.hsync   (hsync),.vsync   (vsync),.rgb     (rgb));endmodule

8.最終的顯示效果:

上位機通過MATLAB處理,用友善助手下發原圖像數據:

在這里插入圖片描述
經過一系列圖像處理后,最終在vga的顯示效果:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10778.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10778.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10778.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡單的DbUtils工具類【精細】

目錄 單條通用增刪改方法 1.創建maven項目&#xff0c;并加載依賴 2.創建數據庫連接工具類(Dbutils類) 3.創建一個執行器(SqlExecutor類) 4.通用(增&#xff0c;刪&#xff0c;改)方法 1.創建方法 2.創建userInfo實體類 3.創建測試類&#xff0c;測試增&#xff0c;刪&#xf…

探索數據結構:樹與二叉樹

?? 歡迎大家來到貝蒂大講堂?? &#x1f388;&#x1f388;養成好習慣&#xff0c;先贊后看哦~&#x1f388;&#x1f388; 所屬專欄&#xff1a;數據結構與算法 貝蒂的主頁&#xff1a;Betty’s blog 1. 樹 1.1. 樹的定義 樹是一種非線性的數據結構&#xff0c;它是由n&a…

ORA-609頻繁出現在alert.log,如何解決?

ORA-609就alertlog中比較常見的一個報錯&#xff0c;雖然并沒有太大的影響&#xff0c;但是頻繁的出現在alert log也是很讓人厭煩的事情&#xff0c;本文介紹如何排查解決ORA-609問題。 1.ORA-609官方定義 could not attach to incoming connection Cause Oracle process cou…

【SRC實戰】前端脫敏信息泄露

挖個洞先 https://mp.weixin.qq.com/s/xnCQQCAneT21vYH8Q3OCpw “ 以下漏洞均為實驗靶場&#xff0c;如有雷同&#xff0c;純屬巧合 ” 01 — 漏洞證明 一、前端脫敏&#xff0c;請求包泄露明文 “ 前端脫敏處理&#xff0c;請求包是否存在泄露&#xff1f; ” 1、獲取驗…

|Python新手小白中級教程|第二十八章:面向對象編程(類定義語法私有屬性類的繼承與多態)(4)

文章目錄 前言一、類定義語法二、私有方法和私有屬性1.私有屬性2.私有方法 三、類“繼承”1.初識繼承2.使用super函數調用父類中構造的東西 四、類“多態”1.多態基礎2.子類不同形態3.使用isinstance函數與多態結合判斷類型 總結 前言 大家好&#xff0c;我是BoBo仔吖&#xf…

6818Linux內核開發移植

Linux內核開發移植 Linux內核版本變遷及其獲得 Linux是最受歡迎的自由電腦操作系統內核&#xff0c; 是一個用C語言寫成&#xff0c; 并且符合POSIX標準的類Unix操作系統 Linux是由芬蘭黑客Linus Torvalds開發的&#xff0c; 目的是嘗試在英特爾x86架構上提供自由免費的類Un…

Task Office for Mac v9.0激活版:任務管理新境界

還在為繁瑣的任務管理而煩惱嗎&#xff1f;Task Office for Mac為您帶來全新的任務管理體驗。簡潔明了的界面設計&#xff0c;讓您輕松上手&#xff1b;強大的任務管理和項目管理功能&#xff0c;讓您輕松掌握任務進度&#xff1b;多用戶協作功能&#xff0c;讓團隊協作更加高效…

ubuntu24.04安裝ros

ubuntu24.04安裝ros 踩坑 踩坑 目前安裝人數比較少&#xff0c;沒有較為詳細的博客&#xff0c;參考官網的鏈接 http://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debians.html 同時在如下的一步中會找不到網址報錯&#xff0c;此時可以參考https://blog.51cto.c…

Excel辦公技巧之下拉菜單

在日常辦工中&#xff0c;經常需在單元格中輸入特定的值&#xff0c;此時我們可以使用下拉菜單解決&#xff0c;輸入錯誤和錯誤值&#xff0c;可以一勞永逸的解決固定數據輸入問題。 使用Excel下拉菜單時&#xff0c;它在數據輸入和驗證方面發揮著重要作用通過點擊單元格的下拉…

學習筆記-Vue3中Hook函數

什么是Hook函數 Hook翻譯過來是鉤子的意思&#xff0c;其本質上是一組可復用的函數。簡單理解來說&#xff0c;你能夠在不同的組件中&#xff0c;實現相同的代碼邏輯&#xff0c;以達到代碼復用、提高維護性的效果。那為何叫’鉤子’呢&#xff0c;我的理解是&#xff1a; 它可…

商業數據分析--時間序列圖及趨勢分析

繪制時間序列圖,并指出存在什么樣的狀態如上兩圖: 可見狀態:從時間序列圖可以看出,這些數據存在明顯的季節性波動,每年的第4季度值都最高,而第2季度值最低。同時也存在一些下降的趨勢。 通過引進虛擬變量,建立多元線性回歸模型。答: 通過引入虛擬變量,我們可以建立如下的…

Oracle數據庫之多表查詢、層次查詢(五)

目錄 前言 Oracle 的連接條件的類型 多表查詢 1. 使用JOIN關鍵字 2. 使用WHERE子句進行多表查詢 3. 子查詢 4. EXISTS關鍵字 5. 集合運算 6. 注意事項&#xff1a; 層次查詢 前言 Oracle 的連接條件的類型 等值連接不等值連接外連接自連接 多表查詢 在Oracle數據…

商場學習之微服務

前言 寒假前在新電腦上配置了java環境&#xff0c;maven倉庫&#xff0c;node,js&#xff0c;navicat&#xff0c;MySQL&#xff0c;linux&#xff0c;vmware等環境&#xff0c;創建了6個mysql數據庫&#xff0c;77張表。 如此多的表&#xff0c;字段&#xff0c;去手寫基礎…

Web入門——三欄布局頁面

前置知識 內外邊距 內邊距(padding)&#xff1a; padding是元素邊框與其內容之間的空間。也就是說&#xff0c;如果你給一個元素設置了內邊距&#xff0c;這個空間會作為元素內容與元素邊框之間的緩沖區域。設置內邊距會使元素本身變大。例如padding:10px就創建了10像素的空間…

Qt之QMqtt 發送圖片數據

簡述 MQTT(消息隊列遙測傳輸)是ISO標準下基于發布/訂閱范式的消息協議;它工作在TCP/IP協議族上,是為硬件性能低下的遠程設備以及網絡狀況糟糕的情況下而設計的發布/訂閱型消息協議,為此,它需要一個消息中間件; MQTT是一個基于客戶端-服務器的消息發布/訂閱傳輸協議;MQT…

Ubuntu設置中午輸入法

本篇博客將指導您如何在Ubuntu系統中設置中文輸入法&#xff0c;讓您能夠輕松地進行中文輸入。 準備工作 在開始之前&#xff0c;請確保您的系統已經更新到最新版本。這可以通過以下命令來完成&#xff1a; sudo apt update && sudo apt upgrade這將幫助確保所有的軟…

Docker in Docker(DinD)原理與實戰

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《Docker幻想曲&#xff1a;從零開始&#xff0c;征服容器宇宙》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、Docker簡介 2、Docker …

使用 AI Assistant for Observability 和組織的運行手冊增強 SRE 故障排除

作者&#xff1a;Almudena Sanz Oliv, Katrin Freihofner, Tom Grabowski 通過本指南&#xff0c;你的 SRE 團隊可以實現增強的警報修復和事件管理。 可觀測性 AI 助手可幫助用戶使用自然語言界面探索和分析可觀測性數據&#xff0c;利用自動函數調用來請求、分析和可視化數據…

Harmony 添加library依賴庫步驟

在Harmony添加library依賴庫步驟如下&#xff1a; 1、在library中定義名字 在library中的oh-package.json5中定義library對外的名字是什么&#xff1a;格式是 “name”:“ohos/名字” {"name": "ohos/library_name" //名字 }2、在項目目錄build-profi…

windows系統安裝Ubuntu子系統

安裝前先在 控制面板 中打開 程序與功能選項 &#xff0c;點擊 啟用或關閉Windows功能&#xff1a; 勾選 適用于 Linux的Windows子系統 和 虛擬機平臺 、 Hyper-v 。 重啟電腦后再 Microsoft Store Windows應用商店 中下載合適的Ubuntu版本。 運行Ubuntu程序&#xff0c;如出現…