概述
边缘检测, 针对的是灰度图像, 顾名思义,检测图像的边缘, 是针对图像像素点的一种计算, 目的是标识数字图像中灰度变化明显的点。(周围灰度急剧变化的像素的集合,这个突变的就是变化率最大的地方,即一阶导数最大的地方)图像的边缘检测,在保留了图像的重要结构信息的同时,剔除了可以认为不相关的信息,大幅度减少了数据量,便于图像的传输和处理。
sobel边缘检测算子、Robert边缘检测算子等为典型的一阶微分算子,可以较好的捕捉图像灰度变化的边缘。对应的二阶边缘算子,如Laplacian边缘检测算子,可以更好的捕捉图像灰度变化的边缘,而对缓慢变化的区域不敏感。
算法阈值设置是关键,不同阈值下的边缘检测效果不同,阈值设置越小(64),则越容易引起脏点,但是边缘保持较粗,反之,阈值设置越大(96),则能屏蔽一些较小梯度的点,但是边缘相应会变得更细。
Matlab实现
function Q=sobel_detector(IMG,thresh)
[h,w] = size(IMG);
Q = ones(h,w);
% -------------------------------------------------------------------------
% Gx Gy Pixel
% [ -1 0 +1 ] [ -1 -2 -1 ] [ P1 P2 P3 ]
% [ -2 0 +2 ] [ 0 0 0 ] [ P4 P5 P6 ]
% [ -1 0 +1 ] [ +1 +2 +1 ] [ P7 P8 P9 ]
Sobel_X = [-1, 0, 1, -2, 0, 2, -1, 0, 1]; % Weight x
Sobel_Y = [-1,-2,-1, 0, 0, 0, 1, 2, 1]; % Weight y
IMG_Gray = double(IMG);
IMG_Sobel = ones(h,w);
n=3;
for i=1 : h
for j=1:w
if(i<1 || i>h-1 || j<1 || j>w-1)
IMG_Sobel(i,j) = 0; %边缘像素不处理
else
temp1 = Sobel_X(1) * IMG_Gray(i-1,j-1) + Sobel_X(2) * IMG_Gray(i-1,j) + Sobel_X(3) * IMG_Gray(i-1,j+1) +...
Sobel_X(4) * IMG_Gray(i,j-1) + Sobel_X(5) * IMG_Gray(i,j) + Sobel_X(6) * IMG_Gray(i,j+1) +...
Sobel_X(7) * IMG_Gray(i+1,j-1) + Sobel_X(8) * IMG_Gray(i+1,j) + Sobel_X(9) * IMG_Gray(i+1,j+1);
temp2 = Sobel_Y(1) * IMG_Gray(i-1,j-1) + Sobel_Y(2) * IMG_Gray(i-1,j) + Sobel_Y(3) * IMG_Gray(i-1,j+1) +...
Sobel_Y(4) * IMG_Gray(i,j-1) + Sobel_Y(5) * IMG_Gray(i,j) + Sobel_Y(6) * IMG_Gray(i,j+1) +...
Sobel_Y(7) * IMG_Gray(i+1,j-1) + Sobel_Y(8) * IMG_Gray(i+1,j) + Sobel_Y(9) * IMG_Gray(i+1,j+1);
temp3 = sqrt(temp1^2 + temp2^2);
if(uint8(temp3) > thresh)
IMG_Sobel(i,j) = 1;
else
IMG_Sobel(i,j) = 0;
end
end
end
end
Q=IMG_Sobel;
算法阈值设置是关键,不同阈值下的边缘检测效果不同,阈值设置越小(64),则越容易引起脏点,但是边缘保持较粗,反之,阈值设置越大(96),则能屏蔽一些较小梯度的点,但是边缘相应会变得更细。
FPGA实现
目的
串口接受图像数据,实现Sobel算法的边缘检测,并且将处理过的图像显示在RGB屏幕中
流程框图
模块作用
时钟生成模块clk_gen
:生成驱动RGB屏幕所需要的时钟信号,这里需要注意的是,使用PLL IP核所的复位信号为高有效,当locked
引脚为高点平时表示生成了稳定的时钟信号,依次来作为后续系统的复位信号。
uart_rx
uart_tx
为串口的发送和接受模块,用于接受和发送串口数据。
sobel_ctrl
实现sobel算法的核心模块。
RGB
模块,将图片数据在RGB屏幕上显示
代码
代码部分主要提供sobel_ctrl
与RGB
模块,其余请查看工程源码。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/01/21 14:52:15
// Design Name:
// Module Name: sobel_ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module sobel_ctrl
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [7:0] pi_data ,
input wire pi_flag ,
output reg [7:0] po_data ,
output reg po_flag
);
//parameter define
parameter P_LENGTH = 10'd100 , //行计数最大值
P_WIDTH = 10'd75 ; //列计数最大值
parameter THRESHOLD = 8'b000_011_00 ; //比较阈值
parameter BLACK = 8'b0000_0000 , //黑色
WHITE = 8'b1111_1111 ; //白色
//wire define
wire [7:0] data_out1 ; //fifo1数据输出
wire [7:0] data_out2 ; //fifo2数据输出
//reg define
reg [9:0] cnt_row ; //行计数,计数一行数据个数
reg [9:0] cnt_col ; //场计数,计数数据行数
reg wr_en1 ; //fifo1写使能
reg wr_en2 ; //fifo2写使能
reg [7:0] data_in1 ; //fifo1写数据输入
reg [7:0] data_in2 ; //fifo2写数据输入
reg rd_en ; //fifo1、fifo2共用的读使能
reg dout_flag ; //控制fifo1,2~84行的写使能
reg po_flag_reg ; //输出标志位缓存,rd_en延后一拍得到,控制计算po_sum
reg [9:0] cnt_rd; //读取数据计数器
reg [7:0] pi_data_delay ; //pi_data 数据寄存
reg [7:0] data_out1_delay ; //fifo1 数据输出寄存
reg [7:0] data_out2_delay ; //fifo2 数据输出寄存
reg rd_en_delay1 ; //输出数据标志信号,延后 rd_en 一拍
reg rd_en_delay2 ; //a,b,c 赋值标志信号
reg gx_gy_flag ; //gx,gy 计算标志信号
reg gxy_flag ; //gxy 计算标志信号
reg gxy_compare_flag; //阈值比较标志信号
reg [7:0] a1 ;
reg [7:0] a2 ;
reg [7:0] a3 ;
reg [7:0] b1 ;
reg [7:0] b2 ;
reg [7:0] b3 ;
reg [7:0] c1 ;
reg [7:0] c2 ;
reg [7:0] c3 ; //图像数据
reg [8:0] gx ;
reg [8:0] gy ; //gx,gy
reg [7:0] gxy ; //gxy
//*********************************************//
//******************main code******************//
//*********************************************//
//cnt_row:行计数器,计数一行数据个数
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
cnt_row <= 10'd0;
else if((cnt_row == P_LENGTH - 1'd1) && (pi_flag == 1'b1))
cnt_row <= 10'd0;
else if(pi_flag == 1'b1)
cnt_row <= cnt_row + 1'b1;
end
//cnt_col:列计数器,计数数据行数
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
cnt_col <= 10'd0;
else if((cnt_col == P_WIDTH - 1'd1) && (pi_flag == 1'b1) && (cnt_row == P_LENGTH - 1'd1))
cnt_col <= 10'd0;
else if((cnt_row == P_LENGTH - 1'd1) && (pi_flag == 1'b1))
cnt_col <= cnt_col + 1'b1;
end
//wr_en1:fifo1写使能信号,高电平有效
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
wr_en1 <= 1'b0;
else if((cnt_col == 7'd0) && (pi_flag == 1'b1))
wr_en1 <= 1'b1; //第0行写入fifo1
else
wr_en1 <= dout_flag; //2-84行写入fifo1
end
//dout_flag:控制2~P_WIDTH - 1'd1-1行wr_en1信号
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
dout_flag <= 0;
else if((wr_en2 == 1'b1) && (rd_en == 1'b1))
dout_flag <= 1'b1;
else
dout_flag <= 1'b0;
end
//wr_en2:fifo2写使能信号,高电平有效
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
wr_en2 <= 1'b0;
else if((cnt_col >= 7'd1) && (cnt_col <= P_WIDTH - 1'd1 - 1'b1) && (pi_flag == 1'b1))
wr_en2 <= 1'b1; //2~P_WIDTH - 1'd1行写入fifo2
else
wr_en2 <= 1'b0;
end
//data_in1:fifo1数据输入
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
data_in1 <= 8'b0;
else if((pi_flag == 1'b1) && (cnt_col == 7'd0))
data_in1 <= pi_data; //第0行数据暂存fifo1中
else if(dout_flag == 1'b1)
data_in1 <= data_out2;//第2~P_WIDTH - 1'd1-1行时,fifo2读出数据存入fifo1
else
data_in1 <= data_in1;
end
//data_in2:fifo2数据输入
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
data_in2 <= 8'b0;
else if((pi_flag == 1'b1)&&(cnt_col >= 7'd1)&&(cnt_col <= (P_WIDTH - 1'd1 - 1'b1)))
data_in2 <= pi_data;
else
data_in2 <= data_in2;
end
//rd_en:fifo1和fifo2的共用读使能信号
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
rd_en <= 1'b0;
else if((pi_flag == 1'b1)&&(cnt_col >= 7'd2)&&(cnt_col <= P_WIDTH - 1'd1)) //第二行之后开始读取数据
rd_en <= 1'b1;
else
rd_en <= 1'b0;
end
//cnt_rd:读取数据计数器
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
cnt_rd <= 1'd0;
else if((rd_en == 1'b1)&&(cnt_rd == P_LENGTH - 1'b1)) //读取一行数据后计数器清零
cnt_rd <= 1'd0;
else if(rd_en == 1'b1)
cnt_rd <= cnt_rd + 1'b1;
end
//rd_en_delay1:读使能延后一拍
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
rd_en_delay1 <= 8'b0;
else if(rd_en == 1'b1)
rd_en_delay1 <= 1'b1;
else
rd_en_delay1<= 1'b0;
end
//rd_en_delay2:读使能再延后一拍
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
rd_en_delay2 <= 8'b0;
else if(rd_en_delay1 == 1'b1)
rd_en_delay2 <= 1'b1;
else
rd_en_delay2 <= 1'b0;
end
//data_out1_delay:fifo1数据输出延后一拍 a1
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
data_out1_delay <= 8'b0;
else if(rd_en_delay1 == 1'b1)
data_out1_delay <= data_out1;
end
//data_out2_delay:fifo2数据输出延后一拍 b1
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
data_out2_delay <= 8'b0;
else if(rd_en_delay1 == 1'b1)
data_out2_delay <= data_out2;
end
//pi_data_delay:pi_data数据输出延后一拍 c1
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
pi_data_delay <= 8'b0;
else if(rd_en_delay1 == 1'b1)
pi_data_delay <= pi_data;
end
//gx_gy_flag:gx_gy计算标志位
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gx_gy_flag <= 1'b0;
else if(rd_en_delay2 == 1'b1&& ((cnt_rd >= 8'd3)|| (cnt_rd == 8'd0)))//第三行开始计算gx,gy
gx_gy_flag <= 1'b1;
else
gx_gy_flag <= 1'b0;
end
//gxy_flag:gxy计算标志位
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gxy_flag <= 1'b0;
else if(gx_gy_flag == 1'b1)
gxy_flag <= 1'b1;
else
gxy_flag <= 1'b0;
end
//gxy比较标志位 gxy_compare_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gxy_compare_flag <= 1'b0;
else if(gxy_flag == 1'b1)
gxy_compare_flag <= 1'b1;
else
gxy_compare_flag <= 1'b0;
end
//a1、a2、a3等赋值
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)begin
a1 <= 8'b0;
a2 <= 8'b0;
a3 <= 8'b0;
b1 <= 8'b0;
b2 <= 8'b0;
b3 <= 8'b0;
c1 <= 8'b0;
c2 <= 8'b0;
c3 <= 8'b0;
end
else if(rd_en_delay2 == 1'b1)begin
a1 <= data_out1_delay;
a2 <= a1;
a3 <= a2;
b1 <= data_out2_delay;
b2 <= b1;
b3 <= b2;
c1 <= pi_data_delay;
c2 <= c1;
c3 <= c2;
end
else begin
a1 <= a1;
a2 <= a2;
a3 <= a3;
b1 <= b1;
b2 <= b2;
b3 <= b3;
c1 <= c1;
c2 <= c2;
c3 <= c3;
end
end
//gx计算
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gx <= 8'b0;
else if(gx_gy_flag == 1'b1)
gx <= a3 - a1 +((b3 - b1)<<1) + c3 - c1;
else
gx <= gx;
end
//gy计算
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gy <= 8'b0;
else if(gx_gy_flag == 1'b1)
gy <= a1 - c1 +((a2 - c2)<<1) + a3 - c3;
else
gy <= gy;
end
//gxy计算
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
gxy <= 8'b0;
else if((gx[8] == 1'b1) && (gy[8] == 1'b1) && (gxy_flag == 1'b1))
gxy <= (~gx[7:0] + 1'b1) + (~gy[7:0] + 1'b1);
else if((gx[8] == 1'b1) && (gy[8] == 1'b0) && (gxy_flag == 1'b1))
gxy <= (~gx[7:0] + 1'b1) + (gy[7:0]);
else if((gx[8] == 1'b0) && (gy[8] == 1'b1) && (gxy_flag == 1'b1))
gxy <= (gx[7:0]) + (~gy[7:0] + 1'b1);
else if((gx[8] == 1'b0) && (gy[8] == 1'b0) && (gxy_flag == 1'b1))
gxy <= (gx[7:0]) + (gy[7:0]);
else
gxy <= gxy;
end
//po_data:gxy与阈值比较
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
po_data <= 1'b0;
else if((gxy >= THRESHOLD) && (gxy_compare_flag == 1'b1))
po_data <= BLACK;
else if(gxy_compare_flag == 1'b1)
po_data <= WHITE;
end
//po_flag:输出标志信号,po_data同步输出
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
po_flag <= 1'b0;
else if(gxy_compare_flag == 1'b1)
po_flag <= 1'b1;
else
po_flag <= 1'b0;
end
//------------- fifo_data_inst1 --------------
fifo1 fifo_data_inst1
(
.clk (sys_clk ), //input clk
.din (data_in1 ), //input [7:0] din
.wr_en (wr_en1 ), //input wr_en
.rd_en (rd_en ), //input rd_en
.full ( ), // output full
.empty ( ), // output empty
.dout (data_out1 ) //output [7:0] dout
);
//------------- fifo_data_inst2 --------------
fifo2 fifo_data_inst2
(
.clk (sys_clk ), //input clk
.din (data_in2 ), //input [7:0] din
.wr_en (wr_en2 ), //input wr_en
.rd_en (rd_en ), //input rd_en
.full ( ), // output full
.empty ( ), // output empty
.dout (data_out2 ) //output [7:0] dout
);
endmodule
这段代码在FIFO三项求和代码的基础上增加了阈值计算与比较代码。在代码最开始,我们定义了P_LENGTH
P_WIDTH
这两个参数作为输入图片的长度与宽度。sobel算法是计算三行三列的数据,因此,我们定义了一个行计数器与列计数器,计算输入数据的行数与列数。由FIFO三项求和的原理我们可以知道,第一行数据输入FIFO1中,第二行数据输入FIFO2中,第三行数据由串口输入,直接与第一行、第二行中的数据计算,结果直接输出,计算过程中,已经参与过计算的第三行数据输入FIFO2中,已经参与过计算的第二行数据输入FIFO1中,原本在FIFO1中的第一行数据被直接舍弃。(FIFO先入先出)。这就是FIFO三项计算的基本原理。
详细讲解:
FIFO1:开始时,第一行数据直接输入FIFO1中,以(cnt_col == 7'd0)
作为标志信号使能FIFO1的写使能信号,即输入的数据开始输入第一行数据,(pi_flag == 1'b1)
为串口输入的标志信号,默认加上。当三行数据开始计算后,将计算过的第二行数据传入FIFO1中,以dout_flag
作为标志信号使能FIFO1的写使能信号。
FIFO2: FIFO2的流程比较简单,当(cnt_col >= 7'd1)
且(cnt_col <= P_WIDTH - 1'd1 - 1'b1)
时,即输入的数据开始输入第二行数据,使能使能FIFO2的写使能信号,之所以(cnt_col <= P_WIDTH - 1'd1 - 1'b1)
是因为最后一行不参与计算。
当前两行数据都已经缓存到对应的FIFO中之后,就可以开始FIFO三项计算,首先将FIFO中的数据读取出来,rd_en
:fifo1和fifo2的共用读使能信号,当(cnt_col >= 7'd2)&&(cnt_col <= P_WIDTH - 1'd1))
即数据存储至第三行以后,就使能rd_en
开始数据读取并且计算。当计算开始之后,将计算过的第二行数据存至FIFO1中,则以(wr_en2 == 1'b1) && (rd_en == 1'b1)
为约束信号dout_flag
,即FIFO2开始写入数据,且FIFO1、2 已经开始读取数据开始计算,此时我们就可以使能wr_en1
将第二行的数据存至FIFO1中此时各个FIFO中读取的为最开始输入的数据即第一行第一个数据与第二行第一个数据。
根据算法,需要三行三列的数据,但是每次只能读取一列的数据,因为我们将读取到的数据打一拍,缓存起来。给一段波形图,大家自己理解。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/01/23 11:13:22
// Design Name:
// Module Name: lcd_display
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module lcd_display(
input wire [7:0] pi_data,
input wire pi_flag,
input wire sys_clk,
input wire lcd_pclk, //时钟
input wire sys_rst_n, //复位,低电平有效
input wire [10:0] pixel_xpos, //当前像素点横坐标
input wire [10:0] pixel_ypos, //当前像素点纵坐标
input wire [10:0] h_disp, //LCD 屏水平分辨率
input wire [10:0] v_disp, //LCD 屏垂直分辨率
output wire [23:0] pixel_data //像素数据
);
wire rd_en;
wire ena;
wire enb;
wire [23:0] pic_data;
reg [23:0] rgb_data;
reg [23:0] pix_data;
reg [17:0] wr_addr ; //ram写地址
reg [17:0] rd_addr ; //ram读地址
reg pic_valid;
reg pi_flag_delay;
parameter H_PIC = 10'd98 , //sobel算法处理后的图片长度
W_PIC = 10'd73 , //sobel算法处理后的图片宽度
PIC_SIZE = 18'd7154 , //sobel算法处理后的图片像素个数
baby_blue = 24'hADD8E6 ; //浅蓝色
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
assign ena = sys_rst_n;
assign enb = sys_rst_n;
//将rgb332转换成rgb888
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
rgb_data <= 24'hFFFFFF;
else if((pi_data == 8'b0000_0000)&& (pi_flag == 1'b1))
rgb_data <= 24'h000000;
else if(pi_flag == 1'b1)
rgb_data <= 24'hFFFFFF;
end
//pi_flag打一拍。对齐时序
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
pi_flag_delay <= 1'b0;
else if(pi_flag == 1'b1)
pi_flag_delay <= 1'b1;
else
pi_flag_delay <= 1'b0;
end
//wr_addr:ram写地址
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
wr_addr <= 14'd0;
else if((wr_addr == (PIC_SIZE - 1'b1)) && (pi_flag_delay == 1'b1))
wr_addr <= 14'd0;
else if(pi_flag == 1'b1)
wr_addr <= wr_addr + 1'b1;
//rd_addr:ram读地址
always@(posedge lcd_pclk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rd_addr <= 14'd0;
else if(rd_addr == (PIC_SIZE - 1'b1))
rd_addr <= 14'd0;
else if(rd_en == 1'b1)
rd_addr <= rd_addr + 1'b1;
else
rd_addr <= rd_addr;
//rd_en:ROM读使能
assign rd_en = (((pixel_xpos >= (((h_disp - H_PIC)/2) - 1'b1))
&& (pixel_xpos < (((h_disp - H_PIC)/2) + H_PIC - 1'b1)))
&&((pixel_ypos >= ((v_disp - W_PIC)/2))
&& ((pixel_ypos < (((v_disp - W_PIC)/2) + W_PIC)))));
//pic_valid:图片数据有效信号
always@(posedge lcd_pclk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pic_valid <= 1'b0;
else
pic_valid <= rd_en;
//pixel_data:输出VGA显示图像数据
assign pixel_data = (pic_valid == 1'b1) ? pic_data : pix_data;
always@(posedge lcd_pclk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pix_data <= 8'd0;
else
pix_data <= baby_blue;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- ram_pic_inst -------------
ram_pic ram_pic_inst
(
.clka (sys_clk ), //输入RAM写时钟,50MHz,1bit
.ena (ena),
.wea (pi_flag_delay ), //输入RAM写使能,1bit
.addra (wr_addr ), //输入RAM写地址,14bit
.dina (rgb_data ), //输入写入RAM的图片数据,8bit
.clkb (lcd_pclk ), //输入RAM读时钟,25MHz,1bit
.addrb (rd_addr ), //输入RAM读地址,14bit
.enb (enb),
.doutb (pic_data ) //输出读取RAM的图片数据,8bit
);
endmodule
RGB模块代码也只放其中的一个模块代码。很简单,大家自己理解
效果验证
工程源码
链接: https://pan.baidu.com/s/1UpxbxtBpMlphn2I-iXmaEA?pwd=dimx 提取码: dimx 复制这段内容后打开百度网盘手机App,操作更方便哦
写在最后
第一次认真的写,写的比较潦草,说一下初学的坑,一定要认真的仿真,看每一个波形,不能感觉好像对了,就急匆匆的烧录到板子里,最后大概率还是错的。😭
参考文献
[1] 正点原子. 达芬奇之FPGA开发指南
[2] 野火. FPGA+Verilog开发实战指南——基于Xilinx+Spartan6
[3] 韩彬.基于MATLAB与FPGA的图像处理教程