【最新版】基于FPGA的图像采集系统设计毕业设计

更新时间:2023-04-11 04:16:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于FPGA的图像采集系统设计

前言

随着科技社会的发展,图像采集系统在日常生活、工业生产、国家安全等众多领域得到广泛的应用,具有广阔的应用前景和研究价值。采用FPGA进行设计的图像采集系统有良好的扩展性能和相对稳定的硬件结构。主要工作如下: 1)分析图像采集和图像处理的原理和特点,设计硬件电路的原理图,完成系统PCB板图的设计。 2)针对FPGA进行内部功能模块的划分,使用Verilog HDL硬件描述语言进行设计。 3)利用SOPC Builder 完成NIOS处理器软核及其外设的创建和配置。 4)根据FPGA内部硬件电路的特点,选择适合FPGA的算法,并对算法进行优化。 5)在NIOS II IDE环境下用Verilog HDL语言编写图像传感器控制、图像采集、SRAM读写控制、图像显示等程序,实现完整的图像采集系统功能。

1课题分析

1.1 选题背景(含国内外相关研究综述及评价)与意义

EDA技术的发展和应用普及性越来越高,已经涉及到现代电子产品设计的各个系统、各个领域中。之所以有这样的广泛应用,主要得益于可编程逻辑器件的长足发展和日益成熟,可编程逻辑器件(Programmable Logic Device, PLD)是一种半定制集成电路,在其内部集成了大量的门和触发器等基本逻辑单元电路,通过用户编程来改变PLD内部电路的逻辑关系或连线,从而得到所需要的电路设计功能。这种新型逻辑器件,不仅速度快、集成度高,能够完成用户定义的逻辑功能,还可以加密和重新定义编程,其允许编程次数可以达到上万次。可编程逻辑器件的出现,大大改变了传统数字系统设计方法,简化了硬件系统、降低成本、提高系统的可靠性、灵活性。因此,自20世纪70年代问世以后,PLD受到广大工程师的青睐,被广泛应用于工业控制、通信设备、仪器仪表和医疗电子仪器等众多领域,为EDA技术开创了广阔的发展空间。

VGA作为一种标准的显示接口,在视频和计算机领域得到了广泛的应用。VGA图像信号发生器是电视台、电视机生产企业、电视维修人员常用的仪器,其主要功能就是产生标准的图像测试信号。对VGA而言,其主要应用在工业控制领域,通过VGA接口实现将信息、图像、文字等内容显示各种VGA显示器上,为客户提供一种完美的显示界面,也是目前重要的显示终端。本次实验设计主要是基于FPGA芯片为处理器,利用硬件描述语言完成VGA的时序控制,并利用相应的实验平台,进行设计验证,基本实现了VGA 的彩条信号和图像显示效果,达到了整个设计目标和要求。

1.2 选题研究的方法与主要内容

1.2.1研究方法

通过查阅资料,学习VGA工作原理和控制方法,掌握EDA技术应用基本技巧,运用FPGA为设计实现的处理器,完成VHDL对各个模块的功能描述,在实验平台上完成整个系统设计实现。

1.2.2主要内容

◆根据设计任务,制定实现方案

◆应用VHDL完成对系统中各个功能模块的描述

◆完成顶层设计文件,并调试仿真系统

◆下载程序代码到FPGA,在实验平台上验证VGA是否正常显示

撰写设计报告书

1.3 研究条件和可能存在的问题

1.3.1研究条件

会使用EDA开发工具软件Quartus II ,能熟练使用VHDL语言编写时序电路,需要有相应的实验开发平台。

1.3.2可能存在的问题:

◆VGA时序控制不正确,无法正常显示相应的图形

◆VGA硬件接口电路PCB设计不能实现其功能

◆FPGA内部ROM存储空间太小,不能存储大容量的图片数据

1.4 拟解决的主要问题和预期的结果

1.4.1拟解决的主要问题

◆VGA时序控制问题

◆PROTEL绘制VGA电阻分压网络电路设计问题

◆调试VHDL程序代码常见错误

1.4.2预期的结果

通过完成整个系统的电路设计,实现各个功能模块和顶层设计电路,能在显示器上正确看到横竖彩条、棋盘格图形和图片显示等效果。

2 图像采集系统介绍

2.1 图像采集系统功能分析

这部分阐述了图像采集系统的各种动作功能和控制要求,给出了完整的图像采集系统操作规程,并介绍了图像采集运行系统中所包括的人工操作步骤。

2.1.1 图像采集系统的基本功能

在进行上、下位机程序编写之前,首先要做的工作是确定图像采集系统本身所具备的功能及在进行某种操作后所具有的状态。

在实际生活中,我们见到的图像采集系统可以采集一些简单的图像,如书本、人物和植物等。图像采例集系统的基本功能就是对图像进行采集,并进行简单的处理。举一个简单的例子来说明:

采集一本书的图像,系统会根据书的颜色大小自动调整,使采集的图像清晰,尽量减小失真。当图像达到最佳状态时,系统等待外部命令,如继续采集,则同上,如果此时不再采集而按下退出按钮,系统则要进行退出操作,并提示你是否保存所采集的图像,完成此次操作。由此看来,系统一次采集要涉及摄像头、VGA以及FPGA等,这是它的内部功能。基于FPGA实现的图像采集系统的整体结构框图如图1.1.1-1所示:系统主要分为:图像采集模块、PLL锁相环时钟管理模块、I2C总线模块、FIFO图像数据处理模块、Nios II 显示控制模块。系统中PLL负责为Nios II嵌入式内核、外部SDRAM和OV7670摄像头提供时钟,系统通电后,FPGA首先从EPCS中读取配置数据,完成自身程序加载,随后对系统时钟分频为摄像头提供系统时钟,然后通过I2C总线完成对OV7670摄像头的配置。

