资讯详情

FPGA视频处理系统

视频图像处理作为一种重要的现代技术,已广泛应用于通信、航空航天、遥感遥测、生物医学、军事、信息安全等领域。视频图像处理,特别是高分辨率图像实时处理的实现技术,对相关领域的发展具有深远的意义。

随着科学技术的进步,对视频图像采集和处理的应用需求也在增加。传统的采集和处理主要依赖于传统的采集和处理PC机器等专用集成电路板卡由于功能单一、体积大、处理速度有限,逐渐无法满足实际要求。由于FPGA技术发展迅速,计算能力不断提高,计算速度越来越快,成本也在下降。目前FPGA从军事到民用,从航空航天到生产生活,技术已广泛应用于各个领域。FPGA。

因此,本设计的视频采集与处理系统采用双处理系统:专用芯片和可编程逻辑器件FPGA,完成图像采集和图像压缩。选择了适合当前行业实际需——DCT算法。FPGA上VHDL模块化和可重用的程序功能可以提高设计效率,从而获得可靠和优化的设计。

2.1 FPGA开发与应用

随着FPGA设计越来越复杂,最重要的硬件描述语言是VHDL和Verilog HDL。从EDA根据技术的发展趋势,直接采用C语言设计FPGA它将是一个发展方向,现在已经出现了FPGA在5~10年内,C语言很可能会逐渐成为继续VHDL和Verilog然后大规模设计FPGA的又一种手段。

通信是FPGA传统领域。随着微细化的进步,芯片面积缩小,价格迅速下降,市场发展加快。同时,由于FPGA灵活方便,不仅性能、速度、连接优势,又能缩短上市时间,因此应用领域不断扩大。现在,许多用户已经开始使用一些批量生产的消费电子产品FPGA,如DVD、TV、游戏设备、空调、PDA、数字视频移动网络、无线局域网等。

2.1.1 FPGA系统结构

FPGA也就是说,现场可编程门阵列的通用结构由逻辑功能块排列成阵列,这些逻辑功能块由可编程的互连资源连接,实现不同的设计。

FPGA静态存储器通常由三个可编程电路和一个用于存储编程数据SRAM组成。这三种可编程电路是:可编程逻辑块(CLB, Configurable Logic Block)、输入∕输出模块(IOB, I/O BLOCK)和互连资源(IR, Interconnect Resource)。可编程逻辑块CLB它是实现逻辑功能的基本单元,通常在整个芯片中定期排列阵列;可编程输入∕输出模块(IOB)主要完成芯片上的逻辑和外部包装脚的接口,通常排列在芯片周围;可编程连接资源包括各种长度的连接段和一些可编程连接开关CLB之间活CLB、IOB之间,以及IOB连接起来,形成特定功能的电路。

