当前位置: 首页 > news >正文

Sobel边沿检测

前言

        Sobel边沿检测是一种用于图像处理的边缘检测技术。它通过计算图像的梯度来识别图像中的边缘。Sobel算子是一种常用的边缘检测滤波器,它利用两个卷积核来分别检测水平和垂直方向的边缘。Sobel边沿检测在很多图像处理应用中都很有用,比如图像分割、目标检测等。它的优点是计算简单且效果较好,但在噪声较多的图像中可能需要结合其他方法进行处理。

正文

一、Sobel边沿检测

        1.项目需求

        通过RS232将原始图片的灰度图像数据发送到FPGA,FPGA实验Sobel算法对图像进行处理,将处理完的数据通过VGA接口在640*480显示器上显示。

        2.技术介绍

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

        3.顶层架构

        4.端口描述

clk_in时钟(50Mhz)
rst_n_in系统复位信号
rxRS232数据接收
[7:0]data显示颜色数据
hx行同步信号
vx场同步信号
txRS232数据发送

二、代码验证

数据生成MATLAB

clear   %清零命令窗口
clc     %清理工作区RGB = imread('abc.bmp');%图片输入%100*100*3
red = RGB(:,:, 1);%红色分量提取figure;%创建窗口
imshow(red);
[height,width,z] = size(red);
% rgb矩阵初始化
data = zeros( 1 ,height*width);% 转换为8位数据
for i = 1:heightfor j = 1:width data((i-1)*width + j ) = bitshift(red(i,j),-5);%红色数据右移动5位end
endfid = fopen ('data.txt', 'w+');%新建文件for i = 1:height*widthfprintf(fid,'%02x ',data(i));
endfclose(fid);

sobel算法模块