配置完成后,OV7670将采集到的图像数据输出格式转换为标准的图像数据及图像时钟送入FPGA进行处理,并将处理后的图像数据通过FIFO模块暂时存储在SDRAM中进行缓冲,同时Nios II模块读取存放在SDRAM中的图像数据,按照TFT液晶显示的时序、数据要求将图像数据送到TFT彩色液晶显示屏上显示。

图1.1.1-1 图像采集系统结构

3 系统硬件设计

3.1 FPGA选型

FPGA是该系统的核心,由于系统目前只是完成简单的图像处理,故FPGA选用Altera 公司的低成本FPGA Cyclone II系列器件简介如表所示。

Cyclone II器件采用90nm工艺制造,它延续Cyclone的低成本定位,在逻辑容量、PLL、乘法器和I/O数量上都比Cyclone有了较大提高,应用Cyclone II进行图像处理开发有如下优点:(1)低成本高性能,适应图像处理要求较高的需要。(2)丰富的内嵌存储器资源,适应大量图像数据存取的需要。(3)丰富的硬件乘法器,适应图像处理算法的需要。系统的FPGA选用开发板自带的EP2CS5Q208C8芯片。

Cyclone II系列FPGA参数对比

器件EP2C5 EP2C8 EP2C15 EP2C20 EP2C35 EP2C50 EP2C70

逻辑单元4608 8256 14448 18752 33216 50528 68416 M4K RAM块26 36 52 52 105 129 250 总比特数119808 165888 239616 239616 483840 594432

嵌入式乘法器13 18 26 26 35 86 150 PLL个数 2 2 4 4 4 4 4 最多用户I/O管脚158 182 315 315 475 450 622

3.2 图像采集模块选择

图像采集采用OV7670图像传感器,OV7670图像传感器体积小、工作电压低。OV7670摄影头的VGA图像最高达到30帧/秒。通过SCCB总线控制内部寄存器,可以是OV7670输出整帧、子采样、取窗口等方式的各种分辨率的图像数据。用户还可以完全控制图像质量、数据格式和传输方式。OV7670与FPGA硬件连接如图所示。

3.3 图像显示模块

图像显示通过在FPGA中构建的Nios II嵌入式内核实现,Nios II系统可以在设计阶段根据实际的需求来增减外设的数量和种类。可以使用Altera提供的开发工具SOPC Builder,在FPGA器件上创建软硬件开发的基础平台,即用SOPC Builder创建嵌入式内核CPU和参数化的接口总线Avalon。在此基础上,可以快速地将硬件系统与常规软件集成在单一可编程芯片中。而且SOPC Builder还提供标准的接口方式,以便用户将外围电路做成Nios II嵌入式内核可以添加的外设模块。这种设计方式,方便了各类系统的调试。

3.4 PLC的选型与工作原理

当某一个控制任务决定由PLC来完成后,选择PLC就成为最重要的事情。一方面要选择多大容量的PLC ,另一方面是选择什么公司的PLC及外设。

对第一个问题,首先要对控制任务进行详细的分析,把所有的I/O点找出来,包括开关量I/O和模拟量I/O以及输出是用继电器还是晶体管或是可控硅型。

3.4.1 PLC的硬件结构图:

图2.4.1-1 PLC硬件结构图

3.4.2 PLC各部分的作用与工作原理

3.4.2.1 中央处理器

CPU是由控制器和运算器组成的。运算器也称为算术逻辑单元,它的功能就是进行算术运算和逻辑运算。控制器的作用是控制整个计算机的各个部件有条不紊地工作,其基本功能是从内存中取指令和执行指令。他的重要功能如下:

★诊断PLC电源、内部电路的工作状态及编制程序中的语法错误。

★采集由现场输入装置送来的状态或数据,并送入PLC的寄存器中。

★按用户程序存储器中存放的先后顺序逐条读取指令,进行编译解释后,按指令规定的任务完成各种运算和操作。

★将存于寄存器中的处理结果送至输出端。

★应各种外部设备的工作请求。

3.4.2.2 存储器

PLC的存储器分为两大部分:

一大部分是系统存储器,用来存放系统管理程序、监控程序及其系统内部数据;二大部分是用户存储器,包括用户程序存储区及工作数据存储区。

3.4.2.3 PLC的基本工作原理

PLC采用的是循环扫描工作方式。对每个程序,CPU从第一条指令开始执行,按指令步序号做周期性的程序循环扫描,如果无跳转指令,则从则从第一条指令开始逐条顺序执行用户程序,直至遇到结束符后又返回第一条指令,如此周而复始不断循环,每一个循环称为一个扫描周期。PLC的扫描全过程如图2.4.2.3-1所示。

图3.4.2.3-1 PLC的扫描全过程

3.4.2.3.1 输入刷新阶段

在输入刷新阶段,CPU扫描全部输入端口,读取其状态并写入输入状态寄存器。完成后关闭输入端口,转入程序执行阶段。

3.4.2.3.2 程序执行阶段

在程序执行阶段,根据用户输入的控制程序,从第一条开始逐条执行,并将相应的逻辑运算结果存入对应的内部辅助寄存器和输出状态寄存器。

3.4.2.3.3 输出刷新阶段

当所有指令执行完毕后,将输出状态寄存器中的内容,依次送到输出锁存电路,并通过一定输出方式输出,驱动外部相应执行元件工作,这才形成PLC的实际输出。显然扫描周期的长短主要取决与程序的长短。扫描周期越长,响应速度越慢。

