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;是呀…

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…

VMP 简单源码分析

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

MySql#MySql安装和配置

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

基于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…

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

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

如何快速找出文件夹里的全部带有中文纯中文的文件

首先&#xff0c;需要用到的这个工具YTool&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 步骤 1、打开工具&#xff0c;切换到批量复制文件 2、鼠标移到右侧&#xff0c;点击搜索添加 3、设定查找范围、指定为文件、勾选 包含全部子文件夹&…

FP16与BF16区别

二者都是占用16bit空间。 FP16由1个符号位、5个指数位和10个尾数位组成。FP16在表达小数时具有较高的精度&#xff0c;但表示的最大范围相对BF16比较小。相比BF16&#xff0c;在表达较大的数时更容易出现上溢的情况。BF16由1个符号位、8个指数位和7个尾数位组成。相比于FP16&a…

RFC 791 (1)-导论

目录 浅论 IP是啥 IP可以管啥 操作 范例查看 提示&#xff1a;本系列将会开始RFC文档阅读&#xff0c;这里会给出我的一些笔记 浅论 我们这篇RFC文档描述的是IP和ICMP协议&#xff0c;我们都知道&#xff0c;在传统的OSI七层或者是现在被简化的五层&#xff1a;应用层&…

2024年Q1季度果酒行业线上市场数据分析:女性消费力量强劲!

随着短视频推广和健康饮酒理念的盛行&#xff0c;果酒凭借酒精度数低、口味丰富、富含多种营养成分等优势逐渐受到了消费者的青睐。 Q1季度&#xff0c;消费者对果酒需求依旧旺盛。根据鲸参谋数据显示&#xff0c;今年Q1季度&#xff0c;线上电商平台&#xff08;某猫&#xf…

6S管理,真的有必要吗?

工厂里的物料不知道是什么时间堆放的&#xff0c;不知道这个是谁的&#xff0c;不知道还有没有用&#xff0c;不知道该不该处理掉&#xff0c;越积越多&#xff0c;想要的东西总是找不着&#xff0c;不要的东西总是“碍手碍脚”……可怕的是大家对这一些现象习以为常。 说起6S…

搬运5款小众,无广告,实用性拉满的软件

​ 你是否喜欢一些小众且无广告的软件&#xff1f;如果是的话&#xff0c;我这边有一些给你推荐的。 1.屏幕录制——OBS Studio ​ OBS Studio是一款广泛使用的实时流媒体和屏幕录制软件&#xff0c;适用于Windows、MacOS、Linux平台。它采用C、C和Qt编写&#xff0c;提供高质…

Keepalived实现LVS高可用

6.1 KeepalivedLVS集群介绍 Keepalived和LVS共同构建了一个高效的负载均衡和高可用性解决方案&#xff1a;LVS作为负载均衡器&#xff0c;负责在集群中的多个服务器间分配流量&#xff0c;以其高性能和可扩展性确保应用程序能够处理大量的并发请求&#xff1b;而Keepalived则作…

如何使用DEEPL免费翻译PDF

如何使用DEEPL免费翻译PDF 安装DEEPL取消PDF限制 安装DEEPL 安装教程比较多&#xff0c;这里不重复。 把英文pdf拖进去&#xff0c;点翻译&#xff0c;在下面的框中有已经翻译完毕的文档。 但是存在两个问题 问题1&#xff1a;这些文档是加密的。 问题2&#xff1a;带有DeepL标…

C#知识|上位机UI设计-详情窗体设计思路及流程(实例)

哈喽,你好啊,我是雷工! 上两节练习记录了登录窗体和主窗体的实现过程,本节继续练习内容窗体的实现,以下为练习笔记。 01 详情窗体效果展示: 02 添加窗体并设置属性 在之前练习项目的基础上添加一个Windows窗体,设置名称为:FrmIPManage.cs 设置窗体的边框和标题栏的外…

flink sql 优化

文章目录 一、参数方面二、资源方面三、总结 提示&#xff1a;实时flink sql 参考很多网上方法与自己实践方法汇总(版本:flink1.13) 一、参数方面 flink sql参数配置 //关闭详细算子链(默认为true),true后job性能会略微有提升。false则可以展示更详细的DAG图方便地位性能结点…

go mod

常用命令 初始化模块 go mod init 模块名下载 go.mod 文件中指明的所有依赖 go mod download github.com/gin-gonic/ginv1.9.(依赖路径)依赖对其&#xff08;使引用的都是所依赖的&#xff09; go mod tidy编辑go.mod go mod edit go mod edit -require"github.com/g…

jvm 马士兵 01 JVM简介,class文件结构

01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件&#xff0c;符合JVM规范的class文件都可以被识别 u1 是一个字节 u2是两个字节