module sobel_ctrl1(input 			clk  		,input 			rst_n		,input	[7:0]		data		,//rs232传输到FPGA的数据input				flag		,output reg[7:0]data_out	,//求和结果output reg		out_flag	 //输出使能
);parameter l_max = 'd99,//列数h_max = 'd99;//行数parameter Th = 8'b000_011_00;	//灰度阈值parameter black = 8'b000_000_00,//颜色white = 8'b111_111_11;reg	[9:0]l_cnt		;//列计数器	
reg	[9:0]h_cnt		;//行计数器reg	fifo1_en	;//fifo_1写使能	 
reg	[7:0]fifo1_data;//fifo_1写数据reg	fifo2_en	;//fifo_2写使能	 
reg	[7:0]fifo2_data;//fifo_2写数据reg	rd_en;//读使能信号	
wire	[7:0]data1;	//fifo1读出数据
wire	[7:0]data2;	//fifo2读出数据
reg	add_en;//求和标志信号	
reg	data_flag;//fifo1的写使能信号	reg 	[7:0]cnt_rd;//寄存计数器
reg	[7:0]data1_r;
reg	[7:0]data2_r;	
reg	[7:0]data_r;reg 	rd_en_reg;
reg	re_en_reg1;
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 	gx_gy_flag;//计算标志信号
reg	[8:0]gx;//计算
reg	[8:0]gy;//计算reg 	gxy_flag;//输出有效
reg 	[7:0]gxy;//计算结果reg	com_flag;//比较always@(posedge clk,negedge rst_n)//列计数器驱动
beginif(rst_n == 0)l_cnt <= 10'd0;elseif((l_cnt == l_max)&&(flag == 1'b1))l_cnt <= 10'd0;elseif(flag == 1'b1)l_cnt <= l_cnt + 10'd1;elsel_cnt <= l_cnt;
endalways@(posedge clk,negedge rst_n)//行计数器驱动
beginif(rst_n == 0)h_cnt <= 10'd0;elseif((h_cnt == h_max)&&(l_cnt == l_max)&&(flag == 1'b1))h_cnt <= 10'd0;elseif((l_cnt == l_max)&&(flag == 1'b1))h_cnt <= h_cnt + 10'd1;elseh_cnt <= h_cnt;
endalways@(posedge clk,negedge rst_n)//fifo_1写使能
beginif(rst_n == 0)fifo1_en <= 1'b0;elseif((h_cnt == 0)&&(flag == 1'b1))fifo1_en <= 1'b1;elsefifo1_en <= data_flag;
endalways@(posedge clk,negedge rst_n)//fifo_1写数据
beginif(rst_n == 0)fifo1_data <= 8'd0;elseif((h_cnt == 0)&&(flag == 1'b1))fifo1_data <= data;elseif(data_flag == 1'b1)fifo1_data <= data2;elsefifo1_data <= fifo1_data;
endalways@(posedge clk,negedge rst_n)//fifo_2写使能
beginif(rst_n == 0)fifo2_en <= 1'b0;elseif((h_cnt >= 8'd1)&&(h_cnt <= h_max - 8'd1)&&(flag == 1'b1))fifo2_en <= 1'b1;elsefifo2_en <= 1'b0;
endalways@(posedge clk,negedge rst_n)//fifo_2写数据
beginif(rst_n == 0)fifo2_data <= 8'd0;elseif((h_cnt >= 8'd1)&&(h_cnt <= h_max - 8'd1)&&(flag == 1'b1))fifo2_data <= data;elsefifo2_data <= fifo2_data;
endalways@(posedge clk,negedge rst_n)//fifo读写使能(共用)
beginif(rst_n == 0)rd_en <= 1'b0;elseif((h_cnt >= 8'd2)&&(flag <= h_max)&&(flag == 1'b1))rd_en <= 1'b1;elserd_en <= 1'b0;
endalways@(posedge clk,negedge rst_n)//fifo1的写使能信号	
beginif(rst_n == 0)data_flag <= 1'b0;elseif((fifo2_en == 1'b1)&&(rd_en == 1'b1))data_flag <= 1'b1;elsedata_flag <= 1'b0;
endalways@(posedge clk,negedge rst_n)//寄存计数器
beginif(rst_n == 0)cnt_rd <= 8'd0;elseif((cnt_rd == l_max)&&(rd_en == 1'b1))cnt_rd <= 8'd0;elseif((rd_en == 1'b1))cnt_rd <= cnt_rd + 8'd1;elsecnt_rd <= cnt_rd;
endalways@(posedge clk,negedge rst_n)//数据寄存
beginif(rst_n == 0)begindata1_r <= 8'd0;data2_r <= 8'd0;data_r  <= 8'd0;endelseif(rd_en_reg == 1'b1)begindata1_r <= data1;data2_r <= data2;data_r  <= data;endelsebegindata1_r <= data1_r;data2_r <= data2_r;data_r  <= data_r ;end
endalways@(posedge clk,negedge rst_n)//数据寄存读使能信号
beginif(rst_n == 0)rd_en_reg <= 1'b0;	elseif(rd_en == 1'b1)rd_en_reg <= 1'b1;elserd_en_reg <= 1'b0;
endalways@(posedge clk,negedge rst_n)//数据寄存读使能信号打排
beginif(rst_n == 0)re_en_reg1 <= 1'b0;	elseif(rd_en_reg == 1'b1)re_en_reg1 <= 1'b1;elsere_en_reg1 <= 1'b0;
endalways@(posedge clk,negedge rst_n)//计算矩阵赋值
beginif(rst_n == 0)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;endelsebegina3 <= data1_r;b3 <= data2_r;c3 <= data_r;a2 <= a3;b2 <= b3;c2 <= c3;a1 <= a2;b1 <= b2;c1 <= c2;end
endalways@(posedge clk,negedge rst_n)//计算使能信号
beginif(rst_n == 0)		gx_gy_flag <= 1'b0;elseif((re_en_reg1 == 1'b1)&&((cnt_rd >= 8'd3)||(cnt_rd == 8'd0)))gx_gy_flag <= 1'b1;elsegx_gy_flag <= 1'b0;	
endalways@(posedge clk,negedge rst_n)//计算准备
beginif(rst_n == 0)		gx <= 9'b0;elseif(gx_gy_flag == 1'b1 )gx <= (a3-a1)+((b3-b1)<<1)+(c3-c1);elsegx <= gx;
endalways@(posedge clk,negedge rst_n)//计算准备
beginif(rst_n == 0)		gy <= 9'b0;elseif(gx_gy_flag == 1'b1 )gy <= (a1-c1)+((a2-c2)<<1)+(a3-c3);elsegy <= gy;
end	always@(posedge clk,negedge rst_n)//计算标志信号
beginif(rst_n == 0)		gxy_flag <= 1'b0;elseif(gx_gy_flag == 1'b1)gxy_flag <= 1'b1;elsegxy_flag <= 1'b0;	
end		always@(posedge clk,negedge rst_n)//计算标志信号
beginif(rst_n == 0)		gxy <= 8'b0;elseif((gx[8] == 1'b1)&&(gy[8] == 1'b1)&&(gxy_flag == 1'b1))//--gxy <= (~gx[7:0] +1'b1) + (~gy[7:0] + 1'b1);elseif((gx[8] == 1'b1)&&(gy[8] == 1'b0)&&(gxy_flag == 1'b1))//-+gxy <= (~gx[7:0] +1'b1) + gy[7:0];elseif((gx[8] == 1'b0)&&(gy[8] == 1'b1)&&(gxy_flag == 1'b1))//+-gxy <= gx[7:0] + (~gy[7:0] + 1'b1);elseif((gx[8] == 1'b0)&&(gy[8] == 1'b0)&&(gxy_flag == 1'b1))//++gxy <= gx[7:0] + gy[7:0];elsegxy <= gxy;
endalways@(posedge clk,negedge rst_n)//比较信号
beginif(rst_n == 0)			com_flag  <= 1'b0;elseif(gxy_flag == 1'b1)com_flag  <= 1'b1;elsecom_flag  <= 1'b0;
endalways@(posedge clk,negedge rst_n)//结果输出
beginif(rst_n == 0)data_out <= 8'd0;elseif((com_flag == 1'b1)&&(gxy > Th))data_out <= black;elseif(com_flag == 1'b1)data_out <= white;elsedata_out <= data_out;
endalways@(posedge clk,negedge rst_n)//结果输出使能
beginif(rst_n == 0)out_flag <= 1'b0;elseif(com_flag == 1'b1)out_flag <= 1'b1;elseout_flag <= 1'b0;
endfifo_sobel	fifo1_inst (.clock 	( clk  		 ),.data 	( fifo1_data ),.rdreq 	( rd_en 		 ),.wrreq 	( fifo1_en   ),.q 		( data1 ));fifo_sobel	fifo2_inst (.clock 	( clk   		 ),.data 	( fifo2_data ),.rdreq 	( rd_en      ),.wrreq 	( fifo2_en   ),.q 		( data2 ));endmodule