由于每一个扫描周期只进行一次I/O刷新,即每一个扫描周期PLC只对输入、输出状态寄存器更新一次,故使系统存在输入、输出滞后现象,这在一定程度上降低了系统的响应速度。I/O端口设置见表3.4.2.3.3-1:

表3.4.2.3.3-1 I/O端口设置

由此可见,若输入变量在I/O刷新期间状态发生变化,则本次扫描期间输出会相应地发生变化。反之,若在本次刷新之后输入变量才发生变化,则本次扫描输出不变,而要到下一次扫描的I/O刷新期间输出才会发生变化。这对于一般的开关量控制系统来说是完全允许的,不但不会造成不利影响,反而可以增强系统的抗干扰能力。这是因为输入采样仅在输入刷新阶段进行,PLC在一个工作周期的大部分时间里实际上是外设隔离的。而工业现场的干扰常常是脉冲式的、短时的,由于系统响应较慢,往往要几个扫描周期才响应一次,而多次扫描后,因瞬间干扰而引起的误操作将会大大减少,从而提高了系统的抗干扰能力。但是对于控制时间要求较严格、响应速度要求较快的系统,就需要精心编制程序,必要时采用一些特殊功能,以减少因扫描周期造成的响应滞后等不良影响。

3.5 VGA的概述

VGA(Video Graphics Array)是IBM公司在1987年推出的一种视频传输标准,具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域得到了广泛的应用,VGA 最早是指分辨率为640*480的一种显示模式。下面就VGA相关的工作原理及时序要求进行简单介绍。

3.5.1 CRT的工作原理

VGA接口技术应用最多的就是CRT显示器,这种显示器的信号接口采用的就是标准的VGA接口。常见的彩色显示器,一般由 CRT (阴极射线管)构成,彩色是由 R、G、B 三原色按不同比例组成。显示过程中,HS和VS的极性可正可负,显示器内可自动转换为正极性逻辑。

3.5.2 VGA工作时序

对于普通的VGA显示器,主要包含5个信号:

●R、G、B:三基色信号

●HS: 行同步信号

●VS:场同步信号

图3.5-1 VGA行扫描时序

图3.5-2 VGA场扫描时序

表3.5-1 行扫描时序时间(单位:像素,即输出一个像素Pixel的时间间隔)

表3.5-2 场扫描时序时间(单位:行,即输出一行Line的时间间隔)

系统原理图

系统PCB图

4 系统软件设计

4.1软件模块介绍

系统软件总设计模块如图所示,在 pll 中建立PLL锁相环对时钟倍频、分频产生系统各模块所需时钟与系统复位信号,ov7670-data_receive 模块负责OV7670摄像头的初始化与图像数据的采集,模块配合Nios II负责对ov7670-data_receive 采集的图像数据的缓存,以防止数据时钟不匹配而出现数据紊乱,而模块主要负责产生读取中的数据域实现数据的VGA显示产生相应的RGB数据与行、场同步信号,再将采

系统总设计框图

4.2 Nios II嵌入式内核程序设计

Nios II嵌入式内核主要任务是将采集到的数据送入SDRAM暂存,然后再根据显示需要将暂存的数据读取出来送到LCD显示,为了确保显示图像与采集图像的一致,在送LCD显示数据时要注意以下几点:

(1)根据实际情况去除行、场消隐数据,再根据显示内容的多少对数据进行裁

剪,裁剪到适合LCD显示的大小,从而避免显示时图像的错位以及乱码

等情况。

(2)由于嵌入式内核时钟频率相对于摄像头的大量数据来说速度还是难以做到摄像头采集的每副图像都能完全显示,所以在设计中采用隔场采集处理

的方式,这样避免SDRAM中数据过多以至于被填满的情况,也解决了嵌

入式内核采集的出现的卡屏的情况。

5 测试结果

电路板成品:

测试结果如图所示:

由上图可以看出,显示的图像清晰,色彩与实际相符,失真较少。测试结果基本达到预期。

6 结束语

采用FPGA设计并实现了一种图像采集系统,大幅减少了电路板的尺寸,节约了成本,同时增加了设计的灵活性和系统的可靠性,充分应用FPGA快速并行处理数据的特性,在产生同步信号的同时送出像素数据。嵌入式内核Nios II的使用,解决了其他系统实时图像显示的体积与速度问题,扩展了应用范围。

(全文完)

参考文献:

[1] 潘松、黄继业: EDA技术实用教程,科学出版社,2003.5,P23-P28

[2] 杨静: 电子设计自动化,高等教育出版社,2004.7,P32-P36

[3] 张文爱:EDA技术与FPGA应用设计,电子工业出版社,2012.1,P25-P48

[4] 杨立英:电子电路EDA技术与应用,清华大学出版社,2011.1,P43-P86

[5] 徐志军、徐光辉:VGA在CPLD/FPGA的开发与应用,电子工业出版社,2002.4,P12-P16

[6] 黄智伟: FPGA系统设计与实践,电子工业出版社,2005.1,P66-P69

[7] 潘松、王国栋:VHDL实用教材(修订版),电子科技大学出版社,2001.7,P48-P52

[8] 孟宪元:FPGA嵌入式系统设计,电子工业出版社,2007.10,P56-P64

[9] 褚振勇、齐亮、田红心:FPGA设计及应用,高等教育出版社,2006.12,P36-P41

附录:源程序

