FPGA project : sobel

实验目标:

sobel算法,处理100X100灰度图像:野火logo

边缘检测:

边缘检测,针对的是灰度图像,顾名思义,检测图像的边缘,是针对图像像素点的一种计算,目的是标识数字图像中灰度变化明显的点,图像的边缘检测,在保留了图像的重要结构信息的同时,剔除了可以认为不相关的信息,大幅度减少了数据量,便于图像的传输和处理。

什么是sobel算法:

 算出来的Gxy与一个数据T比较大小,大于T则b2像素点赋值为黑色,小于赋值白色。

我踩得坑:

vga_pic模块,调用的时候由于图片大小需要更改,当初写vga_pic模块的时候,没有把代码中的一些数,用parameter表示,在修改的时候很麻烦。所以以后写代码的时候,大于2的参数一定要重新定义一下,代码写的应该更具复用性。

代码复用性也是代码质量的体现。

经验总结:

想要沉浸式写代码,就要清清楚楚的画好时序图。在写代码之前就应该想清楚用到的每个信号的时序图应该是什么样的。

fpga开发一大部分时间花在整体(顶层)设计上,一部分时间花在如何把想法转换为Verilog语言,一部分时间花在仿真调试上。

我认为最重要的就是整体设计,以及画好时序图。或者有流程图或者相关的辅助你把想法转换为代码的图。

模块框图:

时序图: 

特别大

代码:

 就放sobel算法部分,和顶层。