RS232数据接收

module uart_rx(input 			clk		,input				rst_n 	,input				rx			,output reg[7:0]po_data	,	//接收到的数据output reg  	po_flag		//数据输出有效);parameter 	uart_btl ='d9600			;//串口波特率
parameter 	clk_shuj ='d50_000_000	;//时钟频率parameter 	cnt_max  =clk_shuj/uart_btl;reg 			reg1,reg2,reg3	;//打排延迟周期,消除亚稳态
reg 			flag				;//uart工作信号(uart工作时在工作状态切换后产生一个时钟周期高电平)
reg 			en					;//uart工作使能标志信号(uart工作时在工作状态切换后的下一个时钟周期开始一直拉高,直到检测到停止信号)
reg [15:0]	cnt				;//每比特数据持续时钟周期计数器
reg [3 :0]	bit_cnt			;//数据个数计数器
reg 			bit_flag			;//每bit数据接收有效信号
reg [7 :0]	rx_data			;//存储输入数据
reg			rx_flag			;//输入数据并位结束信号always@(posedge clk,negedge rst_n)//数据打排1
beginif(rst_n == 0)reg1 <= 1'b1;elsereg1 <= rx;
end	always@(posedge clk,negedge rst_n)//数据打排2
beginif(rst_n == 0)reg2 <= 1'b1;elsereg2 <= reg1;
end	always@(posedge clk,negedge rst_n)//数据打排3
beginif(rst_n == 0)reg3 <= 1'b1;elsereg3 <= reg2;
end	always@(posedge clk,negedge rst_n)//uart工作信号赋值
beginif(rst_n == 0)flag <= 1'b0;elseif((reg2 == 1'b0)&&(reg3 == 1'b1)&&(en == 1'b0))flag <= 1'b1;elseflag <= 1'b0;
endalways@(posedge clk,negedge rst_n)//uart工作使能标志信号赋值
beginif(rst_n == 0)en <= 1'b0;elseif(flag == 1'b1)en <= 1'b1;elseif((bit_cnt == 4'd8)&&(bit_flag == 1'b1))en <= 1'b0;elseen <= en;
end			always@(posedge clk,negedge rst_n)//每比特数据持续时钟周期计数器驱动逻辑
beginif(rst_n == 0)	cnt <= 16'd0;else 	if((cnt == cnt_max - 1)||(en == 1'b0))cnt <= 16'd0;elsecnt = cnt + 1'b1;
endalways@(posedge clk,negedge rst_n)//每比特数据持续时钟周期计数器驱动逻辑
beginif(rst_n == 0)	bit_flag <= 1'b0;elseif(cnt == cnt_max/2 - 1)bit_flag <= 1'b1;elsebit_flag <= 1'b0;
endalways@(posedge clk,negedge rst_n)//数据个数计数器驱动逻辑
beginif(rst_n == 0)	bit_cnt <= 4'd0;else	if((bit_cnt == 4'd8)&&(bit_flag == 1'b1))bit_cnt <= 4'd0;else if(bit_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;
endalways@(posedge clk,negedge rst_n)//接收数据并位
beginif(rst_n == 0)rx_data <= 8'd0;elseif((bit_cnt >= 4'd1)&&(bit_cnt <= 4'd8)&&(bit_flag == 1'b1))rx_data <= {reg3,rx_data[7:1]};
endalways@(posedge clk,negedge rst_n)//输入数据并位结束信号
beginif(rst_n == 0)rx_flag <= 1'b0;else if((bit_cnt == 4'd8)&&(bit_flag == 1'b1))rx_flag <= 1'b1;elserx_flag <= 1'b0;
endalways@(posedge clk,negedge rst_n)//输出数据传递
beginif(rst_n == 0)po_data <= 8'd0;else if(rx_flag == 1'b1)po_data <= rx_data;elsepo_data <= po_data;
endalways@(posedge clk,negedge rst_n)//输出使能
beginif(rst_n == 0)po_flag <= 1'b0;else po_flag <= rx_flag;
endendmodule

