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图像的存储与读取):

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.mzph.cn/news/832212.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

假期的最后一天...

今天是假期最后一天&#xff0c;这个假期我也跑了不少高速&#xff0c;说实话&#xff0c;看到了梅大高速塌方事故&#xff0c;心情一直不是滋味... 我就在思考&#xff0c;我们究竟在追求什么&#xff1f; 有人说生命是脆弱的&#xff0c;也有人说生命是顽强的&#xff0c;是呀…

【C++风云录】科学可视化与数据分析:从特性探索到高级应用实践

科技赋能&#xff1a;六大工具助力你的职业生涯 前言 在本文中&#xff0c;我们将对六种广泛使用的计算机视觉和图形库进行深入介绍&#xff0c;这些库包括VTK、D3.js、OpenCV、Eigen、Boost和PCL。每个章节都会包含库的基本介绍&#xff0c;系统要求&#xff0c;安装和配置过…

Unity MeshRenderer 入门

概述 在项目制作过程中&#xff0c;肯定缺少不了模型的使用&#xff0c;那就一定接触过MeshRenderer&#xff0c;也许还有你不理解的地方&#xff0c;接下来让我们来学习一下这部分的内容吧。 Mesh Filter&#xff08;网格过滤器&#xff09; Mesh:提供一个网格的参考&#xf…

医学图像处理:nii格式转换(3D切片为2D)

目录 NIFTI文件结构 读取NII文件 ITK-SNAP安装 使用方法 NII转PNG NIFTI文件结构 NIFTI 格式&#xff0c;是一种用于存储和交换医学成像数据的文件格式&#xff0c;特别适用于神经影像学领域。NIFTI文件通常有两个扩展名&#xff1a;.nii&#xff08;用于图像数据&#xf…

持续总结中!2024年面试必问 100 道 Java基础面试题(三十二)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 100 道 Java基础面试题&#xff08;三十一&#xff09;-CSDN博客 六十三、接口里面可以写方法实现吗&#xff1f; 在Java中&#xff0c;接口&#xff08;Interface&#xff09;主要用于定义一组抽象方法&#xf…

MySQL 优化 - index_merge 导致查询偶发变慢

文章目录 前言问题描述原因分析总结 前言 今天遇到了一个有意思的问题&#xff0c;线上数据库 CPU 出现了偶发的抖动。定位到原因是一条查询语句偶发变慢造成的&#xff0c;随后通过调整表中的索引解决。 问题描述 下方是脱敏后的 SQL 语句&#xff1a; select oss_path f…

字节跳动后端或大数据基础知识面试题及参考答案(2万字长文)

目录 Redis的数据类型 Redis数据类型的底层数据结构 三次握手、四次挥手 Redis持久化机制

搜索算法系列之三(插值查找)

前言 插值查找仅适用于有序数据、有序数组&#xff0c;和二分查找类似&#xff0c;更讲究数据有序均匀分布。 算法原理 插值查找(interpolation search)是一种查找算法&#xff0c;它与二分查找类似&#xff0c;但在寻找元素时更加智能化。这种算法假设数据集是等距的或者有…

VMP 简单源码分析

虚拟机 获取CPU的型号 实现了一个指令集解释器&#xff0c;每个操作码对应一个特定的处理函数&#xff0c;用于执行相应的指令操作。在执行字节码时&#xff0c;解释器会根据操作码查找并调用相应的处理函数来执行指令。 截获异常 先由虚拟机处理 处理不了再抛出异常 priva…

Python日志记录:全面指南

基本原理 日志记录是软件开发中的一个核心组成部分&#xff0c;它帮助开发者跟踪程序的运行流程&#xff0c;捕获程序执行期间的重要事件。日志记录可以作为程序运行状态的连续监控&#xff0c;记录用户细节、IP地址访问信息等重要数据。当发生错误时&#xff0c;日志不仅提供…

(学习日记)2024.05.12:UCOSIII第六十六节:常用的控制宏介绍 第二部分

之前的章节都是针对某个或某些知识点进行的专项讲解&#xff0c;重点在功能和代码解释。 回到最初开始学μC/OS-III系统时&#xff0c;当时就定下了一个目标&#xff0c;不仅要读懂&#xff0c;还要读透&#xff0c;改造成更适合中国宝宝体质的使用方式。在学完野火的教程后&a…

【LLM】动手部署个人知识库助手

文章目录 动手部署个人知识库助手环境依赖项目运行总结 动手部署个人知识库助手 经过前面章节的学习&#xff0c;理解了LLM、向量知识库等知识&#xff0c;本章节开始实践部署个人知识库助手。 本次部署的项目github地址个人知识库助手项目 环境依赖 技术资源要求 CPU: Int…

MySql#MySql安装和配置

目录 一、卸载不需要的环境 二、安装mysql yum 源 三、开始安装 四、如果保证安装成功呢&#xff1f; 五、MySql 启动&#xff01; 六、登录mysql 七、配置文件说明 八、设置开机启动&#xff01; 本次安装是在Linux环境在centos7中完成 首先先将自己切换成root 一、…

分页封装类

加油&#xff0c;新时代打工人&#xff01; package com.love.starter.common.util;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import java.util.Map;/*** 计算页开始及结束位置** author Administrator*/ public c…

MySQL数据库——20.索引

在 MySQL 中&#xff0c;索引是一种特殊的数据结构&#xff0c;用于快速查找数据库表中的数据。索引可以帮助提高查询速度&#xff0c;特别是对于大型数据表而言&#xff0c;使用索引可以大大减少查询的时间复杂度。 索引类 普通索引&#xff08;Normal Index&#xff09;&am…

基于springboot实现图书电子商务网站系统项目【项目源码+论文说明】

基于springboot实现图书电子商务网站系统演示 摘要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱…

flowable流程跳转或退回到网关上的用户节点后流程走不下去了

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

在Ubuntu上搭建并通过systemctl管理Minecraft Java版服务器

本教程将详细介绍如何在Ubuntu操作系统上搭建一个Minecraft Java版服务器&#xff0c;并使用systemctl服务来管理服务器的启动、停止和重启。同时&#xff0c;我们还将探讨如何通过NGINX设置TCP/UDP转发&#xff0c;使得玩家能够通过域名方便地连接到你的Minecraft服务器。 准…

【JVM】class文件格式,JVM加载class文件流程,JVM运行时内存区域,对象分配内存流程

这篇文章本来只是想讲一下class文件格式&#xff0c;讲着讲着越讲越多。JVM这一块吧&#xff0c;知识比较散比较多&#xff0c;如果深研究下去如死扣《深入理解Java虚拟机》&#xff0c;这本书很深很细&#xff0c;全记住是不可能的&#xff0c;其实也没必要。趁这个机会直接把…

日志中看到来自User Agent go-http-client / 1.1的大量请求(go-http-client 1.1)服务器爆了

在日志中看到来自User Agent go-http-client / 1.1的大量请求 The go-http-client/1.1 User Agent 是Google的Bot / Crawler 这不是真的。这可能是指Go库&#xff08;根据您提到的来源&#xff0c;由Google开发&#xff0c;但是我找不到可靠的信息&#xff09;。 之前写过“G…