`timescale 1ns/1ns module I2C_Controller (

input iCLK, input iRST_N, input I2C_CLK, input I2C_EN, input [23:0] I2C_WDATA, output I2C_SCLK, inout I2C_SDAT, input WR, input GO, output ACK, output reg END, output reg [7:0] I2C_RDATA );

reg I2C_BIT ; reg SCLK ;

reg [5:0] SD_COUNTER ;

wire I2C_SCLK1 = (GO == 1 && ((SD_COUNTER >= 5 && SD_COUNTER <=12 || SD_COUNTER == 14) || (SD_COUNTER >= 16 && SD_COUNTER <=23 || SD_COUNTER == 25) || (SD_COUNTER >= 27 && SD_COUNTER <=34 || SD_COUNTER == 36))) ? I2C_CLK : SCLK ;

wire I2C_SCLK2 = (GO == 1 && ((SD_COUNTER >= 5 && SD_COUNTER <=12 || SD_COUNTER == 14) || (SD_COUNTER >= 16 && SD_COUNTER <=23 || SD_COUNTER == 25) || (SD_COUNTER >= 33 && SD_COUNTER <=40 || SD_COUNTER == 42) || (SD_COUNTER >= 44 && SD_COUNTER <=51 || SD_COUNTER == 53))) ? I2C_CLK : SCLK ; assign I2C_SCLK = WR ? I2C_SCLK1 : I2C_SCLK2;

wire SDO1 = ((SD_COUNTER == 13 || SD_COUNTER == 14)|| (SD_COUNTER == 24 || SD_COUNTER == 25) || (SD_COUNTER == 35 || SD_COUNTER == 36)) ? 1'b0 : 1'b1; wire SDO2 = ((SD_COUNTER == 13 || SD_COUNTER == 14)|| (SD_COUNTER == 24 || SD_COUNTER == 25) || (SD_COUNTER == 41 ||

SD_COUNTER == 42) || (SD_COUNTER >= 43 && SD_COUNTER <= 51)) ? 1'b0 : 1'b1; wire SDO = WR ? SDO1 : SDO2;

assign I2C_SDAT = SDO ? I2C_BIT : 1'bz; reg ACKW1, ACKW2, ACKW3; reg ACKR1, ACKR2, ACKR3;

assign ACK = WR ? (ACKW1 | ACKW2 | ACKW3) : (ACKR1 | ACKR2 | ACKR3);

always @(posedge iCLK or negedge iRST_N) begin

if (!iRST_N)

SD_COUNTER <= 6'b0; else if(I2C_EN) begin

if (GO == 0 || END == 1) SD_COUNTER <= 6'b0; else if (SD_COUNTER < 6'd63) SD_COUNTER <= SD_COUNTER + 6'd1; end else

SD_COUNTER <= SD_COUNTER ;

end

always @(posedge iCLK or negedge iRST_N) begin

if(!iRST_N) begin SCLK <= 1; I2C_BIT <= 1;

ACKW1 <= 1; ACKW2 <= 1; ACKW3 <= 1; ACKR1 <= 1; ACKR2 <= 1; ACKR3 <= 1; END <= 0;

I2C_RDATA <= 8'h0; end

else if(I2C_EN) begin if(GO) begin if(WR) begin

case(SD_COUNTER )

6'd0 : begin

SCLK <= 1; I2C_BIT <= 1; ACKW1 <= 1; ACKW2 <= 1; ACKW3 <= 1;

ACKR1 <= 1; ACKR2 <= 1; ACKR3 <= 1; END <= 0; end

6'd1 : begin

SCLK<= 1; I2C_BIT<= 1; ACKW1<= 1; ACKW2 <= 1; ACKW3 <= 1;

END <= 0;

end

6'd2 : I2C_BIT <= 0;

6'd3 : SCLK <= 0;

6'd4 : I2C_BIT<= I2C_WDATA[23]; 6'd5 : I2C_BIT<= I2C_WDATA[22]; 6'd6 : I2C_BIT<= I2C_WDATA[21]; 6'd7 : I2C_BIT<= I2C_WDATA[20]; 6'd8 : I2C_BIT<= I2C_WDATA[19]; 6'd9 : I2C_BIT<= I2C_WDATA[18]; 6'd10 : I2C_BIT<= I2C_WDATA[17]; 6'd11 : I2C_BIT<= I2C_WDATA[16]; 6'd12 : I2C_BIT <= 0; 6'd13 : ACKW1 <= I2C_SDAT; 6'd14 : I2C_BIT <= 0; 6'd15 : I2C_BIT<= I2C_WDATA[15]; 6'd16 : I2C_BIT<= I2C_WDATA[14]; 6'd17 : I2C_BIT<= I2C_WDATA[13]; 6'd18 : I2C_BIT<= I2C_WDATA[12]; 6'd19 : I2C_BIT<= I2C_WDATA[11]; 6'd20 : I2C_BIT<= I2C_WDATA[10]; 6'd21 : I2C_BIT <= I2C_WDATA[9]; 6'd22 : I2C_BIT <= I2C_WDATA[8]; 6'd23 : I2C_BIT <= 0; 6'd24 : ACKW2 <= I2C_SDAT; 6'd25 : I2C_BIT <= 0; 6'd26 : I2C_BIT <= I2C_WDATA[7]; 6'd27 : I2C_BIT <= I2C_WDATA[6]; 6'd28 : I2C_BIT <= I2C_WDATA[5]; 6'd29 : I2C_BIT <= I2C_WDATA[4]; 6'd30 : I2C_BIT <= I2C_WDATA[3]; 6'd31 : I2C_BIT <= I2C_WDATA[2]; 6'd32 : I2C_BIT <= I2C_WDATA[1]; 6'd33 : I2C_BIT <= I2C_WDATA[0]; 6'd34 : I2C_BIT <= 0;

6'd35 : ACKW3 <= I2C_SDAT; 6'd36 : I2C_BIT <= 0; 6'd37 : begin SCLK<= 0; I2C_BIT

<= 0; end

6'd38 : SCLK <= 1;

6'd39 : begin I2C_BIT <= 1; END <= 1; end

default : begin I2C_BIT<= 1; SCLK <= 1; end endcase

end

else

begin

case(SD_COUNTER)

6'd0 : begin

SCLK <= 1;

I2C_BIT <= 1;

ACKW1<= 1; ACKW2<= 1; ACKW3<= 1;

ACKR1<= 1; ACKR2<= 1; ACKR3<= 1; END <= 0;

end

6'd1 : begin

SCLK <= 1;

I2C_BIT <= 1;

ACKR1<= 1; ACKR2<= 1; ACKR3<= 1;

END <= 0;

end

6'd2 : I2C_BIT <= 0;

6'd3 : SCLK <= 0;

6'd4 : I2C_BIT<= I2C_WDATA[23]; 6'd5 : I2C_BIT<= I2C_WDATA[22]; 6'd6 : I2C_BIT<= I2C_WDATA[21]; 6'd7 : I2C_BIT<= I2C_WDATA[20]; 6'd8 : I2C_BIT<= I2C_WDATA[19]; 6'd9 : I2C_BIT<= I2C_WDATA[18]; 6'd10 : I2C_BIT<= I2C_WDATA[17]; 6'd11 : I2C_BIT<= I2C_WDATA[16]; 6'd12 : I2C_BIT <= 0;

6'd13 : ACKR1 <= I2C_SDAT; 6'd14 : I2C_BIT <= 0; 6'd15 : I2C_BIT<= I2C_WDATA[15]; 6'd16 : I2C_BIT<= I2C_WDATA[14]; 6'd17 : I2C_BIT<= I2C_WDATA[13]; 6'd18 : I2C_BIT<= I2C_WDATA[12]; 6'd19 : I2C_BIT<= I2C_WDATA[11]; 6'd20 : I2C_BIT<= I2C_WDATA[10]; 6'd21 : I2C_BIT <= I2C_WDATA[9]; 6'd22 : I2C_BIT <= I2C_WDATA[8]; 6'd23 : I2C_BIT <= 0; 6'd24 : ACKR2 <= I2C_SDAT; 6'd25 : I2C_BIT <= 0; 6'd26 : begin SCLK<= 0; I2C_BIT<= 0; end

6'd27 : SCLK <= 1;

6'd28 : begin I2C_BIT <= 1; end 6'd29 : begin

SCLK <= 1;

I2C_BIT <= 1;

end

6'd30 : I2C_BIT <= 0;

6'd31 : SCLK <= 0;

6'd32 : I2C_BIT<= I2C_WDATA[23]; 6'd33 : I2C_BIT<= I2C_WDATA[22]; 6'd34 : I2C_BIT<= I2C_WDATA[21]; 6'd35 : I2C_BIT<= I2C_WDATA[20]; 6'd36 : I2C_BIT<= I2C_WDATA[19]; 6'd37 : I2C_BIT<= I2C_WDATA[18]; 6'd38 : I2C_BIT<= I2C_WDATA[17]; 6'd39 : I2C_BIT <= 1'b1; 6'd40 : I2C_BIT <= 0; 6'd41 : ACKR3 <= I2C_SDAT; 6'd42 : I2C_BIT <= 0; 6'd43 : I2C_BIT <= 0;

6'd44 : I2C_RDATA[7] <= I2C_SDAT; 6'd45 : I2C_RDATA[6] <= I2C_SDAT; 6'd46 : I2C_RDATA[5] <= I2C_SDAT; 6'd47 : I2C_RDATA[4] <= I2C_SDAT; 6'd48 : I2C_RDATA[3] <= I2C_SDAT; 6'd49 : I2C_RDATA[2] <= I2C_SDAT; 6'd50 : I2C_RDATA[1] <= I2C_SDAT; 6'd51 : I2C_RDATA[0] <= I2C_SDAT; 6'd52 : I2C_BIT <= 1; 6'd53 : I2C_BIT <= 0; 6'd54 : begin SCLK<= 0; I2C_BIT<= 0; end

6'd55 : SCLK <= 1;

6'd56 : begin I2C_BIT<= 1; END <= 1; end

endcase

end

end

else

begin

SCLK <= 1;

I2C_BIT <= 1;

ACKW1<= 1; ACKW2<= 1; ACKW3<= 1;

ACKR1<= 1; ACKR2<= 1; ACKR3<= 1;

END <= 0;

I2C_RDATA <= I2C_RDATA;

end

end

end

endmodule `timescale 1ns/1ns