RS232数据发送

module uart_tx(input       clk     ,input       rst_n   ,input [7:0] pi_data ,input       pi_flag ,output reg  tx
);parameter 	uart_btl ='d9600			;//串口波特率
parameter 	clk_shuj ='d50_000_000	;//时钟频率parameter 	cnt_max  =clk_shuj/uart_btl;reg         en      ;
reg [15:0]  cnt     ;//每bit数据传输完成计数器
reg         flag    ;//
reg [3 :0]  bit_cnt ;//bit计数器always@(posedge clk,negedge rst_n)
begin if(rst_n == 0)en <= 1'b0;elseif(pi_flag == 1'b1)en <= 1'b1;elseif((bit_cnt == 4'd9)&&(flag == 1'b1))en <= 1'b0;else en <= en;          
endalways@(posedge clk,negedge rst_n)
beginif(rst_n == 0)cnt <= 16'd0;elseif((en == 1'b0)||(cnt == cnt_max - 1'b1))cnt <= 16'd0;elseif(en == 1'b1)cnt <= cnt + 1'b1;elsecnt <= cnt;
endalways@(posedge clk,negedge rst_n)
beginif(rst_n == 0)flag <= 1'b0;else if(cnt == 16'd1)flag <= 1'b1; elseflag <= 1'b0;
endalways@(posedge clk,negedge rst_n)
beginif(rst_n == 0)bit_cnt <= 4'd0;elseif((bit_cnt == 4'd9)&&(flag == 1'b1))bit_cnt <= 4'd0;elseif((en == 1'b1)&&(flag == 1'b1))bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;
end                always@(posedge clk,negedge rst_n)
beginif(rst_n == 0)tx <= 1'b1;elseif(flag == 1'b1)case(bit_cnt)0:  tx <= 1'b0;1:  tx <= pi_data[0];2:  tx <= pi_data[1];3:  tx <= pi_data[2];4:  tx <= pi_data[3];5:  tx <= pi_data[4];6:  tx <= pi_data[5];7:  tx <= pi_data[6];8:  tx <= pi_data[7];9:  tx <= 1'b1;default :tx <= 1'b1;endcase    
endendmodule

