FPGA + 图像处理(三)生成3x3像素矩阵

前言

生成NxN的像素矩阵是对图像进行各类滤波操作的基本前提,本文介绍一种通过bram生成3x3矩阵的方法。

程序

生成bram核

因为本文介绍的是基于bram生成的3x3像素矩阵,所以要先生成两个bram核,用于缓存前两行图像数据

在 IP catalog中选择Block Memory Generator

配置如下

注意这里选择simple dual port RAM,即伪双端口,一个端口只能写,一个端口只能读

端口A用于写入数据,注意数据的位宽要与图像位深相同,彩色通常为24位,灰度图为8位,数据深度为一行像素的长度,operating选择写优先,enable port type选择始终使能

端口B用于读取数据,这里要注意下面的primitives output register要勾选上,勾选该选项后,数据的输出会延迟一个时钟周期,用于对齐数据。

HDMI时序生成模块

这里也用到了HDMI时序生成模块,具体作用和前面文章讲的一样,一是可以做到通过同步信号简化对图像数据的管理,二是可以让测试的数据处理模块更方便的适配用HDMI显示的图像处理工程。

具体代码如下

module hdmi_tim_gen(input           	clk			,input           	rst_n	    ,input   	[23:0]  data_in		,output          	hdmi_hs		,     //行同步信号output          	hdmi_vs		,     //场同步信号output          	hdmi_de		,     //数据使能output  	[23:0]  hdmi_data	,     //RGB888颜色数据output		reg		data_req 	);//1280*720 分辨率时序参数
parameter  H_SYNC   =  11'd40;   //行同步
parameter  H_BACK   =  11'd220;  //行显示后沿
parameter  H_DISP   =  11'd1280; //行有效数据
parameter  H_FRONT  =  11'd110;  //行显示前沿
parameter  H_TOTAL  =  11'd1650; //行扫描周期parameter  V_SYNC   =  11'd5;    //场同步
parameter  V_BACK   =  11'd20;   //场显示后沿
parameter  V_DISP   =  11'd720;  //场有效数据
parameter  V_FRONT  =  11'd5;    //场显示前沿
parameter  V_TOTAL  =  11'd750;  //场扫描周期//reg define
reg  [11:0] 	cnt_h;
reg  [11:0] 	cnt_v;reg [10:0] pixel_xpos;
reg [10:0] pixel_ypos;assign hdmi_de  = data_req;
assign hdmi_hs  = ( cnt_h < H_SYNC ) ? 1'b0 : 1'b1;  //行同步信号赋值
assign hdmi_vs  = ( cnt_v < V_SYNC ) ? 1'b0 : 1'b1;  //场同步信号赋值//RGB888数据输出
assign hdmi_data = hdmi_de ? data_in : 24'd0;//请求像素点颜色数据输入
always @(posedge clk or negedge rst_n) beginif(!rst_n)data_req <= 1'b0;else if(((cnt_h >= H_SYNC + H_BACK - 2'd2) && (cnt_h < H_SYNC + H_BACK + H_DISP - 2'd2))&& ((cnt_v >= V_SYNC + V_BACK) && (cnt_v < V_SYNC + V_BACK+V_DISP)))data_req <= 1'b1;elsedata_req <= 1'b0;
end//像素点x坐标
always@ (posedge clk or negedge rst_n) beginif(!rst_n)pixel_xpos <= 11'd0;else if(data_req)pixel_xpos <= cnt_h + 2'd2 - H_SYNC - H_BACK ;else pixel_xpos <= 11'd0;
end//像素点y坐标	
always@ (posedge clk or negedge rst_n) beginif(!rst_n)pixel_ypos <= 11'd0;else if((cnt_v >= (V_SYNC + V_BACK)) && (cnt_v < (V_SYNC + V_BACK + V_DISP)))pixel_ypos <= cnt_v + 1'b1 - (V_SYNC + V_BACK) ;else pixel_ypos <= 11'd0;
end//行计数器对像素时钟计数
always @(posedge clk or negedge rst_n) beginif (!rst_n)cnt_h <= 11'd0;else beginif(cnt_h < H_TOTAL - 1'b1)cnt_h <= cnt_h + 1'b1;else cnt_h <= 11'd0;end
end//场计数器对行计数
always @(posedge clk or negedge rst_n) beginif (!rst_n)cnt_v <= 11'd0;else if(cnt_h == H_TOTAL - 1'b1) beginif(cnt_v < V_TOTAL - 1'b1)cnt_v <= cnt_v + 1'b1;else cnt_v <= 11'd0;end
endendmodule

生成3x3像素矩阵的顶层模块

module kernel_3x3_gen
(input					clk,  		input					rst_n,				//准备要进行处理的图像数据input					vs_i,input					de_i,input        [23:0]  	data_i,//矩阵化后的图像数据和控制信号output				vs_o,output				de_o,output	reg  [23:0]	mat11, output	reg  [23:0]	mat12,output	reg  [23:0]	mat13,output	reg	 [23:0]	mat21, output	reg  [23:0]	mat22, output	reg  [23:0]	mat23,output	reg	 [23:0]	mat31, output	reg  [23:0]	mat32, output	reg  [23:0]	mat33
);//wire define
wire  [23:0]  	row1_data;        //第一行数据
wire  [23:0]  	row2_data;        //第二行数据
wire	     	de_i_en ;//reg define
reg  [23:0]  row3_data;         //第三行数据,即当前正在接受的数据
reg  [23:0]  row3_data_d0;
reg  [23:0]  row3_data_d1;
reg  [23:0]  row2_data_d0;
reg  [1:0]   vs_i_d;
reg  [1:0]   de_i_d;assign	de_i_en = de_i_d[0] ;
assign	vs_o 	= vs_i_d[1];
assign	de_o  	= de_i_d[1] ;//当前数据放在第3行
always@(posedge clk or negedge rst_n) beginif(!rst_n)row3_data <= 0;else begin		if(de_i)row3_data <= data_i ;elserow3_data <= row3_data ;end
end//用于存储列数据的RAM
line_shift  u_line_shift
(.clk		    (clk),.de_i 			(de_i),.data_i	    	(data_i),   //当前行的数据.data1_o		(row2_data),   //前一行的数据.data2_o		(row1_data)    //前前一行的数据
);//将同步信号延迟两拍,用于同步化处理
always@(posedge clk or negedge rst_n) beginif(!rst_n) begin		vs_i_d <= 0;de_i_d <= 0;endelse begin		vs_i_d  <= { vs_i_d[0], vs_i };de_i_d  <= { de_i_d[0], de_i };end
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginrow3_data_d1 <= 0;row3_data_d0 <= 0;row2_data_d0 <= 0;endelse beginrow3_data_d0 <= row3_data;row3_data_d1 <= row3_data_d0;row2_data_d0 <= row2_data;end
end//在同步处理后的控制信号下,输出图像矩阵
always@(posedge clk or negedge rst_n) beginif(!rst_n) begin		{mat11, mat12, mat13} <= 0;{mat21, mat22, mat23} <= 0;{mat31, mat32, mat33} <= 0;endelse if(de_i_en) begin				{mat11, mat12, mat13} <= {mat12, mat13, row1_data};{mat21, mat22, mat23} <= {mat22, mat23, row2_data_d0};{mat31, mat32, mat33} <= {mat32, mat33, row3_data_d1};endelse begin		{mat11, mat12, mat13} <= 0;{mat21, mat22, mat23} <= 0;{mat31, mat32, mat33} <= 0;end
endendmodule

行移位模块

module line_shift(input 			clk,input           de_i,input   [23:0]  data_i,    //当前行的数据output  [23:0]  data1_o,   //前一行的数据output  [23:0]  data2_o    //前前一行的数据
);//reg define
reg  de_i_d0;
reg  de_i_d1;
reg  de_i_d2;
reg  [10:0]  ram_rd_addr;
reg  [10:0]  ram_rd_addr_d0;
reg  [10:0]  ram_rd_addr_d1;
reg  [23:0]  data_i_d0;
reg  [23:0]  data_i_d1;
reg  [23:0]  data_i_d2;
reg  [23:0]  data1_o_d0;//在数据到来时,RAM的读地址累加
always@(posedge clk)beginif(de_i)ram_rd_addr <= ram_rd_addr + 1 ;	elseram_rd_addr <= 0 ;
end//将数据使能延迟两拍
always@(posedge clk) beginde_i_d0 <= de_i;de_i_d1 <= de_i_d0;de_i_d2 <= de_i_d1;
end//将RAM地址延迟2拍
always@(posedge clk ) beginram_rd_addr_d0 <= ram_rd_addr;ram_rd_addr_d1 <= ram_rd_addr_d0;
end//输入数据延迟3拍送入RAM
always@(posedge clk)begindata_i_d0 <= data_i;data_i_d1 <= data_i_d0;data_i_d2 <= data_i_d1;
end//用于存储前一行图像的RAM
blk_mem_gen_0  u_ram_1024x8_0(.clka   (clk),.wea    (de_i_d2),.addra  (ram_rd_addr_d1),     //在延迟的第三个时钟周期,当前行的数据写入RAM0.dina   (data_i_d2),.clkb   (clk),.addrb  (ram_rd_addr),    .doutb  (data1_o)              //延迟一个时钟周期,输出RAM0中前一行图像的数据
);//寄存前一行图像的数据
always@(posedge clk)begindata1_o_d0  <= data1_o;
end//用于存储前前一行图像的RAM
blk_mem_gen_0  u_ram_1024x8_1(.clka   (clk),.wea    (de_i_d1),.addra  (ram_rd_addr_d0),.dina   (data1_o_d0),       //在延迟的第二个时钟周期,将前一行图像的数据写入RAM1.clkb   (clk),.addrb  (ram_rd_addr),.doutb  (data2_o)           //延迟一个时钟周期,输出RAM1中前前一行图像的数据
);endmodule

仿真模块

`timescale 1ns/1nsmodule pic_tb();reg             clk,rst_n				;reg [23:0]      data_in					;
wire      		hdmi_hs,hdmi_vs,hdmi_de ;
wire [23:0]  	hdmi_data  				;
wire 			data_req   				;reg  			vs_i,de_i	;
wire 			vs_o,de_o		;
wire [23:0]		mat11, mat12, mat13 ;
wire [23:0]		mat21, mat22, mat23 ;
wire [23:0]		mat31, mat32, mat33 ;
//延迟1clk,与data同步,hdmi时序中,data比de延迟了一个时钟周期
always @(posedge clk)beginvs_i <= hdmi_vs;de_i <= hdmi_de;
endinitial beginclk = 1;rst_n = 0;#20 rst_n = 1;
end
always #10 clk = ~clk;reg [23:0] img[0:1280*720-1];
reg [31:0] addr;
initial begin$readmemh("D:/pic/img2txt.txt",img);
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginaddr <= 0		;data_in <= 0	;endelse if(data_req) begindata_in	 <= img[addr];addr	 <= addr + 1;if(addr == (1280*720-1))addr <= 0;end
endhdmi_tim_gen u_hdmi_tim_gen(.clk		 	(clk),	.rst_n	  		(rst_n),//input.data_in	 	(data_in),//output.hdmi_hs	 	(hdmi_hs),.hdmi_vs	 	(hdmi_vs),.hdmi_de	 	(hdmi_de),.hdmi_data 		(hdmi_data),.data_req  		(data_req)
);kernel_3x3_gen u_kernel_3x3_gen(.clk        (clk), .rst_n      (rst_n),//预处理灰度数据.vs_i    		 (vs_i),.de_i     		 (de_i), .data_i          (hdmi_data),//输出3x3矩阵.vs_o   		(vs_o),.de_o    		(de_o),.mat11         (mat11),    .mat12         (mat12),    .mat13         (mat13),.mat21         (mat21),    .mat22         (mat22),    .mat23         (mat23),.mat31         (mat31),    .mat32         (mat32),    .mat33         (mat33)
);endmodule

整体架构

仿真结果

截取部分数据结果

mat31、mat32、mat33是第一行数据(最先输入的那一行),mat11、mat12、mat13是第三行数据(最后输入的那一行),可以看见数据的移位满足像素矩阵的要求。

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

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

相关文章

【LeetCode热题100】74. 搜索二维矩阵(二分)

一.题目要求 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;…

特别详细的Spring Cloud 系列教程1:服务注册中心Eureka的启动

Eureka已经被Spring Cloud继承在其子项目spring-cloud-netflix中&#xff0c;搭建Eureka Server的方式还是非常简单的。只需要通过一个独立的maven工程即可搭建Eureka Server。 我们引入spring cloud的依赖和eureka的依赖。 <dependencyManagement><!-- spring clo…

CentOS7.9.2009安装elasticsearch7.11.1(单节点)

本文章使用CentOS7.9.2009服务器安装elasticsearch7.11.1软件 1.服务器信息 [root@elasticsearch ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [root@elasticsearch ~]# [root@elasticsearch ~]# cat /etc/hosts | grep elasticsearch 192.168.10.24…

【MacBook系统homebrew镜像记录】

安装 使用Homebrew 国内源安装脚本,贼方便&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"切换至清华大学镜像源&#xff1a; 命令合并&#xff1a; 分别切换了 brew.git、 homebrew-core.git、 homebrew-…

windows一键休眠,一键唤醒

1.使windows睡眠不可用&#xff0c;cmd以管理员身份运行&#xff1a; powercfg.exe /hibernate off 2.桌面创建快捷键 Rundll32.exe Powrprof.dll,SetSuspendState Sleep

探索7个MAMP本地开发环境的高效替代软件

什么是本地开发环境 本地开发环境是Web开发环境中的一种类型&#xff0c;它是指开发者自己的计算机上配置的一套用于开发和测试网站或应用程序的软件集合。这套环境使得开发者可以在本地计算机上构建和测试网站&#xff0c;而无需实时部署到服务器。 创建本地开发环境有两种方…

ubuntu系统安装k8s1.28精简步骤

目录 一、规划二、环境准备2.1 配置apt仓库配置系统基本软件仓库配置k8s软件仓库安装常用软件包 2.2 修改静态ip、ntp时间同步、主机名、hosts文件、主机免密2.3 内核配置2.4 关闭防火墙、selinux、swap2.5 安装软件安装docker安装containerd安装k8s软件包 三、安装配置k8s3.1 …

文本识别 OCR 解决方案

Capture2Text 便携式 OCR 工具 Capture2Text 能够使用键盘快捷键快速对屏幕的一部分进行 OCR。 默认情况下&#xff0c;生成的文本将保存到剪贴板。支持中文、英文、法文、德文、日文、韩文、俄文、西班牙文等 90 多种语言。 Capture2Text 是便携式工具&#xff0c;不需要安装…

【单源最短路 图论】882. 细分图中的可到达节点

作者推荐 视频算法专题 本文涉及知识点 单源最短路 图论 LeetCode 882. 细分图中的可到达节点 给你一个无向图&#xff08;原始图&#xff09;&#xff0c;图中有 n 个节点&#xff0c;编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链&#xff0c;每条边之间…

编程杂谈-代码review

目录 1. 关于智商 2. 关于能力 3. 关于changelist 3.1 关于CL内容编写 3.2 关于CL的大小 3.3 处理审稿人的意见 4. 关于代码审查 一个人的编程能力怎么去衡量&#xff1f;特别是在面试中&#xff0c;怎么避免“高分低能儿”、“专业做题家”、“面试造火箭”&#xff0c…

【JavaEE】_Spring MVC项目获取Session

目录 1. 使用servlet原生方法获取Session 1.1 错误获取方法 1.2 正确获取方法 2. 使用Spring注解获取Session 3. 使用Spring内置对象获取Session 1. 使用servlet原生方法获取Session .java文件内容如下&#xff1a; setSession方法用于设置Session对象的内容&#xff1b;…

LeetCode-74. 搜索二维矩阵【数组 二分查找 矩阵】

LeetCode-74. 搜索二维矩阵【数组 二分查找 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;先二分查找行&#xff0c;再二分查找列。解题思路二&#xff1a;暴力遍历&#xff0c;也能过。解题思路三&#xff1a;用python的in。 题目描述&#xff1a; 给你一个满足下述两条…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之四 简单视频倒放效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之四 简单视频倒放效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之四 简单视频倒放效果 一、简单介绍 二、简单视频倒放效果实现原理 三、简单视频倒放效果案例实现…

切比雪夫窗函数

Skip to content 产品解决方案学术支持社区活动 获取 MATLAB登录到您的 MathWorks 帐户 Help Center 搜索帮助中心 帮助中心 Off-Canvas Navigation Menu Toggle Documentation Home Signal Processing Signal Processing ToolboxSpectral AnalysisWindows chebwinON…

JetBrains IDE 2024.1 发布 - 开发者工具

JetBrains IDE 2024.1 (macOS, Linux, Windows) - 开发者工具 CLion, DataGrip, DataSpell, Fleet, GoLand, IntelliJ IDEA, PhpStorm, PyCharm, Rider, RubyMine, WebStorm 请访问原文链接&#xff1a;JetBrains IDE 2024.1 (macOS, Linux, Windows) - 开发者工具&#xff0…

51单片机里面的白盒测试中

白盒测试说直白点就是&#xff0c;加入一个盒子&#xff08;中间模块&#xff09;&#xff0c;使得测试的数据可视化&#xff0c;知道是内部是怎么运作的 场景&#xff1a;51单片机与WIFI模块通信&#xff0c;不能知道他们之间到底发没发数据&#xff0c;所以引出白盒测试 测试…

前端组件化探索:打造创意Canvas绘图小程序的关键技术与实现

摘要 在前端开发领域&#xff0c;Canvas 绘图已经成为了实现用户交互和视觉展示的重要手段。尤其在移动应用和小程序开发中&#xff0c;Canvas 的应用更为广泛。本文将结合一个实际的创意绘图小程序项目&#xff0c;探讨前端组件化技术在实现绘图功能中的关键作用&#xff0c;…

网络基础知识入门

目录 一、局域网与广域网 1、局域网 2、广域网 二、协议 1、概念 2、协议的理解 3、协议的分层 1、分层 2、OSI七层模型 三、网络传输基本流程 1、报头 2、局域网通信原理 3、跨网络传输流程 四、IP地址和MAC地址 1、IP地址 2、MAC地址 3、两者的区别 一、局域…

C语言 文件函数

目录 1. 文件的打开和关闭 2. 文件的顺序读写 2.1 顺序读写函数介绍 2.2读文件&#xff08;读文件只能读一次&#xff09; 2.3写文件 3. 文件的随机读写 3.1 fseek 3.2 ftell 3.3 rewind 4.文件读取结束的判定 4.1 被错误使误的 feof 我对读写的理解&#xff1a;(从…

Svg Flow Editor 原生svg流程图编辑器(五)

系列文章 Svg Flow Editor 原生svg流程图编辑器&#xff08;一&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;二&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;三&#xff09; Svg Flow Editor 原生svg流程图编辑器&#xff08;四&#xf…