module sobel(input		wire 			clk_50		,input 		wire 			sys_rst_n 	,input 		wire	[7:0]	pi_data		,input 		wire 			pi_flag 	,output 		reg  			po_flag		,output		reg  	[7:0]	po_data 
);// parameterparameter	MAX_LINE = 8'd100 		 ,MAX_COL  = 8'd100 		 ,THR      = 8'b0000_1100  ,BLACK    = 8'b0000_0000  ,WHITE    = 8'b1111_1111  ;// reg signal definereg 	[7:0]	cnt_line	;reg 	[7:0]	cnt_col		;reg 			wrreq1		;reg		[7:0]	dataf1_in	;reg 			rdreq		;reg				wrreq2		;reg 	[7:0]	dataf2_in	;reg  	[7:0]	pi_data_reg1;reg     [7:0]	cnt_read 	; // 对从FIFO中读出的数据个数计数。reg 			dataRegFlag ;reg 	[7:0]	fifo1_reg   ;reg		[7:0]	fifo2_reg	;reg  	[7:0]	pi_data_reg2;reg  	[7:0]	pi_data_reg3; // 用来保存pi_data以进行sobel运算。不是单纯的对pi_data_reg2打拍。reg 			flag_abc	;reg		[7:0]	a3			;reg 	[7:0]	b3			;reg		[7:0]	c3			;reg		[7:0]	a2			;reg 	[7:0]	b2			;reg		[7:0]	c2			;reg		[7:0]	a1			;reg 	[7:0]	b1			;reg		[7:0]	c1			;reg  			arithmetic  ; // 进行sobel算法的标志。reg 	[8:0]	gx			; // 因为有符号位,所以运算过后要多加一位。reg		[8:0]	gy			; // 因为有符号位,所以运算过后要多加一位。reg 			flag_gxy	;reg		[8:0]	gxy			;reg				answer_flag ;// wire signal definewire            rdreq_w     ;    wire 			wrreq1_w	;wire 	[7:0]	dataf1_in_w ;wire	[7:0]	dataf1_out	;wire    [9:0]   usedw_f1    ;wire            full_f1     ;wire            empty_f1    ;wire			wrreq2_w	;wire	[7:0]	dataf2_in_w ;wire	[7:0]	dataf2_out	;wire    [9:0]   usedw_f2    ;wire            full_f2     ;wire            empty_f2    ;/*********************************************************************/
// 	reg 	[7:0]	cnt_line	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) cnt_line <= 8'd0 ;else if(pi_flag && cnt_col == MAX_COL - 1 && cnt_line == MAX_LINE - 1)cnt_line <= 8'd0 ;else if(pi_flag && cnt_col == MAX_COL - 1)cnt_line <= cnt_line + 1'b1 ;else cnt_line <= cnt_line ;end
// 	reg 	[7:0]	cnt_col		;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n)cnt_col <= 8'd0 ;else if(pi_flag && cnt_col == MAX_COL - 1)cnt_col <= 8'd0 ;else if(pi_flag)cnt_col <= cnt_col + 1'b1 ;else cnt_col <= cnt_col ;end
// 	reg 			wrreq1		;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) wrreq1 <= 1'b0 ;else if(cnt_line == 0)wrreq1 <= pi_flag ;else if(((cnt_line == 2) && (cnt_col != 0)) || ((cnt_line) > 2 && (cnt_line < MAX_LINE - 1)) || ((cnt_line == MAX_LINE - 1) && (cnt_col == 0))) wrreq1 <= wrreq2 ;else wrreq1 <= 1'b0 ;end
// 	reg		[7:0]	dataf1_in	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) dataf1_in <= 8'd0 ;else if(cnt_line == 0)dataf1_in <= pi_data ;else if(((cnt_line == 2) && (cnt_col != 0)) || ((cnt_line) > 2 && (cnt_line < MAX_LINE - 1)) || ((cnt_line == MAX_LINE - 1) && (cnt_col == 0))) dataf1_in <= dataf2_out ;else dataf1_in <= dataf1_in ;end
// 	reg 			rdreq		;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) rdreq <= 1'b0 ;else if(cnt_line >= 2)rdreq <= pi_flag ;else rdreq <= 1'b0 ; end
// 	reg				wrreq2		;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) wrreq2 <= 1'b0 ;else if(cnt_line == 1)wrreq2 <= pi_flag ;else if((cnt_line >= 2 && cnt_line <= (MAX_LINE - 1)) || (cnt_line == (MAX_LINE - 1) && (cnt_col == 0)) ) wrreq2 <= rdreq ;else wrreq2 <= 1'b0 ;end
// 	reg 	[7:0]	dataf2_in	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) dataf2_in <= 8'd0 ;else if(cnt_line == 1)dataf2_in <= pi_data ;else if((cnt_line >= 2 && cnt_line <= (MAX_LINE - 1)) || (cnt_line == (MAX_LINE - 1) && (cnt_col == 0)) ) dataf2_in <= pi_data_reg1 ;else dataf2_in <= dataf2_in ;end
// 	reg  	[7:0]	pi_data_reg1;
// 	reg  	[7:0]	pi_data_reg2;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) beginpi_data_reg1 <= 8'd0 ;pi_data_reg2 <= 8'd0 ;end else beginpi_data_reg1 <= pi_data      ;pi_data_reg2 <= pi_data_reg1 ;endend
// 	reg     [7:0]	cnt_read 	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) cnt_read <= 8'd0 ;else if(rdreq && cnt_read == MAX_COL - 1)cnt_read <= 8'd0 ;else if(rdreq)cnt_read <= cnt_read + 1'b1 ;else cnt_read <= cnt_read ;            end
// 	reg 			dataRegFlag ;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) dataRegFlag <= 1'b0 ;else dataRegFlag <= rdreq ; end
// 	reg 	[7:0]	fifo1_reg   ;
// 	reg		[7:0]	fifo2_reg	;
// 	reg  	[7:0]	pi_data_reg3;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) beginfifo1_reg    <= 8'd0 ;fifo2_reg    <= 8'd0 ;pi_data_reg3 <= 8'd0 ;end else beginif(dataRegFlag) beginfifo1_reg    <= dataf1_out   ;fifo2_reg    <= dataf2_out   ;pi_data_reg3 <= pi_data_reg2 ;end else beginfifo1_reg    <= fifo1_reg    ;fifo2_reg    <= fifo2_reg    ;pi_data_reg3 <= pi_data_reg3 ;endendend
// 	reg 			flag_abc	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) flag_abc <= 1'b0 ;else flag_abc <= dataRegFlag ;end
// 	reg		[7:0]	a3			;
// 	reg 	[7:0]	b3			;
// 	reg		[7:0]	c3			;
// 	reg		[7:0]	a2			;
// 	reg 	[7:0]	b2			;
// 	reg		[7:0]	c2			;
// 	reg		[7:0]	a1			;
// 	reg 	[7:0]	b1			;
// 	reg		[7:0]	c1			;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) begina3 <= 8'd0 ;b3 <= 8'd0 ;c3 <= 8'd0 ;a2 <= 8'd0 ;b2 <= 8'd0 ;c2 <= 8'd0 ;a1 <= 8'd0 ;b1 <= 8'd0 ;c1 <= 8'd0 ;end else beginif(flag_abc) begina3 <= fifo1_reg    ;b3 <= fifo2_reg    ;c3 <= pi_data_reg3 ;a2 <= a3 ;b2 <= b3 ;c2 <= c3 ;a1 <= a2 ;b1 <= b2 ;c1 <= c2 ;end else begina3 <= a3 ;b3 <= b3 ;c3 <= c3 ;a2 <= a2 ;b2 <= b2 ;c2 <= c2 ;a1 <= a1 ;b1 <= b1 ;c1 <= c1 ;endendend
// 	reg  			arithmetic  ;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) arithmetic <= 1'b0 ;else if(cnt_col != 1 && cnt_col != 2)arithmetic <= flag_abc ;else arithmetic <= 1'b0 ;end
// 	reg 	[8:0]	gx			;
// 	reg		[8:0]	gy			;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) begingx <= 9'd0 ;gy <= 9'd0 ;end else beginif(arithmetic) begingx <= (a3-a1)+((b3-b1) << 1)+(c3-c1) ; // 向左移动1bit相当于扩大二倍。gy <= (a1-c1)+((a2-c2) << 1)+(a3-c3) ; // 向左移动1bit相当于扩大二倍。end else begingx <= gx ;gy <= gy ;endendend
// 	reg 			flag_gxy	;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n)flag_gxy <= 1'b0 ;else flag_gxy <= arithmetic ;end// 	reg		[8:0]	gxy			;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) gxy <= 8'd0 ;else if(flag_gxy) begincase ({gx[8],gy[8]})2'b00  : gxy <=  gx[7:0] +  gy[7:0]        ;2'b01  : gxy <=  gx[7:0] + ~gy[7:0] + 1'b1 ;2'b10  : gxy <= ~gx[7:0] +  gy[7:0] + 1'b1 ;2'b11  : gxy <= ~gx[7:0] + ~gy[7:0] + 2'd2 ;default: gxy <= gxy ;endcaseend //    gxy <= {1'b0,gx[7:0]} + {1'b0,gy[7:0]} ; // 取其绝对值相加。也就是说最高位应该为0.end
// 	reg				answer_flag ;always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) answer_flag <= 1'b0 ;else answer_flag <= flag_gxy ; end
// output signal
// reg  			po_flag		always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) po_flag <= 1'b0 ;else if(answer_flag)po_flag <= 1'b1 ;else po_flag <= 1'b0 ;end
// reg  	[7:0]	po_data always @(posedge clk_50 or negedge sys_rst_n) beginif(~sys_rst_n) po_data <= 8'd0 ;else if(answer_flag && (gxy >  THR))po_data <= BLACK ;else if(answer_flag && (gxy <= THR))po_data <= WHITE ;else po_data <=  po_data ;end
/*************************************************************/// 例化assign  dataf1_in_w = dataf1_in ;assign  dataf2_in_w = dataf2_in ;assign  rdreq_w     = rdreq     ; assign  wrreq1_w    = wrreq1    ;assign  wrreq2_w    = wrreq2    ;fifo fifo_f1(.clock                  ( clk_50        ) ,.data                   ( dataf1_in_w   ) ,.rdreq                  ( rdreq_w       ) ,.wrreq                  ( wrreq1_w      ) ,.empty                  ( empty_f1      ) ,.full                   ( full_f1       ) ,.q                      ( dataf1_out    ) ,.usedw                  ( usedw_f1      ) 
);fifo fifo_f2(.clock                  ( clk_50        ) ,.data                   ( dataf2_in_w   ) ,.rdreq                  ( rdreq_w       ) ,.wrreq                  ( wrreq2_w      ) ,.empty                  ( empty_f2      ) ,.full                   ( full_f2       ) ,.q                      ( dataf2_out    ) ,.usedw                  ( usedw_f2      ) 
);endmodule

 