VGA模块顶层

module vga_top(input 			clk_ram	,input 			clk		,input				rst_n 	,input[7:0]		po_data	,input 			po_flag	,	output   		vga_hs	,output   		vga_vs	,output[7:0]  	vga_rgb	
);wire volid_en;//数据输出有效
wire [7:0]vga_rgb_t;//显示数据
wire [9:0]vga_h;//x
wire [9:0]vga_v;//yvga_ctrl vga_ctrl(.clk			(clk			),.rst_n		(rst_n		),.in_rgb		(vga_rgb_t	),.volid_en 	(			 	),.vga_hs		(vga_hs		),.vga_vs		(vga_vs		),.vga_h		(vga_h		),//坐标.vga_v		(vga_v		),//坐标.vga_rgb		(vga_rgb		)
);vga_data vga_data(.clk_ram		(clk_ram		),.clk     	(clk     	),.rst_n   	(rst_n   	),.pix_x		(vga_h		),.pix_y		(vga_v		),.po_data		(po_data		),	//接收到的数据.po_flag		(po_flag 	),	//数据输出有效.vga_rgb_t	(vga_rgb_t	));endmodule

VGA数据生成

module vga_data(input 					clk_ram	,input               clk     	,input               rst_n   	,input[9:0]				pix_x		,input[9:0]				pix_y		,input[7:0]				po_data	,	//接收到的数据input  					po_flag	,	//数据输出有效output [7:0]		vga_rgb_t);parameter 	show_h = 10'd110,//定位点X坐标show_v = 10'd100;//定位点Y坐标parameter 	show_chan = 10'd256,//图片长度show_kuan = 10'd32;//图片宽度parameter 	show_1_rgb = 8'b000_000_00,//背景show_0_rgb = 8'b111_100_00;//图片颜色parameter 	pot_h = 10'd120,//定位点X坐标pot_v = 10'd100;//定位点Y坐标parameter 	chan = 10'd100,//图片长度kuan = 10'd100;//图片宽度	reg [255:0]	char	[31:0];//存储字符数据
wire[9:0]	char_x;
wire[9:0]	char_y;reg [07:0]vga_rgb;
wire[07:0]rom_data;//存储RAM数据
reg [13:0]addr;//ip核读地址
reg [13:0]wier;//ip核写地址
wire rd_en ;//ip核读使能assign char_x =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_x - show_h):10'h3ff;
assign char_y =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_y - show_v):10'h3ff;always@(posedge clk)
beginchar[0  ] <= 256'h0000000000000000000000000001000000200000000100000020000000010000; char[1  ] <= 256'h0020000000010000003FFFFFFFFF0000003FFFFFFFFF0000003FFFFFFFFF0000;char[2  ] <= 256'h003FFFFFFFFF0000003000180001000000300018000100000030001800010000;char[3  ] <= 256'h0030001800010000003000180000000000300018000000000030001800000000;char[4  ] <= 256'h003000180000000000300018000000000030003C000000000030007E00000000;char[5  ] <= 256'h003803FFE00000000038000000000000003C000000000000003E000000000000;char[6  ] <= 256'h003F8000000000000003C0000000000000006000000000000000000000000000;char[7  ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;char[8  ] <= 256'h0000000000000000000000000001000000200000000100000020000000010000;char[9  ] <= 256'h0020000000010000003FFFFFFFFF0000003FFFFFFFFF0000003FFFFFFFFF0000;char[10 ] <= 256'h003FFFFFFFFF0000003000060001000000300006000100000030000600010000;char[11 ] <= 256'h0030000600010000003000060000000000300006000000000030000600000000;char[12 ] <= 256'h00300006000000000038000E000000000038000E00000000001C001C00000000;char[13 ] <= 256'h001E003C00000000000F80F800000000000FFFF8000000000007FFF000000000;char[14 ] <= 256'h0001FFC00000000000007F000000000000000000000000000000000000000000;char[15 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;char[16 ] <= 256'h00000000000000000000000000000000000000FFE000000000000FFFFE000000;char[17 ] <= 256'h00007FFFFF8000000000FFFFFFE000000003FE001FF800000007E00000FC0000;char[18 ] <= 256'h000F0000003C0000001E0000000E0000001C0000000600000038000000070000;char[19 ] <= 256'h0030000000030000003000000003000000300000000300000030000100030000;char[20 ] <= 256'h00300001000300000018000100060000001C0001800E0000001E0001FFFC0000;char[21 ] <= 256'h001F8001FFF80000001FF001FFF8000000003801FFF800000000000180000000;char[22 ] <= 256'h0000000100000000000000010000000000000001000000000000000000000000;char[23 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;char[24 ] <= 256'h00000000000100000000000000010000000000000003000000000000001F0000;char[25 ] <= 256'h0000000001FF0000000000001FE3000000000001FC0100000000001FC0010000;char[26 ] <= 256'h000001FCC000000000001FC0C00000000001FC00C0000000001FC000C0000000;char[27 ] <= 256'h003E0000C0000000007F0000C0000000007FF000C0000000003FFF00C0000000;char[28 ] <= 256'h0001FFF0C000000000001FFFC0000000000001FFFC0100000000001FFFC10000;char[29 ] <= 256'h00000001FFFF0000000000000FFF00000000000000FF000000000000000F0000;char[30 ] <= 256'h0000000000030000000000000001000000000000000100000000000000000000;char[31 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
endalways @(posedge clk,negedge rst_n)
beginif(rst_n == 0)vga_rgb <= show_1_rgb;elseif(	((pix_x >= show_h - 1'b1)&&(pix_x < (show_h + show_chan - 1'b1)))&&	((pix_y >= show_v )&&(pix_y <(show_v + show_kuan)))&&	(char[char_y][10'd255 - char_x] == 1'b1))vga_rgb  <= show_0_rgb;elsevga_rgb <= show_1_rgb;
endassign rd_en = (((pix_x >=  pot_h)&&(pix_x < pot_h + chan))&&((pix_y >= pot_v)&&(pix_y <pot_v + kuan)))? 1'b1:1'b0;//ip核图片显示区域always @(posedge clk,negedge rst_n)//读地址
beginif(rst_n == 0)addr <= 14'd0;elseif(addr == 14'd9999)addr <= 14'd0;elseif(rd_en == 1'b1)addr <= addr + 14'd1;elseaddr <= addr;
endalways @(posedge clk_ram,negedge rst_n)//写地址
beginif(rst_n == 0)wier <= 14'd0;elseif((wier == 14'd9999)&&(po_flag == 1'b1))wier <= 14'd0;elseif(po_flag == 1'b1)wier <= wier + 14'd1;elsewier <= wier;
end			ram_vga	ram_vga_inst (.data 		( po_data 	),.inclock 	( clk_ram 	),.outclock 	( clk 		),.rdaddress 	( addr 		),.wraddress 	( wier 		),.wren 		(  ~po_flag ),.q 			( rom_data 	)
);assign vga_rgb_t = (rd_en)?rom_data:vga_rgb;endmodule 

VGA驱动模块

module vga_ctrl(input    		clk		,input    		rst_n		,input[7:0]		in_rgb	,output			volid_en ,output   		vga_hs	,output   		vga_vs	,output[9:0]   	vga_h		,//坐标output[9:0]   	vga_v		,//坐标output[7:0]  	vga_rgb
);reg [9:0] cnt_hs;//列计数器
reg [9:0] cnt_vs;//行计数器
wire hs_en;//列有效显示区域
wire vs_en;//行有效显示区域
//wire volid_en;//有效显示区域parameter 	hs_sync = 10'd96	,//同步hs_bask = 10'd40	,//后沿hs_left = 10'd8	,//左边hs_vali = 10'd640	,//有效hs_righ = 10'd8	,//右边hs_fpon = 10'd8	,//前沿hs_tota = 10'd800	;//总共parameter 	vs_sync = 10'd2	,//同步   vs_bask = 10'd25	,//后沿	  vs_left = 10'd8	,//上边   vs_vali = 10'd480	,//有效 vs_righ = 10'd8	,//底边   vs_fpon = 10'd2	,//前沿   vs_tota = 10'd525	;//总共				always @(posedge clk,negedge rst_n)
beginif(rst_n == 0)cnt_hs <= 10'd0;elseif(cnt_hs < hs_tota - 10'd1)cnt_hs <= cnt_hs + 10'd1;elsecnt_hs <= 10'd0;
end always @(posedge clk,negedge rst_n)
beginif(rst_n == 0)cnt_vs <= 10'd0;elseif(cnt_hs ==  hs_tota - 10'd1)if(cnt_vs < vs_tota - 10'd1)cnt_vs <= cnt_vs + 10'd1;else cnt_vs <= 10'd0;elsecnt_vs <= cnt_vs;
end assign vga_hs = (cnt_hs < hs_sync)?1'b0:1'b1;//行同步信号赋值assign vga_h  = (volid_en == 1'b1)?(cnt_hs - (hs_sync + hs_bask + hs_left)):10'd0;//行坐标(Y)assign vga_vs = (cnt_vs < vs_sync)?1'b0:1'b1;//场同步信号赋值assign vga_v  = (volid_en == 1'b1)?(cnt_vs - (vs_sync + vs_bask + vs_left)):10'd0;//列坐标(X)assign hs_en = ((cnt_hs >= hs_sync + hs_bask + hs_left )&&(cnt_hs < hs_sync + hs_bask + hs_left + hs_vali))?1'b1:1'b0;assign vs_en = ((cnt_vs >= vs_sync + vs_bask + vs_left )&&(cnt_vs < vs_sync + vs_bask + vs_left + vs_vali))?1'b1:1'b0;assign volid_en = hs_en & vs_en;//显示区域assign vga_rgb = (volid_en == 1'b1)?in_rgb:8'd0;endmodule 

顶层连线

module sobel_vga_top (input 			clk_in	,input				rst_n_in	,input				rx			,output [7:0]	data		,output 			hx			,output			vx			,output			tx				
);wire clk;//25Mhz
wire rst_n;//复位信号
wire clk_ram;//50Mhzwire[7:0]po_data;//接收到的数据
wire  	po_flag;//数据输出有效wire[7:0]data_out;//边沿数据
wire		out_flag;pll_25	pll_25_inst (.areset 	( ~rst_n_in ),.inclk0 	( clk_in ),.c0 		( clk_ram),.c1 		( clk 	),.locked 	( rst_n 	)
);uart_rx uart_rx(.clk		(clk_ram		),.rst_n 	(rst_n 	),.rx		(rx		),.po_data	(po_data	),	//接收到的数据.po_flag	(po_flag	)	//数据输出有效);sobel_ctrl1 sobel_ctrl1(.clk		(clk		),.rst_n	(rst_n	),.data		(po_data	),.flag		(po_flag	),.data_out(data_out),.out_flag(out_flag)	
);vga_top vga_top(.clk_ram	(clk_ram	),.clk		(clk		),.rst_n 	(rst_n 	),.po_data	(data_out),.po_flag	(out_flag),	.vga_hs	(hx		),.vga_vs	(vx		),.vga_rgb	(data		)
);uart_tx uart_tx(.clk     (clk_ram ),.rst_n   (rst_n   ),.pi_data (data_out),.pi_flag (out_flag),.tx		(tx		)
);endmodule

仿真模块

`timescale 1ns/1ps
module sobel_vga_top_tb;reg 			clk	;reg 			rst_n	;reg 			rx		;reg [7:0]	data_a[9999:0];//数据存储器wire 			tx		;wire [7:0]	data	;wire 			hx		;wire			vx		;sobel_vga_top fifo_add_top(.clk_in	(clk		),.rst_n_in(rst_n	),.rx		(rx		),.data		(data		),.hx		(hx		),.vx		(vx		),.tx		(tx		)	
);initial $readmemh("E:/FPGA_exer/Sobel_vga_0906/doc/data.txt",data_a);//调用目标位置文件initial clk = 1'b1;
always #10 clk = ~clk;initial beginrst_n = 1'b0;rx = 1'b1;#40rst_n = 1'b1;#200re_byte();#100000$stop;
end
//璧嬪€煎嚱鏁	task	rx_bit(input [7:0]data);integer i;for(i = 0;i < 10; i = i + 1)//寰幆9娆			begincase(i)0:  rx <= 1'b0;1:  rx <= data[0];2:  rx <= data[1];3:  rx <= data[2];4:  rx <= data[3];5:  rx <= data[4];6:  rx <= data[5];7:  rx <= data[6];8:  rx <= data[7];9:  rx <= 1'b1;endcase#(5208*20);//姣忔寤舵椂endendtask//defparam fifo_add_top.uart_rx.clk_shuj = 50_000;task re_byte();integer j;for(j = 0;j < 10000;j = j + 1)rx_bit(data_a[j]);//浼犻€鈥斺€锛涓暟鎹	endtaskendmodule 

三、仿真验证

进行仿真,运行仿真代码,可以看到数据输出完整。

data_out在0使显示黑色,在255时显示白色,由此提取出图像边缘。

数据提取成功,数据对比正确,实验成功。

参考资料

边缘检测

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • TPM赋能智能机器人:重塑工业4.0时代的生产力革命
  • 【解决bug之路】npm install node-sass(^4.14.1)连环报错解决!!!(Windows)
  • 达梦数据库导入dmp文件数据
  • 关于Redis集群同步/持久化/淘汰机制的详解
  • html知识点总结
  • Windows子系统Ubuntu安装MySQL及windows的navicate连接
  • NDP协议是怎样帮助IPv6实现网络安全运行的?
  • 技术分享-商城篇-营销模块-优惠券-常见问题(二十五)
  • 油耳朵耳屎怎么清理?可视耳勺使用方法
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】
  • 搭建Windows下的Rust开发环境
  • mapActions辅助函数的使用
  • 操作系统 --- 进程的状态和状态转换
  • 10个Python办公自动化案例
  • Docker容器的基础命令操作大全(入门必看)
  • 2017年终总结、随想
  • angular2开源库收集
  • Flex布局到底解决了什么问题
  • JAVA_NIO系列——Channel和Buffer详解
  • pdf文件如何在线转换为jpg图片
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 简单易用的leetcode开发测试工具(npm)
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 我的面试准备过程--容器(更新中)
  • 源码安装memcached和php memcache扩展
  • 自动记录MySQL慢查询快照脚本
  • 你对linux中grep命令知道多少?
  • PostgreSQL之连接数修改
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • (1)STL算法之遍历容器
  • (2)nginx 安装、启停
  • (4.10~4.16)
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (六)vue-router+UI组件库
  • (一)WLAN定义和基本架构转
  • (转)创业的注意事项
  • (转载)Google Chrome调试JS
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (自适应手机端)响应式服装服饰外贸企业网站模板
  • .JPG图片,各种压缩率下的文件尺寸
  • .NET BackgroundWorker
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .net 程序发生了一个不可捕获的异常
  • .NET中两种OCR方式对比
  • /dev下添加设备节点的方法步骤(通过device_create)
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [Algorithm][综合训练][kotori和气球][体操队形][二叉树中的最大路径和]详细讲解
  • [Android] Amazon 的 android 音视频开发文档
  • [bzoj1912]异象石(set)
  • [c]统计数字
  • [DDR5 Jedec 4-1] 预充电命令 Precharge
  • [Docker]五.Docker中Dockerfile详解