CLB是FPGA主要部件。它主要由逻辑函数发生器触发器、数据选择器等电路组成。CLB三个逻辑函数发生器分别是G、F和H,相应的输出是G`、F`和H`。G有四个输入变量,和;F还有四个输入变量,和。这两个逻辑函数发生器完全独立,可以实现四个输入变量的任意组合逻辑函数。逻辑函数发生器H有三个输入信号:前两个函数发生器的输出G`和F`,另一个输入信号来自信号变换电路的输出。该函数发生器可以实现三个输入变量的各种组合函数。这三个函数发生器可以实现多达9个变量的逻辑函数。

CLB有许多不同规格的数据选择器(4选1,2选1等)CLB内部数据选择器编程,逻辑函数发生器G、F与H的输出可以连接到CLB内部触发器或直接连接到CLB输出端X或Y,并用于选择触发器激励输入信号、时钟有效边缘、时钟使能信号和输出信号。编程信息提供这些数据选择器的地址控制信号,以实现所需的电路结构。

CLB逻辑函数发生器F和G都是搜索表结构,工作原理类似ROM。F和G的输入等效于ROM搜索地址码ROM组合逻辑函数可以输出中的地址表。另一方面,逻辑函数发生器F和G也可作为器件内的高速RAM由信号变换电路控制的小型可读写存储器。

IOB设备引脚与内部逻辑阵列之间的连接。主要由输入触发器、输入缓冲器和输出触发∕由定器和输出缓冲器组成。

每个IOB可配置为输入、输出或双向引脚I/O功能。当IOB当控制引脚被定义为输入时,通过引脚的输入信号首先输入输入缓冲器。缓冲器的输出分为两种方式:一种方式可以直接送到MUX,另一条路径延迟几次ns(或不延迟)送到输入通路D触发器,然后送到数据选择器。通过编程向数据选择器发送不同的控制信息CLB阵列的I1和I来自输入缓冲器或触发器。

IOB两个输出端MOS管道,它们的网格极其可编程,使其极其可编程MOS管道分别通过上拉电阻或下拉电阻连接或截止VCC、地线或不连接,以提高输出波形和负载能力。

可编程互联网资源IR可以将FPGA内部的CLB和CLB之间、CLB和IOB它们相互连接,形成具有各种复杂功能的系统。IR通过自动布线实现各种电路连接,主要由多个金属线段组成。

根据相对长度,长度分为单长线、双长线和长线。

单长度线连接结构,CLB输入和输出分别连接到相邻的单长度线,然后连接到开关矩阵。开关矩阵可以通过编程控制CLB与其他CLB或IOB连在一起。

双长度线连接结构,双长度线金属线段的长度是单位长度线金属线段的两倍,通过两个CLB之后,这些金属线段才与可编程的开关矩阵相连接。因此,通过双长度线可使两个相隔(非相邻)的CLB连接起来。

长线连接结构,由长线网络组成的金属网络,充满了阵列的所有长度和宽度,每个长线中间有一个可编程的分离开关,使长线分为两个独立的连接连接,每个连接只有阵列宽度或高度的一半。CLB输入可由相邻的任何长线驱动,输出可由三态缓冲器驱动。

单长度线盒的双长度线提供了相邻的CLB快速连接和复杂连接的灵活性,但传输信号增加了一个延迟,而不是通过可编程开关矩阵。FPGA内部延迟与设备结构和逻辑布线有关,其信号传输延迟不确定。长期不通过可编程开关矩阵,信号延迟时间小,长期用于传输高风扇和关键信号。

2.1.2 FPGA的结构特点

FPGA芯片是小批量系统提高系统集成度和可靠性的最佳选择之一,其主要特点是:

(1) 采用FPGA设计ASIC,设计周期短,开发成本低,风险低,无需投影生产;

(2) FPGA可以做其他全定制或半定制ASIC电路中试样片;

(3)FPGA触发器内部丰富I∕O引脚;

(4)FPGA采用高速CHMOS工艺,低功耗,可与CMOS、TTL电平兼容。

下面以Altera公司的FLEX∕ACEX系列FPGA与Xilinx公司的FPGA比较结构有以下区别:

(1)结构不同。

Altera FPGA: 嵌入式阵列块EAB、逻辑阵列块LAB、FastTrack、I∕O单元;

Xilinx FPGA: CLB(Configurable Logic Block)、IOB、布线资源(ICR)。

(2)RAM不同的使用。

Altera FPGA: EAB可用做大型RAM,LE也可以构成中搜表RAM;

Xilinx FPGA: 没有专门的RAM,需要时可由CLB中的LUT构成。

(3)基本单元不同。

Altera FPGA: LE(8个LE组成一个LAB,一个LE带触发器);

< style="margin-left:0cm;"> Xilinx FPGA: CLB(一个CLB带两个触发器)。

(4)布线不同

 Altera FPGA: FastTrack,局部互连,进位链和级联链;

 Xilinx FPGA: 单长线、双长线、长线。

(5)时钟的同步方式不同。

 Altera FPGA: 使用时钟锁定和时钟自举方法;

 Xilinx FPGA: 有一个时钟网用于时钟同步,在Virtex器件中使用DLL(Delay-locked-loop)技术,缩短了信号输出时间,提高了I∕O速度。

(6)另外,Xilinx FPGA中有专门的乘法器。

2.1.3 FPGA的编程工艺

FPGA的功能由逻辑结构的配置数决定。工作时,这些配置数据存放在片内的SRAM或熔丝图上。基于SRAM的FPGA器件,在工作前需要从芯片外部加载配置数据,配置数据可以存储在片外的EPROM或其他存储体上。用户可以控制加载过程,在现场修改器件的逻辑功能,即所谓的现场编程。

用户可以根据不同的配置模式,采用不同的编码方式。加电时,FPGA芯片将EPROM中数据读入片内编程RAM中,配置完成后,FPGA进入工作状态。掉电后,FPGA恢复成白片,内部逻辑关系消失,因此,FPGA能够反复使用。FPGA的编程无需专用的FPGA编程器,只需用通用的EPROM、PROM编程即可。当需要修改FPGA功能时,只需要换一片EPROM即可。这样,同一片FPGA,不同的编程数据,可以产生不同的电路功能。因此,FPGA的使用非常灵活。

FPGA有多种配置模式:并行主题模式为一片FPGA加一片EPROM的方式;主从模式可以支持一片PROM编程多片FPGA;串行模式可以采用串行PROM编程FPGA;外设模式可以将FPGA作为微处理器的外设,有微处理器对其进行编译。

 

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_arith.all;

USE ieee.std_logic_unsigned.all;

ENTITY videocpt IS

PORT

(

       cdao : out std_logic_vector(7 downto 0); -- 验证视频数据输出口

       cps : out std_logic;    -- 视频数据输出像素 Pixel SYN Signal

       cfs : out std_logic;    -- 视频数据输出帧

       caclk: out std_logic;

       cclk : in std_logic;     --主时钟 24M

       cdi : in std_logic_vector(7 downto 0);        --视频数据输入口

       pclk : in std_logic;     -- 采集时钟 4M

       ccs : in std_logic;      -- 视频信号选择

       avf : in std_logic;      --有效场同步帧

       avh : in std_logic;              --有效行同步帧

       vd : in std_logic               --场同步信号

);

END videocpt;

ARCHITECTURE a OF videocpt IS

       constant StartWidPix : integer range 0 to 1023 := 0; --起始宽度像素常量

       constant StartHiPix : integer range 0 to 288 := 0;      --起始高度像素常量

       constant EndWidPix : integer range 0 to 1023 := 704; --末端宽度像素常量

       constant EndHiPix : integer range 0 to 288 := 287;  --末端高度像素常量

       signal pclk1 : std_logic := '0';

       signal demodata : std_logic_vector(7 downto 0) := "01111001";

       signal readline : std_logic := '0';

       signal read : std_logic := '0';

       signal done : std_logic := '0';

BEGIN

       process (cclk)

              variable ccount : integer range 0 to 3 :=0;

       begin

         if cclk='1' and cclk'event then

              if ccount < 3 then

                     ccount := ccount+1; caclk <= '1';

              else

                     ccount := 0; caclk <= '0';

              end if;

         end if;

       end process;

       process (cclk, ccs )

              variable HPCnt : integer range 0 to 288 := 0;

              variable WPCnt : integer range 0 to 1023 := 0;

              variable avh1 : std_logic;               -- avh延迟1个周期

              variable vd1 : std_logic;          -- vd延迟1个周期

              variable frame : boolean;         -- 搜索起始帧

       begin

              if ccs = '1' then

                     read <='0';

                     frame := FALSE;

                     HPCnt:=0;

                     WPCnt:=0;

                     done <='0';

              elsif cclk='1' and cclk'event then

                     pclk1<=pclk;

                     if vd1='1' and vd='0' and done='0' then

                            done<='1';

                            frame :=TRUE;

                            HPCnt:=0;

                            WPCnt:=0;

                     end if;

                     if frame and avh1='0' and avh='1' then

                            if HPCnt < 288 then

                                   HPCnt:=HPCnt+1;

                            end if;

                            WPCnt:=0;

                     end if;

                     if frame and avh='1' and avf='1' then

                            readline<='1';

                     else

                            readline<='0';

                     end if;

                     if(readline='1' and pclk='0'and pclk1='1')then

                            WPCnt:=WPCnt+1;

                     end if;

--此处如果用if frame and HPCnt>3-HiPix and HPCnt<=HiPix and avh='1' and avf = '1' then 就会出现毛刺

                     if frame and HPCnt>StartHiPix and HPCnt<=EndHiPix and WPCnt>=StartWidPix and WPCnt<EndWidPix then

                            if avh='1' and avf = '1' then

                                   read <='1';

                                   demodata<=cdi;

                            else

                                   read<='0';

                            end if;

                     else

                            read <='0';

                     end if;

                     vd1:=vd;

                     avh1:=avh;

              end if;

       end process;

       cdao <= demodata WHEN read = '1' ELSE (OTHERS=>'1') ;

       cps <= not pclk1 WHEN read = '1' ELSE '1' ;

       cfs <= '1';

END a;

 

C语言

#include "DataType.h"

void ffdct(LINT8 *mcubyte, LINT32 *array)

{

       LINT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;

       LINT32 tmp10, tmp11, tmp12, tmp13;

       LINT32 z1, z2, z3, z4, z5, z11, z13;

       LINT32* dataptr;

       LINT8* datain;

       int ctr;

       datain = mcubyte;

       dataptr = array;

       for(ctr=0;ctr<64;ctr++)

       {

              dataptr[ctr]=datain[ctr]-128;

       }

                                                                                    /* 第一部分,对行进行计算 */

       for (ctr = 7; ctr >= 0; ctr--)

       {

              tmp0 = dataptr[0] + dataptr[7];

              tmp7 = dataptr[0] - dataptr[7];

              tmp1 = dataptr[1] + dataptr[6];

              tmp6 = dataptr[1] - dataptr[6];

              tmp2 = dataptr[2] + dataptr[5];

              tmp5 = dataptr[2] - dataptr[5];

              tmp3 = dataptr[3] + dataptr[4];

              tmp4 = dataptr[3] - dataptr[4];

                                                                                    /* 对偶数项进行运算 */

              tmp10 = tmp0 + tmp3;                /* 相位2 */

              tmp13 = tmp0 - tmp3;

              tmp11 = tmp1 + tmp2;

              tmp12 = tmp1 - tmp2;

              dataptr[0] = tmp10 + tmp11;         /*相位3 */

              dataptr[4] = tmp10 - tmp11;

              z1 = (tmp12 + tmp13) * (46341);    /* c4 / 0.707106781 */

              z1 = z1 >> 16;

              dataptr[2] = tmp13 + z1;            /* 相位 5 */

              dataptr[6] = tmp13 - z1;

                                                                                       /* 对奇数项进行计算 */

              tmp10 = tmp4 + tmp5;                  /* 相位2 */

              tmp11 = tmp5 + tmp6;

              tmp12 = tmp6 + tmp7;

              z5 = (tmp10 - tmp12) * (25080);      /* c6 /0.382683433 */

              z5 = z5 >> 16;

 

              z2 = tmp10*(35468);

              z2 = z2 >> 16;

              z2 = z2 + z5;

 

              z4 = tmp12 * (85627);

              z4 = z4 >> 16;

              z4 = z4 + z5;

              z3 = tmp11 * (46341);                /* c4 / 0.707106781*/

              z3 = z3 >> 16;

              z11 = tmp7 + z3;                                   /* 相位 5 */

              z13 = tmp7 - z3;

              dataptr[5] = z13 + z2;                           /* 相位 6 */

              dataptr[3] = z13 - z2;

              dataptr[1] = z11 + z4;

              dataptr[7] = z11 - z4;

              dataptr += 8;                                                 /* 将指针指向下一行 */

       }

                                                                                    /* 第二部分,对列进行计算 */

       dataptr = array;

       for (ctr = 7; ctr >= 0; ctr--)

       {

              tmp0 = dataptr[0] + dataptr[56];

              tmp7 = dataptr[0] - dataptr[56];

              tmp1 = dataptr[8] + dataptr[48];

              tmp6 = dataptr[8] - dataptr[48];

              tmp2 = dataptr[16] + dataptr[40];

              tmp5 = dataptr[16] - dataptr[40];

              tmp3 = dataptr[24] + dataptr[32];

              tmp4 = dataptr[24] - dataptr[32];

                                                                                           /* 对偶数项进行运算 */

              tmp10 = tmp0 + tmp3;                                /* 相位 2 */

              tmp13 = tmp0 - tmp3;

              tmp11 = tmp1 + tmp2;

              tmp12 = tmp1 - tmp2;

              dataptr[0] = tmp10 + tmp11;                /* 相位3 */

              dataptr[32] = tmp10 - tmp11;

              z1 = (tmp12 + tmp13) * (46341);         /* c4 / 0.707106781 */

              z1 = z1 >> 16;

              dataptr[16] = tmp13 + z1;                     /* 相位5 */

              dataptr[48] = tmp13 - z1;

                                                                                           /* 对奇数项进行计算 */

              tmp10 = tmp4 + tmp5;                                 /* phase 2 */

              tmp11 = tmp5 + tmp6;

              tmp12 = tmp6 + tmp7;

              z5 = (tmp10 - tmp12) * (25080);           /* c6 /0.382683433 */

              z5 = z5 >> 16;

              z2 = tmp10*(35468);

              z2 = z2 >> 16;

              z2 = z2 + z5;

              z4 = tmp12 * (85627);

              z4 = z4 >> 16;

              z4 = z4 + z5;

              z3 = tmp11 * (46341);                                  /* c4 / 0.707106781*/

              z3 = z3 >> 16;

              z11 = tmp7 + z3;                                          /* 相位5 */

              z13 = tmp7 - z3;

              dataptr[40] = z13 + z2;                         /* 相位6 */

              dataptr[24] = z13 - z2;

              dataptr[8] = z11 + z4;

              dataptr[56] = z11 - z4;

              ++dataptr;                                                    /* 将指针指向下一列 */

       }

       dataptr = array;

       for(ctr=0;ctr<64;ctr++) dataptr[ctr]=dataptr[ctr]>>3;}

 

#include "DataType.h"

#include "tables.h"

#include "dct.h"

#include "flash.h"

#define DEBUG

#ifdef DEBUG

#include "serial.h"

#endif

#define CIFW 352

#define CIFH 288

LINT8 cha_y[CIFW][CIFH];

LINT8 cha_u[CIFW/2][CIFH/2];

LINT8 cha_v[CIFW/2][CIFH/2];

LINT8 ix=0;

LINT8 iy=0;

LINT32 ydc=0,udc=0,vdc=0;

LINT32 accoder[16][11],acbit[16][11];

LINT32 accoder2[16][11],acbit2[16][11];

 

///文件部分/

 

#define MAXSIZE 262114 //256K

typedef struct{

       LINT8 buffer[MAXSIZE];

       LINT32 fp,lp,CurrentPosition,length;

       LINT8 CurrentData;

       LINT8 CurrentBits;

       }FILEBUF;

FILEBUF infile;

                                                                                           //输入数据,长度为bits

void PutDatatoJpegFile(LINT32 data,LINT8 bits,FILEBUF *buf)

{

       LINT8 CurrentFreeBits=0;

       while (bits!=0)

       {

              if (buf->CurrentBits+bits<8)

              {

                     buf->CurrentData=(buf->CurrentData<<bits)|data;

                     buf->CurrentBits+=bits;

                     bits=0;

              }

              else

              {

                     CurrentFreeBits=8-buf->CurrentBits;

                     bits=bits-CurrentFreeBits;

              buf->CurrentData=(buf->CurrentData<<CurrentFreeBits)|data>>bits;

                     buf->buffer[buf->CurrentPosition]=buf->CurrentData;

                     buf->CurrentPosition++;

                     buf->length++;

                                                                                    //如果data=0xFF, 加0

                     if (buf->CurrentData==0xff)

                     {

                            buf->buffer[buf->CurrentPosition]=0;

                            buf->CurrentPosition++;

                            buf->length++;

                     }

                     buf->CurrentData=0;

                     buf->CurrentBits=0;

                     data=data&mask[bits];

              }

       }

}

 

///Huffman编码 /

 

typedef struct

{

       LINT32 maxcode[16];

       LINT32 mincode[16];

       LINT8 ml;

       unsigned valptr[16];

}DHUFF;

 

typedef struct

{

       LINT8 huffval[256];

}XHUFF;

 

DHUFF dhuff,dhuffdc,dhuff2,dhuffdc2;

XHUFF xhuff,xhuffdc,xhuff2,xhuffdc2;

void len2huff(LINT8 *lengthtab,DHUFF *dhuff,XHUFF *xhuff,LINT8 *val)

{

       int i,l,k,base=0;

       dhuff->ml=16;

       for(i=0;i<dhuff->ml;i++)

       {

              dhuff->mincode[i]=0;

              dhuff->maxcode[i]=0;

              dhuff->valptr[i]=-1;

       }

       for(i=0;i<256;i++)

              xhuff->huffval[i]=0;

              i=0;

              base=0;

       for(l=0;l<dhuff->ml;l++)

       {

              if(lengthtab[l]!=0)

              {

                     dhuff->mincode[l]=base;

                     dhuff->valptr[l]=i;

              }

              for(k=0;k<lengthtab[l];k++)

              {

                     xhuff->huffval[i]=val[i];

                     i++;

                     base++;

              }

              if(lengthtab[l]!=0)dhuff->maxcode[l]=base-1;

              base=base*2;

       }

}

void iztransfer(LINT32 *array)

{

       LINT32 temp[64],n,x,y;

       for(n=0;n<64;n++)

       {

              x=iztab[2*n];

              y=iztab[2*n+1];

              temp[n]=array[x*8+y];

       }

       for(n=0;n<64;n++)

       array[n]=temp[n];

}

//量化

void qdata(LINT32 * in,LINT32 * out,LINT8 level)

{

       int i;

       for(i=0;i<64;i++)

       {

              if(in[i]>0)

                     out[i]=in[i]/agraytab[level][i];

              else

                     out[i]=in[i]/agraytab[level][i];

       }

}

void quvdata(LINT32 * in,LINT32 * out,LINT8 level)

{

       int i;

       for(i=0;i<64;i++)

       {

              if(in[i]>0)

                     out[i]=in[i]/acolortab[level][i];

              else

                     out[i]=in[i]/acolortab[level][i];

       }

}

//从SRAM 0xC0100000读数据到 cha_y[CIFW][CIFH];

//cha_u[CIFW/2][CIFH/2]; cha_v[CIFW/2][CIFH/2];

 

#ifdef DEBUG

void put_num8(unsigned char i)

{

       put_char(((((i>>4) & 0x0f) + '0')> '9' )? ((i>>4) & 0x0f) +'0'+7 : ((i>>4) & 0x0f) +'0' );

       put_char((((i & 0x0f) + '0')> '9' )? (i & 0x0f) +'0'+7 : (i & 0x0f) +'0' );

}

static void put_num32(int i)

{

       put_num8((unsigned char)(( i>>24) & 0xff));

       put_num8( (unsigned char) (i>>16 & 0xff));

       put_num8((unsigned char)(( i>>8) & 0xff));

       put_num8( (unsigned char) (i & 0xff));

}

#endif

void readfile(void)

{

       int i,count=0;

       for (i=0;i<CIFW*CIFH*6/4;i+=6)

       {

                                                                                                  //取决于图像的帧格式

              cha_y[(i*2/6%CIFW)][(i*2/6/CIFW)*2]=RAM_BYTE(i);

              cha_y[(i*2/6%CIFW)+1][(i*2/6/CIFW)*2]=RAM_BYTE(i+1);

              cha_y[(i*2/6%CIFW)][(i*2/6/CIFW)*2+1]=RAM_BYTE(i+2);

              cha_y[(i*2/6%CIFW)+1][(i*2/6/CIFW)*2+1]=RAM_BYTE(i+3);

              cha_u[i/6%(CIFW/2)][i/6/(CIFW/2)]=RAM_BYTE(i+4);

              cha_v[i/6%(CIFW/2)][i/6/(CIFW/2)]=RAM_BYTE(i+5);

              count++;

       }

}

                                                                                           //写编码文件到串行口

void writefile(FILEBUF *buf)

{

       int i;

       for (i=0;i<=buf->length;i++)

       {

         

标签: 继电器ah5cniy集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台