module I2C_AV_Config

(

input iCLK,

input iRST_N,

output I2C_SCLK,

inout I2C_SDAT,

output reg Config_Done); parameter LUT_SIZE = 168;

parameter CLK_Freq = 25_000000; parameter I2C_Freq = 10_000;

reg [15:0] mI2C_CLK_DIV;

reg mI2C_CTRL_CLK; always@(posedge iCLK or negedge iRST_N) begin

if(!iRST_N)

begin

mI2C_CLK_DIV <= 0;

mI2C_CTRL_CLK <= 0;

end

else

begin

if( mI2C_CLK_DIV <

(CLK_Freq/I2C_Freq)/2)

mI2C_CLK_DIV <= mI2C_CLK_DIV+ 1'd1; else

begin

mI2C_CLK_DIV <= 0;

mI2C_CTRL_CLK <=

~mI2C_CTRL_CLK;

end

end

end

reg i2c_en_r0, i2c_en_r1;

always@(posedge iCLK or negedge iRST_N) begin

if(!iRST_N)

begin

i2c_en_r0 <= 0;

i2c_en_r1 <= 0;

end

else

begin

i2c_en_r0 <= mI2C_CTRL_CLK;

i2c_en_r1 <= i2c_en_r0;

end

end

wire i2c_negclk = (i2c_en_r1 & ~i2c_en_r0) ? 1'b1 : 1'b0; wire mI2C_END ; wire mI2C_ACK ; reg [7:0] LUT_INDEX ; reg [1:0] mSetup_ST ; reg mI2C_GO ; reg mI2C_WR ; reg [15:0] LUT_DATA ; always@(posedge iCLK or negedge iRST_N) begin