module top(input		wire			sys_clk 	,input 		wire			sys_rst_n 	,input 		wire 			rx 			,output 		wire 			hsync 		,output		wire			vsync  		,output		wire	[7:0]	rgb			,output		wire			tx 
);// 例化间连线wire			clk_50     ;wire			clk_25     ;wire			rst_n      ;wire  			po_flag_rx ;wire	[7:0]	po_data_rx ;wire  			po_flag_so ;wire	[7:0]	po_data_so ;pll pll_50_25(.sys_rst_n		( sys_rst_n  ) ,.areset			( ~sys_rst_n ) ,.inclk0			( sys_clk 	 ) ,.c0				( clk_50 	 ) ,.c1				( clk_25 	 ) ,.locked			( rst_n 	 ) 
);uart_rx uart_rx_inst(.sys_clk		( clk_50     ) ,.sys_rst_n		( rst_n      ) ,.rx				( rx         ) ,.po_flag		( po_flag_rx ) ,.po_data		( po_data_rx )    
);sobel sobel_inst(.clk_50			( clk_50     ) ,.sys_rst_n		( rst_n      ) ,.pi_data		( po_data_rx ) ,.pi_flag		( po_flag_rx ) ,.po_flag         ( po_flag_so ) ,.po_data         ( po_data_so ) 
);uart_tx uart_tx_inst(.sys_clk        ( clk_50     ) ,.sys_rst_n      ( rst_n      ) ,.pi_flag        ( po_flag_so ) ,.pi_data        ( po_data_so ) ,.tx             ( tx         )          
);vga vga_inst(.clk_25         ( clk_25     ) ,.clk_50         ( clk_50     ) ,.rst_n          ( rst_n      ) ,.pi_data        ( po_data_so ) ,.pi_flag        ( po_flag_so ) ,.hsync          ( hsync      ) ,.vsync          ( vsync      ) ,.rgb            ( rgb        )    
);endmodule

 仿真图忘记截屏了。

