图像边缘检测--SOBEL
SOBEL图像边缘检测器的设计1)在嵌入式图形系统处理领域,图像处理的速度问题一直是一个很难突破的设计瓶颈。2)基于速度、系统集成和产品升级等角度考虑,使用高速可编程逻辑器件CPLD/FPGA自行开发有关处理芯片成了一种全新的解决方案。
1.SOBEL图像边缘检测器的设计
边缘可定义为图像中灰度发生急剧变化的区域边界,它是图像最基本的特征。边缘检测主要就是(图像的)灰度变化的度量、检测和定位,它是图像分析和模式识别的主要特征提取手段,它在计算机视觉、图像分析等应用中起着重要的作用,是图像分析与处理中研究的热点问题。在过去的20年里产生了许多边缘检测器,而Sobel算法只涉及加法操作,但却可以得到很好的划分效果,因而是图像处理系统中最常用的边缘检测算法。
Sobel算法包括带4个3×3掩码的输入图像数据,即Sobel算子,它设置权重来检测水平、垂直、左对角、右对角各个不同方向上密度幅度的不同。这个过程通常被称为过滤。我们来看像素窗口(3×3),如图2所示。水平、垂直、左对角、右对角各图像方向上密度幅度的变化可以用如下算子进行计算:
Q0 | Q3 | Q6 |
Q1 | [i,j] | Q7 |
Q2 | Q5 | Q8 |
H=(Q0+2Q3+Q6)-(Q2+2Q5+Q8);V=(Q0+2Q1+Q2)-(Q6+2Q7+Q8);
DR=(Q1+2Q0+Q3)-(Q5+2Q8+Q7);DL=(Q1+2Q2+Q5)-(Q3+2Q6+Q7);
H,V,DL,DR这四个参数用于计算梯度大小和方向。
对梯度大小的一个普遍估计值为:Magnitude=Max(H,V,DR,DL)。
我们通过对图像灰度作直方图分析后,便可以给出区分度阀值
Threshold,区分度阀值往往要借助一定的经验并需要反复调整。如果Magnitude大于Threshold,则该像素被声明为边界像素,否则为一般像素。
本课题就是要求使用LPM兆功能块设计和VHDL程序设计相结合的方式或全部采用VHDL程序设计方式,用FPGA/CPLD实现Sobel算法。
2 . 算法实现
Sobel的滤波函数为:
H=(Q0+2Q3+Q6)-(Q2+2Q5+Q8);
V=(Q0+2Q1+Q2)-(Q6+2Q7+Q8);
DR=(Q1+2Q0+Q3)-(Q5+2Q8+Q7);
DL=(Q1+2Q2+Q5)-(Q3+2Q6+Q7);
Magnitude=Max(H,V,DR,DL)
为了减少设计的复杂度,可将Sobel的滤波函数中的乘法运算可以改写成加法运算:
H=(Q0+Q3+Q3+Q6)-(Q2+Q5+Q5+Q8);
V=(Q0+Q1+Q1+Q2)-(Q6+Q7+Q7+Q8);
DR=(Q1+Q0+Q0+Q3)-(Q5+Q8+Q8+Q7);
DL=(Q1+Q2+Q2+Q5)-(Q3+Q6+Q6+Q7);
对于以上数据的处理,我们先估算一下分别使用单片机、DSP、CPLD/FPGA所需的时间。
(1)如果使用12M的单片机:完成一次Sobel滤波操作需要的时间至少为:(24×2+20+2×3+2)×1us=72us。对于一幅600×800像素的图像,总共的时间为:600×800×72us=32s。
(2)若使用40M六级流水的DSP,他们的处理时间大概为 32s/24=1.4s。
(3)如果使用CPLD/FPGA进行自行设计,通过采用并行流水线技术假设使用50M的系统时钟,处理完一个像素点的时间为 4×1/(50M)=80ns,处理完一帧图像的时间为 800×600×80ns=38.4ms,结果处理速度比DSP高了大约两个数量级。
从上可以看出,使用CPLD/FPGA进行自行设计有关图像处理模块,对整个系统速度的改善是很非常明显的。
3 . 总体设计方案
整个系统的实现可划分为四个大的模块,总体结构如图3所示,其中:
帧窗口接收模块(FIFO):负责接收DSP传送过来的一个帧窗口的数据,其本质为一个双端口先入先出栈FIFO,其数据宽度为8,深度等于一个帧窗口内的像素点个数(600×3=1800)。
串入并出模块(SIPO):负责把FIFO内的数据转换成为像素处理窗口的列像素向量,便于像素处理窗口的数据刷新处理。
像素窗口刷新模块(REFRESH):实现对需要处理的像素数据的刷新。
数据处理模块(PROCESSOR):它是本图形边缘处理器的核心部分,主要是实现Sobel算法,其性能的好坏对整个设计的成败有着关键的作用。本模块拟采用全硬件并行算法实现,因只有五级串行结构,所以相当于在5个时钟周期内就能完成一个像素点的边界判别。
图3.图像边缘检测器总体结构图
3.1主要模块的设计思想
- 帧窗口接收模块FIFO
由于高速设备与慢速设备之间处理速度的差别,本系统数据传输选择了帧同步方式。存储器的类型拟选用FIFO,堆栈空时向主机发出准备好信号,主机检测到它的数据传输请求时,传送一帧数据,由于FIFO的大小与一帧图像的大小是一致的,所以接收完毕后,堆栈满,Sobel处理器启动边缘检测进程,处理完一帧数据后,堆栈重新变为空,为下一帧数据处理作准备。
2.串入并出模块SIPO
串入并出模块的主要功能是负责一列像素的刷新,也就是把主处理器传送过来的像素值转换成3×3像素窗口的一列。该模块的实现主要是通过六个D触发器和一个三进制的计数器组成,当计数器产生进位溢出时,串行输入的三个像素点并行输出。
3.像素窗口刷新模块REFRESH
像素刷新窗口的主要功能是接收串入并出模块的3个并行像素,把窗口中原有的第二列像素推入第三列,第一列推入第二列,新到的并行像素填入第一列。其本质为一个移位寄存器。
4.滤波模块FILTER
对于SOBEL算法的各个滤波器,经变换后可得到:
H=(Q0+Q3+Q3+Q6)-(Q2+Q5+Q5+Q8);
V=(Q0+Q1+Q1+Q2)-(Q6+Q7+Q7+Q8);
DR=(Q1+Q0+Q0+Q3)-(Q5+Q8+Q8+Q7);
DL=(Q1+Q2+Q2+Q5)-(Q3+Q6+Q6+Q7);
5.数据处理模块PROCESSOR
数据处理模块PROCESSOR的主要功能是求出四个方向的图像梯度数据绝对值的最大值,同时判别最大值出现的方向。
3.2系统源程序
--SOBEL.VHD 顶层
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY SOBEL IS
PORT(CLK1,CLK2:IN STD_LOGIC;
LIBRARY IEEE;
K1:IN STD_LOGIC;
K2:IN STD_LOGIC;
K3:IN STD_LOGIC;
K4:IN STD_LOGIC;
COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY SOBEL;
ARCHITECTURE ART OF SOBEL IS
COMPONENT CNT13 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC_VECTOR(12 DOWNTO 0));
END COMPONENT CNT13;
COMPONENT SOBELROM IS
PORT(CLOCK:IN STD_LOGIC;
ADDRESS:IN STD_LOGIC_VECTOR(12 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT SOBELROM;
COMPONENT SIPO IS
PORT(CLK:IN STD_LOGIC;
PIXEL:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
QA:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
QB,QC:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT SIPO;
COMPONENT REFRESH IS
PORT(CLK:IN STD_LOGIC;
DATA0,DATA1,DATA2:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q0,Q1,Q2,Q3,Q5,Q6,Q7,Q8:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT REFRESH;
COMPONENT PROCESSOR IS
PORT( CLK:IN STD_LOGIC;
Q0,Q1,Q2,Q3,Q5,Q6,Q7,Q8:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
O0,O1,O2,O3,O5,O6,O7,O8:BUFFER STD_LOGIC_VECTOR(7 DOWNTO 0);
MAGOUT:OUT STD_LOGIC;
MAX,H,V,DL,DR:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT PROCESSOR;
COMPONENT CHOOSE IS
PORT(K1:IN STD_LOGIC;
K2:IN STD_LOGIC;
K3:IN STD_LOGIC;
K4:IN STD_LOGIC;
A1,A2,A3,A4,A5:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
DOUT1:OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
DOUT2:OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
I0,I1,I2,I3,I5,I6,I7,I8:IN STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT CHOOSE;
COMPONENT CTRLS IS
PORT(CLK: IN STD_LOGIC;
SEL: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COMPONENT CTRLS;
COMPONENT DISPLAY IS
PORT(SEL: IN STD_LOGIC_VECTOR(2 DOWNTO 0);
MAGIN:IN STD_LOGIC;
K1:IN STD_LOGIC;
K2:IN STD_LOGIC;
K3:IN STD_LOGIC;
K4:IN STD_LOGIC;
DATA1: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
DATA2: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
COM: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT DISPLAY;
SIGNAL R1:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL A1,A2,A3:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL B0,B1,B2,B3,B5,B6,B7,B8:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL C0,C1,C2,C3,C5,C6,C7,C8:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL P0,P1,P2,P3,P4:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL X1,X2:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL S0:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL S1:STD_LOGIC_VECTOR(12 DOWNTO 0);
SIGNAL S2:STD_LOGIC;
BEGIN
U0:CNT13 PORT MAP(CLK=>CLK1,CO=>S1);
U1:SOBELROM PORT MAP(CLOCK=>CLK1,ADDRESS=>S1,Q=>R1);
U2:SIPO PORT MAP(CLK=>CLK1,PIXEL=>R1,QA=>A1,QB=>A2,QC=>A3);
U3:REFRESH PORT MAP(CLK1,A1,A2,A3,B0,B1,B2,B3,B5,B6,B7,B8);
U4:PROCESSOR PORT MAP(CLK1,B0,B1,B2,B3,B5,B6,B7,B8,C0,C1,C2,C3,C5,C6,C7,C8,S2,P0,P1,P2,P3,P4);
U5:CHOOSE PORT MAP(K1=>K1,K2=>K2,K3=>K3,K4=>K4,A1=>P1,A2=>P2,A3=>P3,A4=>P4,A5=>P0,DOUT1=>X1,DOUT2=>X2,I0=>C0,I1=>C1,I2=>C2,I3=>C3,I5=>C5,I6=>C6,I7=>C7,I8=>C8);
U6:CTRLS PORT MAP(CLK=>CLK2,SEL=>S0);
U7:DISPLAY PORT MAP(SEL=>S0,MAGIN=>S2,K1=>K1,K2=>K2,K3=>K3,K4=>K4,DATA1=>X1,DATA2=>X2,COM=>COM,SEG=>SEG);
END ARCHITECTURE ART;
--SIPO.VHD 串入并出
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY SIPO IS
PORT( CLK:IN STD_LOGIC;
PIXEL:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
QA:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
QB,QC:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY SIPO;
ARCHITECTURE ART OF SIPO IS
COMPONENT REG IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT REG;
COMPONENT CNT3 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC);
END COMPONENT CNT3;
SIGNAL S0:STD_LOGIC;
SIGNAL S1,S2,S3:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
U0:REG PORT MAP(CLK=>CLK,D=>PIXEL,Q=>S1);
U1:REG PORT MAP(CLK=>CLK,D=>S1,Q=>S2);
U2:REG PORT MAP(CLK=>CLK,D=>S2,Q=>S3);
U3:CNT3 PORT MAP(CLK=>CLK,CO=>S0);
U4:REG PORT MAP(CLK=>S0,D=>S1,Q=>QA);
U5:REG PORT MAP(CLK=>S0,D=>S2,Q=>QB);
U6:REG PORT MAP(CLK=>S0,D=>S3,Q=>QC);
END ARCHITECTURE ART;
--REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY REG IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY REG;
ARCHITECTURE ART OF REG IS
BEGIN
PROCESS(CLK,D) IS
BEGIN
IF(CLK'EVENT AND CLK='1') THEN
Q<=D;
END IF;
END PROCESS;
END ARCHITECTURE ART;
--CNT3.VHD 计数器模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT3 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC);
END ENTITY CNT3;
ARCHITECTURE ART OF CNT3 IS
SIGNAL CQ:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
PROCESS(CLK) IS
BEGIN
IF(CLK'EVENT AND CLK='1') THEN
IF CQ="10" THEN
CQ<="00";CO<='1';
ELSE
CQ<=CQ+'1';
CO<='0';
END IF;
END IF;
END PROCESS;
END ARCHITECTURE ART;
--REFRESH.VHD 像素刷新
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY REFRESH IS
PORT(CLK:IN STD_LOGIC;
DATA0,DATA1,DATA2:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q0,Q1,Q2,Q3,Q5,Q6,Q7,Q8:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY REFRESH;
ARCHITECTURE ART OF REFRESH IS
COMPONENT REG IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT REG;
SIGNAL A1,A2:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL B1,B2:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL C1,C2:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
U1:REG PORT MAP(CLK=>CLK,D=>DATA0,Q=>A1);
U2:REG PORT MAP(CLK=>CLK,D=>A1,Q=>A2);
U3:REG PORT MAP(CLK=>CLK,D=>A2,Q=>Q6);
U4:REG PORT MAP(CLK=>CLK,D=>DATA1,Q=>B1);
U5:REG PORT MAP(CLK=>CLK,D=>B1,Q=>B2);
U6:REG PORT MAP(CLK=>CLK,D=>B2,Q=>Q7);
U7:REG PORT MAP(CLK=>CLK,D=>DATA2,Q=>C1);
U8:REG PORT MAP(CLK=>CLK,D=>C1,Q=>C2);
U9:REG PORT MAP(CLK=>CLK,D=>C2,Q=>Q8);
Q3<=A2;Q0<=A1;
Q1<=B1;Q2<=C1;
Q5<=C2;
END ARCHITECTURE ART;
--ADD.VHD(加法器)
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ADD IS
PORT (A,B:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
SUM:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY ADD;
ARCHITECTURE ART OF ADD IS
SIGNAL A1:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL B1:STD_LOGIC_VECTOR(10 DOWNTO 0);
BEGIN
A1<="000"&A;
B1<="000"&B;
SUM<=A1+B1;
END ARCHITECTURE ART;
--REG2.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY REG2 IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY REG2;
ARCHITECTURE ART OF REG2 IS
BEGIN
PROCESS(CLK,D) IS
BEGIN
IF(CLK'EVENT AND CLK='1') THEN
Q<=D;
END IF;
END PROCESS;
END ARCHITECTURE ART;
--ADD2.VHD(加法器)
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ADD2 IS
PORT (A,B:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
SUM:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY ADD2;
ARCHITECTURE ART OF ADD2 IS
BEGIN
SUM<=A+B;
END ARCHITECTURE ART;
--FILTER.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY FILTER IS
PORT(CLK:IN STD_LOGIC;
QA,QB,QC,QD,QE,QF:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY FILTER;
ARCHITECTURE ART OF FILTER IS
COMPONENT ADD IS
PORT (A,B:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
SUM:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT ADD;
COMPONENT ADD2 IS
PORT (A,B:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
SUM:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT ADD2;
COMPONENT REG2 IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT REG2;
SIGNAL D0,D1,D2,D3:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL A0,A1,A2,A3:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL B1,B2,C1,C2:STD_LOGIC_VECTOR(10 DOWNTO 0);
BEGIN
U1:ADD PORT MAP(A=>QA,B=>QB,SUM=>D0);
U2:ADD PORT MAP(A=>QB,B=>QC,SUM=>D1);
U3:ADD PORT MAP(A=>QD,B=>QE,SUM=>D2);
U4:ADD PORT MAP(A=>QE,B=>QF,SUM=>D3);
U5:REG2 PORT MAP(CLK=>CLK,D=>D0,Q=>A0);
U6:REG2 PORT MAP(CLK=>CLK,D=>D1,Q=>A1);
U7:REG2 PORT MAP(CLK=>CLK,D=>D2,Q=>A2);
U8:REG2 PORT MAP(CLK=>CLK,D=>D3,Q=>A3);
U9:ADD2 PORT MAP(A=>D0,B=>D1,SUM=>B1);
U10:ADD2 PORT MAP(A=>D2,B=>D3,SUM=>B2);
U11:REG2 PORT MAP(CLK=>CLK,D=>B1,Q=>C1);
U12:REG2 PORT MAP(CLK=>CLK,D=>B2,Q=>C2);
DOUT<=C1-C2;
END ARCHITECTURE ART;
--ZFIFO.VHD 帧窗口接收模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ZFIFO IS
PORT(CLK:IN STD_LOGIC;
WR:IN STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
READY:OUT STD_LOGIC;
PROCESS_EN:OUT STD_LOGIC);
END ENTITY ZFIFO;
ARCHITECTURE ART OF ZFIFO IS
COMPONENT SOBELROM IS
PORT(ADDRESS:IN STD_LOGIC_VECTOR(12 DOWNTO 0);
CLOCK:IN STD_LOGIC:= '1';
Q:OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END COMPONENT SOBELROM;
COMPONENT CNT13 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC_VECTOR(12 DOWNTO 0));
END COMPONENT CNT13;
COMPONENT D IS
PORT(CLK:IN STD_LOGIC;
ENA:IN STD_LOGIC;
CLR:IN STD_LOGIC;
Q:OUT STD_LOGIC);
END COMPONENT D;
COMPONENT YUMEN IS
PORT(A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC);
END COMPONENT YUMEN;
COMPONENT FEIMEN IS
PORT(A:IN STD_LOGIC;
Y:OUT STD_LOGIC);
END COMPONENT FEIMEN;
COMPONENT FIFO IS
PORT(CLOCK:IN STD_LOGIC;
DATA:IN STD_LOGIC_VECTOR (7 DOWNTO 0);
RDREQ:IN STD_LOGIC;
WRREQ:IN STD_LOGIC;
EMPTY:OUT STD_LOGIC;
FULL:OUT STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END COMPONENT FIFO;
SIGNAL A1,A2,A3:STD_LOGIC;
SIGNAL B1:STD_LOGIC_VECTOR(12 DOWNTO 0);
SIGNAL B2,B3:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL C1,D1:STD_LOGIC;
BEGIN
U1:CNT13 PORT MAP(CLK=>CLK,CO=>B1);
U2:SOBELROM PORT MAP(ADDRESS=>B1,CLOCK=>CLK,Q=>B2);
U3:D PORT MAP(CLK=>CLK,ENA=>A1,CLR=>A2,Q=>A3);
U4:FIFO PORT MAP(CLOCK=>CLK,DATA=>B2,RDREQ=>A3,WRREQ=>D1,EMPTY=>A2,FULL=>A1,Q=>B3);
U5:FEIMEN PORT MAP(A=>A3,Y=>C1);
U6:YUMEN PORT MAP(A=>C1,B=>WR,Y=>D1);
Q<=B3;
READY<=A3;
PROCESS_EN<=C1;
END ARCHITECTURE ART;
--CNT2.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT2 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
END ENTITY CNT2;
ARCHITECTURE ART OF CNT2 IS
SIGNAL CNT:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
PROCESS(CLK)IS
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
IF CNT="11" THEN
CNT<="00";
ELSE
CNT<=CNT+'1';
END IF;
END IF;
END PROCESS;
CO<=CNT;
END ARCHITECTURE ART;
--D.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY D IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC;
ENA:IN STD_LOGIC;
CLR:IN STD_LOGIC;
Q:OUT STD_LOGIC);
END ENTITY D;
ARCHITECTURE ART OF D IS
BEGIN
PROCESS(CLK,CLR,ENA)IS
BEGIN
IF(CLR='1')THEN
Q<='0';
ELSIF(ENA='1')THEN
IF(CLK'EVENT AND CLK='1')THEN
Q<='1';
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
--YUMEN.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY YUMEN IS
PORT(A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC);
END ENTITY YUMEN;
ARCHITECTURE ART OF YUMEN IS
BEGIN
Y<=A AND B;
END ARCHITECTURE ART;
--FEIMEN.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY FEIMEN IS
PORT(A:IN STD_LOGIC;
Y:OUT STD_LOGIC);
END ENTITY FEIMEN;
ARCHITECTURE ART OF FEIMEN IS
BEGIN
Y<=NOT A;
END ARCHITECTURE ART;
--CNT13.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNT13 IS
PORT(CLK:IN STD_LOGIC;
CO:OUT STD_LOGIC_VECTOR(12 DOWNTO 0));
END ENTITY CNT13;
ARCHITECTURE ART OF CNT13 IS
SIGNAL CNT:STD_LOGIC_VECTOR(12 DOWNTO 0);
BEGIN
PROCESS(CLK)IS
BEGIN
IF(CLK'EVENT AND CLK='1') THEN
IF CNT="1111111111111" THEN
CNT<="0000000000000";
ELSE
CNT<=CNT+'1';
END IF;
END IF;
END PROCESS;
CO<=CNT;
END ARCHITECTURE ART;
--COMPARE.VHD 比较模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COMPARE IS
PORT (DATA1,DATA2:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
MAX:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY COMPARE;
ARCHITECTURE ART OF COMPARE IS
BEGIN
PROCESS(DATA1,DATA2) IS
BEGIN
IF(DATA1(10 DOWNTO 0)>DATA2(10 DOWNTO 0))THEN
MAX<=DATA1;
ELSE
MAX<=DATA2;
END IF;
END PROCESS;
END ARCHITECTURE ART;
--RELUST.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY RELUST IS
PORT(CLK:IN STD_LOGIC;
MAX:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
MAGOUT:OUT STD_LOGIC);
END ENTITY RELUST;
ARCHITECTURE ART OF RELUST IS
BEGIN
PROCESS(CLK) IS
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
IF(MAX(10 DOWNTO 0)>"00010000000") THEN
MAGOUT<='1';
ELSE MAGOUT<='0';
END IF;
END IF;
END PROCESS;
END ARCHITECTURE ART;
--PROCESSOR.VHD 进程处理模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY PROCESSOR IS
PORT( CLK:IN STD_LOGIC;
Q0,Q1,Q2,Q3,Q5,Q6,Q7,Q8:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
O0,O1,O2,O3,O5,O6,O7,O8:BUFFER STD_LOGIC_VECTOR(7 DOWNTO 0);
MAGOUT:OUT STD_LOGIC;
MAX,H,V,DL,DR:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY PROCESSOR;
ARCHITECTURE ART OF PROCESSOR IS
COMPONENT FILTER IS
PORT(CLK:IN STD_LOGIC;
QA,QB,QC,QD,QE,QF:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT FILTER;
COMPONENT REG2 IS
PORT(CLK:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT REG2;
COMPONENT COMPARE IS
PORT (DATA1,DATA2:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
MAX:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END COMPONENT COMPARE;
COMPONENT RELUST IS
PORT(CLK:IN STD_LOGIC;
MAX:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
MAGOUT:OUT STD_LOGIC);
END COMPONENT RELUST;
SIGNAL A1,A2,A3,A4:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL B1,B2,B3,B4:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL C1,C2:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL D1,D2:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL F1:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL M1:STD_LOGIC_VECTOR(10 DOWNTO 0);
BEGIN
U0:FILTER PORT MAP(CLK,Q0,Q3,Q6,Q2,Q5,Q8,A1);
U1:FILTER PORT MAP(CLK,Q0,Q1,Q2,Q6,Q7,Q8,A2);
U2:FILTER PORT MAP(CLK,Q1,Q0,Q3,Q5,Q8,Q7,A3);
U3:FILTER PORT MAP(CLK,Q1,Q2,Q5,Q3,Q6,Q7,A4);
U4:REG2 PORT MAP(CLK,A1,B1);
U5:REG2 PORT MAP(CLK,A2,B2);
U6:REG2 PORT MAP(CLK,A3,B3);
U7:REG2 PORT MAP(CLK,A4,B4);
U8:COMPARE PORT MAP(B1,B2,C1);
U9:COMPARE PORT MAP(B3,B4,C2);
U10:REG2 PORT MAP(CLK,C1,D1);
U11:REG2 PORT MAP(CLK,C2,D2);
U12:COMPARE PORT MAP(D1,D2,F1);
U13:REG2 PORT MAP(CLK,F1,M1);
U14:RELUST PORT MAP(CLK=>CLK,MAX=>M1,MAGOUT=>MAGOUT);
MAX<=M1;H<=A1;V<=A2;DR<=A3;DL<=A4;
O0<=Q0;O1<=Q1;O2<=Q2;O3<=Q3;O5<=Q5;O6<=Q6;O7<=Q7;O8<=Q8;
END ARCHITECTURE ART;
--SOBELROM.VHD 存储模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
LIBRARY ALTERA_MF;
USE ALTERA_MF.ALTERA_MF_COMPONENTS.ALL;
ENTITY SOBELROM IS
PORT
(
ADDRESS : IN STD_LOGIC_VECTOR (12 DOWNTO 0);
CLOCK : IN STD_LOGIC := '1';
Q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END SOBELROM;
ARCHITECTURE SYN OF SOBELROM IS
SIGNAL SUB_WIRE0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
Q <= SUB_WIRE0(7 DOWNTO 0);
ALTSYNCRAM_COMPONENT : ALTSYNCRAM
GENERIC MAP (
ADDRESS_ACLR_A => "NONE",
CLOCK_ENABLE_INPUT_A => "BYPASS",
CLOCK_ENABLE_OUTPUT_A => "BYPASS",
INIT_FILE => "GRAY_IMAGE.MIF",
INTENDED_DEVICE_FAMILY => "CYCLONE III",
LPM_HINT => "ENABLE_RUNTIME_MOD=NO",
LPM_TYPE => "ALTSYNCRAM",
NUMWORDS_A => 6400,
OPERATION_MODE => "ROM",
OUTDATA_ACLR_A => "NONE",
OUTDATA_REG_A => "UNREGISTERED",
WIDTHAD_A => 13,
WIDTH_A => 8,
WIDTH_BYTEENA_A => 1
)
PORT MAP (
ADDRESS_A => ADDRESS,
CLOCK0 => CLOCK,
Q_A => SUB_WIRE0
);
END SYN;
--CHOOSE.VHD 选择模块
--在kk等于0100时DOUT1输出H,DOUT2输出V;在kk等于1000时DOUT1输出DL,DOUT2输出DR;当kk等于1100时,DOUT1输出四者中最大值MAX,DOUT2输出空。KK=0000时,DOUT1为I0,DOUT2为I1;...
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CHOOSE IS
PORT(K1:IN STD_LOGIC;
K2:IN STD_LOGIC;
K3:IN STD_LOGIC;
K4:IN STD_LOGIC;
A1,A2,A3,A4,A5:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
I0,I1,I2,I3,I5,I6,I7,I8:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT1:OUT STD_LOGIC_VECTOR(10 DOWNTO 0);
DOUT2:OUT STD_LOGIC_VECTOR(10 DOWNTO 0));
END ENTITY CHOOSE;
ARCHITECTURE ART OF CHOOSE IS
SIGNAL KK:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
KK<=K1&K2&K3&K4;
PROCESS(KK,A1,A2,A3,A4,A5) IS
BEGIN
CASE KK IS
WHEN "0100"=>DOUT1<=A1;DOUT2<=A2;
WHEN "1000"=>DOUT1<=A3;DOUT2<=A4;
WHEN "1100"=>DOUT1<=A5;DOUT2<="00000000000";
WHEN "0000"=>DOUT1<="000"&I0;DOUT2<="000"&I1;
WHEN "0001"=>DOUT1<="000"&I2;DOUT2<="000"&I3;
WHEN "0010"=>DOUT1<="000"&I5;DOUT2<="000"&I6;
WHEN "0011"=>DOUT1<="000"&I7;DOUT2<="000"&I8;
WHEN OTHERS=>NULL;
END CASE;
END PROCESS;
END ARCHITECTURE ART;
--CTRLS.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CTRLS IS
PORT(CLK: IN STD_LOGIC;
SEL: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END ENTITY CTRLS;
ARCHITECTURE ART OF CTRLS IS
SIGNAL CNT: STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
PROCESS(CLK) IS
BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF CNT="111" THEN
CNT<="000";
ELSE
CNT<=CNT+'1';
END IF ;
END IF;
END PROCESS;
SEL<=CNT;
END ARCHITECTURE ART;
--DISPLAY.VHD 动态显示模块
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DISPLAY IS
PORT(SEL:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
MAGIN:IN STD_LOGIC;
K1:IN STD_LOGIC;
K2:IN STD_LOGIC;
K3:IN STD_LOGIC;
K4:IN STD_LOGIC;
DATA1: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
DATA2: IN STD_LOGIC_VECTOR(10 DOWNTO 0);
COM: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY DISPLAY;
ARCHITECTURE ART OF DISPLAY IS
SIGNAL DATA:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL CONTROL:STD_LOGIC_VECTOR(6 DOWNTO 0);
BEGIN
CONTROL<=K1&K2&K3&K4&SEL;
PROCESS(SEL) IS
BEGIN
CASE SEL IS
WHEN "000" => COM<="11111110";
WHEN "001" => COM<="11111101";
WHEN "010" => COM<="11111011";
WHEN "011" => COM<="11110111";
WHEN "100" => COM<="11101111";
WHEN "101" => COM<="11011111";
WHEN "110" => COM<="10111111";
WHEN "111" => COM<="01111111";
WHEN OTHERS => COM<="11111111";
END CASE ;
END PROCESS;
PROCESS(SEL) IS
BEGIN
CASE CONTROL IS
WHEN "0100000" =>DATA<=DATA1(3 DOWNTO 0); --H
WHEN "0100001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "0100010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "0100011" =>DATA<=DATA2(3 DOWNTO 0); --V
WHEN "0100100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "0100101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "0100110" =>DATA<="000"&MAGIN; --边缘检测
WHEN "1000000" =>DATA<=DATA1(3 DOWNTO 0); --DL
WHEN "1000001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "1000010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "1000011" =>DATA<=DATA2(3 DOWNTO 0); --DR
WHEN "1000100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "1000101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "1000110" =>DATA<="000"&MAGIN; --边缘检测
WHEN "1100000" =>DATA<=DATA1(3 DOWNTO 0); --MAX
WHEN "1100001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "1100010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "1100110" =>DATA<="000"&MAGIN; --边缘检测
WHEN "0000000" =>DATA<=DATA1(3 DOWNTO 0); --Q0
WHEN "0000001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "0000010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "0000011" =>DATA<=DATA2(3 DOWNTO 0); --Q1
WHEN "0000100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "0000101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "0000110" =>DATA<="000"&MAGIN;
WHEN "0001000" =>DATA<=DATA1(3 DOWNTO 0); --Q2
WHEN "0001001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "0001010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "0001011" =>DATA<=DATA2(3 DOWNTO 0); --Q3
WHEN "0001100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "0001101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "0001110" =>DATA<="000"&MAGIN;
WHEN "0010000" =>DATA<=DATA1(3 DOWNTO 0); --Q5
WHEN "0010001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "0010010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "0010011" =>DATA<=DATA2(3 DOWNTO 0); --Q6
WHEN "0010100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "0010101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "0010110" =>DATA<="000"&MAGIN;
WHEN "0011000" =>DATA<=DATA1(3 DOWNTO 0); --Q7
WHEN "0011001" =>DATA<=DATA1(7 DOWNTO 4);
WHEN "0011010" =>DATA<="0"&DATA1(10 DOWNTO 8);
WHEN "0011011" =>DATA<=DATA2(3 DOWNTO 0); --Q8
WHEN "0011100" =>DATA<=DATA2(7 DOWNTO 4);
WHEN "0011101" =>DATA<="0"&DATA2(10 DOWNTO 8);
WHEN "0011110" =>DATA<="000"&MAGIN;
WHEN OTHERS=>DATA<="0000";
END CASE;
CASE DATA IS
WHEN "0000" => SEG<="00111111";--0
WHEN "0001" => SEG<="00000110";--1
WHEN "0010" => SEG<="01011011";--2
WHEN "0011" => SEG<="01001111";--3
WHEN "0100" => SEG<="01100110";--4
WHEN "0101" => SEG<="01101101";--5
WHEN "0110" => SEG<="01111101";--6
WHEN "0111" => SEG<="00000111";--7
WHEN "1000" => SEG<="01111111";--8
WHEN "1001" => SEG<="01101111";--9
WHEN "1010" => SEG<="01110111";--A
WHEN "1011" => SEG<="01111100";--b
WHEN "1100" => SEG<="00111001";--C
WHEN "1101" => SEG<="01011110";--d
WHEN "1110" => SEG<="01111001";--E
WHEN "1111" => SEG<="01110001";--F
END CASE ;
END PROCESS;
END ARCHITECTURE ART;
4 软硬件实验系统构建与测试结果
processor模块仿真
整体RTL视图
实物验证
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)