if(!iRST_N) begin

Config_Done <= 0; LUT_INDEX <= 0; mSetup_ST <=0; mI2C_GO <= 0; mI2C_WR <= 0; end

else if(i2c_negclk ) begin

if(LUT_INDEX < LUT_SIZE ) begin

Config_Done <= 0; case(mSetup_ST )

0: begin if(~mI2C_END ) mSetup_ST <= 1; else mSetup_ST <= 0; mI2C_GO <= 1; if(LUT_INDEX < 8'd2) mI2C_WR <= 0; else

mI2C_WR <= 1; end

1: begin if(mI2C_END ) begin

mI2C_WR <= 0; mI2C_GO <= 0; if(~mI2C_ACK ) mSetup_ST <= 2; else

mSetup_ST <= 0; end end

2: begin LUT_INDEX <= LUT_INDEX + 8'd1; mSetup_ST <= 0; mI2C_GO <= 0;

mI2C_WR <= 0; end endcase end else begin

Config_Done <= 1'b1; LUT_INDEX <= LUT_INDEX ; mSetup_ST <= 0; mI2C_GO <= 0;

mI2C_WR <= 0; end end

end

I2C_Controller u_I2C_Controller (

.iCLK (iCLK), .iRST_N (iRST_N),

.I2C_CLK (mI2C_CTRL_CLK ), .I2C_EN (i2c_negclk ), .I2C_WDATA ({8'h42, LUT_DATA }), .I2C_SCLK (I2C_SCLK), .I2C_SDAT (I2C_SDAT), .GO (mI2C_GO ), .WR (mI2C_WR ), .ACK (mI2C_ACK ), .END (mI2C_END ),

.I2C_RDATA (I2C_RDATA) );

parameter Read_DATA = 0; parameter SET_OV7670 = 2; always@(*) begin

case(LUT_INDEX )

SET_OV7670 + 0 : LUT_DATA = 16'h3a04;

SET_OV7670 + 1 : LUT_DATA = 16'h40d0;

SET_OV7670 + 2 : LUT_DATA = 16'h1204;

SET_OV7670 + 3 : LUT_DATA = 16'h32b6;

SET_OV7670 + 4 : LUT_DATA = 16'h1713;

SET_OV7670 + 5 : LUT_DATA = 16'h1801;

SET_OV7670 + 6 : LUT_DATA =

16'h1902;

SET_OV7670 + 7 : LUT_DATA = 16'h1a7a;

SET_OV7670 + 8 : LUT_DATA = 16'h030a;

SET_OV7670 + 9 : LUT_DATA = 16'h0c00;

SET_OV7670 + 10 : LUT_DATA = 16'h3e00;

SET_OV7670 + 11 : LUT_DATA = 16'h7000;

SET_OV7670 + 12 : LUT_DATA = 16'h7100;

SET_OV7670 + 13 : LUT_DATA = 16'h7211;

SET_OV7670 + 14 : LUT_DATA = 16'h7300;

SET_OV7670 + 15 : LUT_DATA = 16'ha202;

SET_OV7670 + 16 : LUT_DATA = 16'h1180;

SET_OV7670 + 17 : LUT_DATA = 16'h7a20;

SET_OV7670 + 18 : LUT_DATA = 16'h7b1c;

SET_OV7670 + 19 : LUT_DATA = 16'h7c28;

SET_OV7670 + 20 : LUT_DATA = 16'h7d3c;

SET_OV7670 + 21 : LUT_DATA = 16'h7e55;

SET_OV7670 + 22 : LUT_DATA = 16'h7f68;

SET_OV7670 + 23 : LUT_DATA = 16'h8076;

SET_OV7670 + 24 : LUT_DATA = 16'h8180;

SET_OV7670 + 25 : LUT_DATA = 16'h8288;

SET_OV7670 + 26 : LUT_DATA = 16'h838f;

SET_OV7670 + 27 : LUT_DATA = 16'h8496;

SET_OV7670 + 28 : LUT_DATA = 16'h85a3;

SET_OV7670 + 29 : LUT_DATA = 16'h86af;

SET_OV7670 + 30 : LUT_DATA = 16'h87c4;

SET_OV7670 + 31 : LUT_DATA = 16'h88d7;

SET_OV7670 + 32 : LUT_DATA = 16'h89e8;

SET_OV7670 + 33 : LUT_DATA = 16'h13e0;

SET_OV7670 + 34 : LUT_DATA = 16'h0000;

SET_OV7670 + 35 : LUT_DATA = 16'h1000;

SET_OV7670 + 36 : LUT_DATA = 16'h0d00;

SET_OV7670 + 37 : LUT_DATA = 16'h1428;

SET_OV7670 + 38 : LUT_DATA = 16'ha505;

SET_OV7670 + 39 : LUT_DATA = 16'hab07;

SET_OV7670 + 40 : LUT_DATA = 16'h2475;

SET_OV7670 + 41 : LUT_DATA = 16'h2563;

SET_OV7670 + 42 : LUT_DATA = 16'h26a5;

SET_OV7670 + 43 : LUT_DATA = 16'h9f78;

SET_OV7670 + 44 : LUT_DATA = 16'ha068;

SET_OV7670 + 45 : LUT_DATA = 16'ha103;

SET_OV7670 + 46 : LUT_DATA = 16'ha6df;

SET_OV7670 + 47 : LUT_DATA = 16'ha7df;

SET_OV7670 + 48 : LUT_DATA = 16'ha8f0;

SET_OV7670 + 49 : LUT_DATA = 16'ha990;

SET_OV7670 + 50 : LUT_DATA = 16'haa94;

SET_OV7670 + 51 : LUT_DATA = 16'h13ef;

SET_OV7670 + 52 : LUT_DATA = 16'h0e61;

SET_OV7670 + 53 : LUT_DATA =

16'h0f4b;

SET_OV7670 + 54 : LUT_DATA = 16'h1602;

SET_OV7670 + 55 : LUT_DATA = 16'h1e30;

SET_OV7670 + 56 : LUT_DATA = 16'h2102;

SET_OV7670 + 57 : LUT_DATA = 16'h2291;

SET_OV7670 + 58 : LUT_DATA = 16'h2907;

SET_OV7670 + 59 : LUT_DATA = 16'h330b;

SET_OV7670 + 60 : LUT_DATA = 16'h350b;

SET_OV7670 + 61 : LUT_DATA = 16'h371d;

SET_OV7670 + 62 : LUT_DATA = 16'h3871;

SET_OV7670 + 63 : LUT_DATA = 16'h392a;

SET_OV7670 + 64 : LUT_DATA = 16'h3c78;

SET_OV7670 + 65 : LUT_DATA = 16'h4d40;

SET_OV7670 + 66 : LUT_DATA = 16'h4e20;

SET_OV7670 + 67 : LUT_DATA = 16'h6900;

SET_OV7670 + 68 : LUT_DATA = 16'h6b00;

SET_OV7670 + 69 : LUT_DATA = 16'h7419;

SET_OV7670 + 70 : LUT_DATA = 16'h8d4f;

SET_OV7670 + 71 : LUT_DATA = 16'h8e00;

SET_OV7670 + 72 : LUT_DATA = 16'h8f00;

SET_OV7670 + 73 : LUT_DATA = 16'h9000;

SET_OV7670 + 74 : LUT_DATA = 16'h9100;

SET_OV7670 + 75 : LUT_DATA = 16'h9200;

SET_OV7670 + 76 : LUT_DATA = 16'h9600;

SET_OV7670 + 77 : LUT_DATA = 16'h9a80;

SET_OV7670 + 78 : LUT_DATA = 16'hb084;

SET_OV7670 + 79 : LUT_DATA = 16'hb10c;

SET_OV7670 + 80 : LUT_DATA = 16'hb20e;

SET_OV7670 + 81 : LUT_DATA = 16'hb382;

SET_OV7670 + 82 : LUT_DATA = 16'hb80a;

SET_OV7670 + 83 : LUT_DATA = 16'h4314;

SET_OV7670 + 84 : LUT_DATA = 16'h44f0;

SET_OV7670 + 85 : LUT_DATA = 16'h4534;

SET_OV7670 + 86 : LUT_DATA = 16'h4658;

SET_OV7670 + 87 : LUT_DATA = 16'h4728;

SET_OV7670 + 88 : LUT_DATA = 16'h483a;

SET_OV7670 + 89 : LUT_DATA = 16'h5988;

SET_OV7670 + 90 : LUT_DATA = 16'h5a88;

SET_OV7670 + 91 : LUT_DATA = 16'h5b44;

SET_OV7670 + 92 : LUT_DATA = 16'h5c67;

SET_OV7670 + 93 : LUT_DATA = 16'h5d49;

SET_OV7670 + 94 : LUT_DATA = 16'h5e0e;

SET_OV7670 + 95 : LUT_DATA = 16'h6404;

SET_OV7670 + 96 : LUT_DATA = 16'h6520;

SET_OV7670 + 97 : LUT_DATA = 16'h6605;

SET_OV7670 + 98 : LUT_DATA = 16'h9404;

SET_OV7670 + 99 : LUT_DATA = 16'h9508;

SET_OV7670 + 100 : LUT_DATA =

16'h6c0a;

SET_OV7670 + 101 : LUT_DATA = 16'h6d55;

SET_OV7670 + 102 : LUT_DATA = 16'h6e11;

SET_OV7670 + 103 : LUT_DATA = 16'h6f9f;

SET_OV7670 + 104 : LUT_DATA = 16'h6a40;

SET_OV7670 + 105 : LUT_DATA = 16'h0140;

SET_OV7670 + 106 : LUT_DATA = 16'h0240;

SET_OV7670 + 107 : LUT_DATA = 16'h13e7;

SET_OV7670 + 108 : LUT_DATA = 16'h1500;

SET_OV7670 + 109 : LUT_DATA = 16'h4f80;

SET_OV7670 + 110 : LUT_DATA = 16'h5080;

SET_OV7670 + 111 : LUT_DATA = 16'h5100;

SET_OV7670 + 112 : LUT_DATA = 16'h5222;

SET_OV7670 + 113 : LUT_DATA = 16'h535e;

SET_OV7670 + 114 : LUT_DATA = 16'h5480;

SET_OV7670 + 115 : LUT_DATA = 16'h589e;

SET_OV7670 + 116 : LUT_DATA = 16'h4108;

SET_OV7670 + 117 : LUT_DATA = 16'h3f00;

SET_OV7670 + 118 : LUT_DATA = 16'h7505;

SET_OV7670 + 119 : LUT_DATA = 16'h76e1;

SET_OV7670 + 120 : LUT_DATA = 16'h4c00;

SET_OV7670 + 121 : LUT_DATA = 16'h7701;

SET_OV7670 + 122 : LUT_DATA = 16'h3dc2;

SET_OV7670 + 123 : LUT_DATA = 16'h4b09;

SET_OV7670 + 124 : LUT_DATA = 16'hc960;

SET_OV7670 + 125 : LUT_DATA = 16'h4138;

SET_OV7670 + 126 : LUT_DATA = 16'h5640;

SET_OV7670 + 127 : LUT_DATA = 16'h3411;

SET_OV7670 + 128 : LUT_DATA = 16'h3b02;

SET_OV7670 + 129 : LUT_DATA = 16'ha489;

SET_OV7670 + 130 : LUT_DATA = 16'h9600;

SET_OV7670 + 131 : LUT_DATA = 16'h9730;

SET_OV7670 + 132 : LUT_DATA = 16'h9820;

SET_OV7670 + 133 : LUT_DATA = 16'h9930;

SET_OV7670 + 134 : LUT_DATA = 16'h9a84;

SET_OV7670 + 135 : LUT_DATA = 16'h9b29;

SET_OV7670 + 136 : LUT_DATA = 16'h9c03;

SET_OV7670 + 137 : LUT_DATA = 16'h9d4c;

SET_OV7670 + 138 : LUT_DATA = 16'h9e3f;

SET_OV7670 + 139 : LUT_DATA = 16'h7804;

SET_OV7670 + 140 : LUT_DATA = 16'h7901;

SET_OV7670 + 141 : LUT_DATA = 16'hc8f0;

SET_OV7670 + 142 : LUT_DATA = 16'h790f;

SET_OV7670 + 143 : LUT_DATA = 16'hc800;

SET_OV7670 + 144 : LUT_DATA = 16'h7910;

SET_OV7670 + 145 : LUT_DATA = 16'hc87e;

SET_OV7670 + 146 : LUT_DATA = 16'h790a;

SET_OV7670 + 147 : LUT_DATA =

16'hc880;

SET_OV7670 + 148 : LUT_DATA = 16'h790b;

SET_OV7670 + 149 : LUT_DATA = 16'hc801;

SET_OV7670 + 150 : LUT_DATA = 16'h790c;

SET_OV7670 + 151 : LUT_DATA = 16'hc80f;

SET_OV7670 + 152 : LUT_DATA = 16'h790d;

SET_OV7670 + 153 : LUT_DATA = 16'hc820;

SET_OV7670 + 154 : LUT_DATA = 16'h7909;

SET_OV7670 + 155 : LUT_DATA = 16'hc880;

SET_OV7670 + 156 : LUT_DATA = 16'h7902;

SET_OV7670 + 157 : LUT_DATA = 16'hc8c0;

SET_OV7670 + 158 : LUT_DATA = 16'h7903;

SET_OV7670 + 159 : LUT_DATA = 16'hc840;

SET_OV7670 + 160 : LUT_DATA = 16'h7905;

SET_OV7670 + 161 : LUT_DATA = 16'hc830;

SET_OV7670 + 162 : LUT_DATA = 16'h7926;

SET_OV7670 + 163 : LUT_DATA = 16'h0903;

SET_OV7670 + 164 : LUT_DATA = 16'h3b42;

default : LUT_DATA = 0;

endcase

end

endmodule

`timescale 1ns/1ns

module I2C_OV7670_Config

(

input [7:0] LUT_INDEX,

output reg [15:0] LUT_DATA

);

parameter Read_DATA = 0; parameter SET_OV7670 = 2; always@(*)

begin

case(LUT_INDEX)

Read_DATA + 0 : LUT_DATA = {8'h0A, 8'h76};

Read_DATA + 1 : LUT_DATA = {8'h0B, 8'h73};

SET_OV7670 + 0 : LUT_DATA = 16'h3a04;

SET_OV7670 + 1 : LUT_DATA = 16'h40d0;

SET_OV7670 + 2 : LUT_DATA = 16'h1204;

SET_OV7670 + 3 : LUT_DATA = 16'h32b6;

SET_OV7670 + 4 : LUT_DATA = 16'h1713;

SET_OV7670 + 5 : LUT_DATA = 16'h1801;

SET_OV7670 + 6 : LUT_DATA = 16'h1902;

SET_OV7670 + 7 : LUT_DATA = 16'h1a7a;

SET_OV7670 + 8 : LUT_DATA = 16'h030a;

SET_OV7670 + 9 : LUT_DATA = 16'h0c00;

SET_OV7670 + 10 : LUT_DATA = 16'h3e00;

SET_OV7670 + 11 : LUT_DATA = 16'h7000;

SET_OV7670 + 12 : LUT_DATA = 16'h7100;

SET_OV7670 + 13 : LUT_DATA = 16'h7211;

SET_OV7670 + 14 : LUT_DATA = 16'h7300;

SET_OV7670 + 15 : LUT_DATA = 16'ha202;

SET_OV7670 + 16 : LUT_DATA = 16'h1180;

SET_OV7670 + 17 : LUT_DATA = 16'h7a20;

SET_OV7670 + 18 : LUT_DATA = 16'h7b1c;

SET_OV7670 + 19 : LUT_DATA = 16'h7c28;

本文来源:https://www.bwwdw.com/article/t8rl.html

Top