上板验证:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103616.shtml

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

相关文章

vue3学习(二)--- ref和reactive

文章目录 ref1.1 ref将基础类型和对象类型数据转为响应式1.2 ref()获取id元素1.3 isRef reactive1.1 reactive()将引用类型数据转为响应式数据&#xff0c;基本类型无效1.2 ref和reactive的联系 toRef 和 toRefs1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的 ref …

点燃市场热情,让产品风靡全球——实用推广策略大揭秘!

文章目录 一、实用推广策略的重要性1. 提高产品知名度和认可度2. 拓展产品市场和用户群体3. 增强企业品牌形象和市场竞争力 二、实用推广策略的种类1. 社交媒体推广2. 定向推广3. 口碑营销4. 内容推广 三、实用推广策略的实施步骤1. 研究目标用户和市场需求&#xff0c;明确产品…

大数据NoSQL数据库HBase集群部署

目录 1. 简介 2. 安装 1. HBase依赖Zookeeper、JDK、Hadoop&#xff08;HDFS&#xff09;&#xff0c;请确保已经完成前面 2. 【node1执行】下载HBase安装包 3. 【node1执行】&#xff0c;修改配置文件&#xff0c;修改conf/hbase-env.sh文件 4. 【node1执行】&#xf…

第14章总结:lambda表达式与处理

14.1&#xff1a; lambada表达式 14.1.1&#xff1a;lambada表达式简介 无参数 package fourteen; interface SayhHi{ String say();//抽象方法接口 } public class NoParamDemo { public static void main(String[] args) { //无参数 …

【AI视野·今日Robot 机器人论文速览 第五十二期】Wed, 11 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 11 Oct 2023 Totally 31 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers RoboHive: A Unified Framework for Robot Learning Authors Vikash Kumar, Rutav Shah, Gaoyue Zhou, Vincent Moens, Vittor…

SAP MM学习笔记35 - 请求书照合中的差额处理(发票扣减,受入)

SAP中&#xff0c;请求书照合之后&#xff0c;发现不一致&#xff0c;就会支付保留。 支付保留&#xff0c;可以参考如下文章。 SAP MM学习笔记34 - 请求书照合中的支付保留&#xff08;发票冻结&#xff09;_东京老树根的博客-CSDN博客 即使支付保留之后暂时不付钱&#xff…

外卖跑腿系统开发的最佳实践和成功案例

外卖跑腿系统的开发既涉及技术实现&#xff0c;也需要考虑用户体验、运营策略和合规性。以下是一些最佳实践和一些成功的案例&#xff0c;以帮助您更好地理解这个领域的要点。 1. 技术框架的选择 选择适合的技术框架是外卖跑腿系统成功的关键。您可以考虑使用以下技术&#…

mysql面试题45:读写分离常见方案、哪些中间件可以实现读写分离

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说你知道的读写分离常见方案 读写分离是一种常见的数据库架构方案,旨在分担数据库的读写压力,提高系统的性能和可扩展性。以下是两种常见的…

Nacos 小bug: application.properties配置未生效,导致端口未生效

最近用了下nacos 1.4.6 ,发现windows 中修改配置中的启动端口未生效&#xff0c;其实就是配置文件没读取到。 去github 逛了一下issue ,参考这个&#xff1a;https://github.com/alibaba/nacos/issues/10217 这哥们儿是nacos 1.4.5 Linux系统下的相同问题&#xff0c;shell 中…

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Radio

单选框&#xff0c;提供相应的用户交互选择项。该组件从API Version 8开始支持。无子组件。 一、接口 Radio(options: {value: string, group: string}) 从API version 9开始&#xff0c;该接口支持在ArkTS卡片中使用。 参数: 二、属性 除支持通用属性外&#xff0c;还支持以…

更新 | 持续开源迅为RK3568驱动指南第十二篇-GPIO子系统

《iTOP-RK3568开发板驱动开发指南》更新&#xff0c;本次更新内容对应的是驱动&#xff08;第十二期_GPIO子系统-全新升级&#xff09;视频&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 文档教程更新至第十…

基于FPGA的视频接口之千兆网口(四配置)

简介 相信网络上对于FPGA驱动网口的开发板、博客、论坛数不胜数,为何博主需要重新手敲一遍呢,而不是做一个文抄君呢!因为目前博主感觉网络上描述的多为应用层上的开发,非从底层开始说明,本博主的思虑还是按照老规矩,按照硬件、底层、应用等关系,使用三~四篇文章,来详细…

Flutter - 波浪动画和lottie动画的使用

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 波浪动画三方库wave lottie动画 Lottie 是 Airbnb 开发的一款能够为原生应用添加动画效果的开源工具。具有丰富的动画效果和交互功能。 # 波浪动画 https://pub-web…

家政服务小程序,家政维修系统,专业家政软件开发商;家政服务小程序,家政行业软件开发

家政服务小程序&#xff0c;家政维修系统&#xff0c;专业家政软件开发商&#xff1b; 家政服务小程序&#xff0c;家政行业软件开发解决方案&#xff0c;家政软件经验丰富实践&#xff0c;系统高度集成&#xff0c;提供师傅端、用户端、… 家政服务app开发架构有 1、后台管理端…

用什么工具来画UML?

2023年10月9日&#xff0c;周一晚上 目录 我的决定 关于rational rose UML工具有哪些 相关资料 我的决定 我决定用plantUML、draw.io或starUML就可以了 其实没必要在意工具&#xff0c; 重要的是能把图画出来、把图画好画规范&#xff0c; 重要的是知道怎么去画图、把意…

nnunetv2训练报错 ValueError: mmap length is greater than file size

目录 报错解决办法 报错 笔者在使用 nnunetv2 进行 KiTS19肾脏肿瘤分割实验的训练步骤中 使用 2d 和3d_lowres 训练都没有问题 nnUNetv2_train 40 2d 0nnUNetv2_train 40 3d_lowres 0但是使用 3d_cascade_fullres 和 3d_fullres 训练 nnUNetv2_train 40 3d_cascade_fullres …

如何实现前端缓存管理?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

SQL sever中的视图

目录 一、视图概述&#xff1a; 二、视图好处 三、创建视图 法一&#xff1a; 法二&#xff1a; 四、查看视图信息 五、视图插入数据 六、视图修改数据 七、视图删除数据 八、删除视图 法一&#xff1a; 法二&#xff1a; 一、视图概述&#xff1a; 视图是一种常用…

K8S云计算系列-(4)

K8s Dashboard UI 部署实操 Kubernetes实现的最重要的工作是对Docker容器集群统一的管理和调度&#xff0c;通常使用命令行来操作Kubernetes集群及各个节点&#xff0c;命令行操作非常不方便&#xff0c;如果使用UI界面来可视化操作&#xff0c;会更加方便的管理和维护。如下为…

基于统计学库statsmodel实现时间序列预测

文章目录 1.数据探索与清洗2.假设检验&#xff1a;平稳性检验3.差分处理4.绘制ACF与PACF图像&#xff0c;完成模型选择4.建立ARIMA和SARIMA模型5.解读summary6.确定最终的模型 ARIMA模型在统计学上的三大基本假设&#xff1a; 时间序列具有平稳性&#xff08;stationary&#x…