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

企业网站标签页是什么网页编辑布局在线

企业网站标签页是什么,网页编辑布局在线,网站建设公司广告,dw网站设计模板1.OV5640简介 OV5640是OV#xff08;OmniVision#xff09;公司推出的一款CMOS图像传感器#xff0c;实际感光阵列为#xff1a;2592 x 1944#xff08;即500w像素#xff09;#xff0c;该传感器内部集成了图像出炉的电路#xff0c;包括自动曝光控制#xff08;AEC…1.OV5640简介 OV5640是OVOmniVision公司推出的一款CMOS图像传感器实际感光阵列为2592 x 1944即500w像素该传感器内部集成了图像出炉的电路包括自动曝光控制AEC、自动白平衡 AWB 等。同时该传感器支持LED补光、 MIPI移动产业处理器接口多用于手机等输出接口和DVP数字视频并行在设计HDMI显示时就用的这个输出接口选择、 ISP图像信号处理以及自动聚焦控制AFC等功能。 2.OV5640工作原理 OV5640的功能框图如上可以看到时序发生器和系统控制逻辑timing generator and system control logic控制着感光阵列image array、放大器AMP、AD转换10bit以及输出外部时序信号PCLK和行场同步信号等。 感光阵列输出模拟信号经过AMP增强信号强度进入到AD转换器转换成数字信号并经过ISP进行相关图像处理最终输出10位DVP数据流或者MIPI数据流。 AMP和ISP等都是由控制寄存器进行控制而配置寄存器的接口时序就是使用的SCCB由于OV5640寄存器较多OV5640寄存器的地址为16位所以SCCB协议中的寄存器地址为16位。 OV5640摄像头引脚功能描述如下表所示 注意XCLK引脚它跟 PCLK是完全不同的XCLK是用于驱动个传感器芯片的时钟信号是外部输入到OV5640的信号而 PCLK是OV5640输出数据时的同步信号它是由OV5640输出的信号。XCLK可以外接晶振或由外部控制器提供。 OV5640的输出模式如下图所示我们可以通过对其寄存器的配置来控制不同的工作模式。 3.OV5640寄存器功能介绍 OV5640的寄存器较多对于其它寄存器的描述可以参OV5640的数据手册。但是OV5640的数据手册并没有提供全部的寄存器描述 而大多数必要的寄存器配置在OV5640的软件应用手册《OV5640 Camera Module Software Application Notes》中可以找到其中还有相关初始化例程。这里我们只介绍几个关键的寄存器配置。 输出模式设置如下图所示可以通过配置0x4300这个寄存器控制输出的像素模式包括REG565、YUV422等常用模式。设置输出模式为RGB565时还可以控制输出。 输出像素设置则通过0x3808~0x380b进行控制方法也非常简单只需要将期望得到的分辨率转换为16进制数据再分别写入四个寄存器即可。举个例子我想要的分辨率为960x540960转换为16进制数据为3c0540转换为16进制数据为21c因此我需要向0x3808中写入03向0x3809中写入c0向0x380a中写入02向0x380b中写入1c。 OV5640的像素时钟计算如图所示 通过图可以看出PCLK是经过图中8个步骤之后得到的频率以下逐步计算得到PCLK。 OV5640要求输入的时钟频率为6-27MHz,一般情况下输入24MHz在本次计算中也以24MHz为输入频率 输入时钟首先经过pre-divider进行分频分频系数由3037[3:0]确定在本次计算中3037[3:0]为3故经过分频之后的输出为24/38MHz 经过pre-divider分频后需要给分频后的时钟做一次倍频乘法因子为3036[6:0]0x69105经过倍频后的时钟频率为8MHz*105840MHz; Sys divider0分频分频系数为0x3035[7:4]在demo中的值为1故没有进行分频840MHz/1840MHz; PLL R divider分频如果0x3037[4]为高电平则进行2分频否则不分频在demo中3037[4]为1故二分频840MHz/2420MHz; BIT divider分频分频系数为0x3034[3:0]如果是8则是2分频如果是A则是2.5分频如果是其他则为1分频在demo中0x3034[3:0]为a故需要进行2.5分频420MHz/2.5168MHz; PCLK divider分频, 分频系数为0x3108[5:4],00:1分频01:2分频10:4分频11:8分频在demo中0x3108[5:4]2’b00,故需要进行1分频168MHz/1168MHz P divider分频如果是mipi2 lane,则分频系数是0x3035[3:0],如果是DVP 接口则分频系数为2*0x3035[3:0]2在demo中0x3035[3:0]1故在此是2分频168MHz/284MHz Scale divider分频分频系数为0x3824[4:0],在demo中0x3824[4:0]2故需要进行2分频84MHz/421MHz。 通过以上分析可以看出在demo中输入时钟为24MHz时输出时钟为21MHz。 OV5640 的图像输出帧率可以通过修改地址为 0x3035、0x3036、0x3037 的寄存器的值来修改该寄存器实际上是设置了 OV5640 片上 PLL 的各种分频和倍频系数例如在典型配置模式下当输入时钟 XCLK 的信号频率为 24MHz 时 设置 0x3035 寄存器的值为 0x21 可设置输出帧率为30fps设为0x41可设置输出帧率为15fps、设为0x81可设置输出帧率为7.5fps。 4.SCCB协议 外部控制器对 OV5640 寄存器的配置参数是通过 SCCB 总线传输过去的而 SCCB 总线跟 I2C 十分类似。 SCCB 的起始、停止信号及数据有效性 起始信号 在 SCL图中为 SIO_C 为高电平时 SDA(图中为 SIO_D)出现一个下降沿则 SCCB 开始传输。停止信号在 SCL 为高电平时 SDA 出现一个上升沿则 SCCB 停止传输。数据有效性除了开始和停止状态 在数据传输过程中当 SCL 为高电平时必须保证 SDA 上的数据稳定也就是说 SDA 上的电平变换只能发生在 SCL 为低电平的时候SDA 的信号在 SCL 为高电平时被采集。 在 SCCB 协议中定义的读写操作与 I2C 也是一样的只是换了一种说法。它定义了两种写操作即三步写操作和两步写操作。三步写操作可向从设备的一个目的寄存器中写入数据见下图。在三步写操作中第一阶段发送从设备的ID地址W标志(等于 I2C 的设备地址7位设备地址读写方向标志)第二阶段发送从设备目标寄存器的 8 位地址第三阶段发送要写入寄存器的 8 位数据。图中的“X”数据位可写入 1 或 0对通讯无影响。而在i2c协议中“X”为从机给主机的响应若主机未收到从机的响应信号则无法发送后面的数据。 而两步写操作没有第三阶段即只向从器件传输了设备 IDW 标志和目的寄存器的地址见下图 。两步写操作是用来配合后面的读寄存器数据操作的它与读操作一起使用实现i2c的复合过程。 两步读操作它用于读取从设备目的寄存器中的数据见下图。在第一阶段中发送从设备的设备 IDR 标志(设备地址读方向标志)和自由位在第二阶段中读取寄存器中的8 位数据和写 NA 位(非应答信号)。 由于两步读操作没有确定目的寄存器的地址所以在读操作前必需有一个两步写操作以提供读操作中的寄存器地址。 总的来说i2c协议与SCCB协议的主要区别如下 .SCCB的应答位称为X表示“dont care”而i2c应答位称为ACK。 .SCCB只能单次读而i2c除了单次读还支持连续读。 .SCCB读操作中间有stop而i2c读操作中间可以有stop也可以不需要stop。 5.程序设计 OV5640的整体设计框图如图总共包含三个模块i2c驱动模块、寄存器配置模块和图像采集模块。 timescale 1ns / 1psmodule ov5640_top#(parameter DEVICE_ADDR 7b0111_100 , //i2c从机地址parameter SYS_CLK_FREQ 27d100_000_000 , //系统时钟频率parameter I2C_FREQ 19d400_000, //i2c时钟频率400kparameter PIC_CNT_MAX 4d10, //舍弃前10帧数据parameter REG_NUM 8d0250, //需配置寄存器个数parameter CNT_WAIT_MAX 15d20000 //寄存器配置等待时间)(input clk, //系统时钟100MHzinput rst_n, //系统复位input pclk, //ov5640工作时钟input hsync, //行同步信号input vsync, //场同步信号input [7:0] ov5640_din, //ov5640输入数据input init_done, //初始化完成信号output wire ov5640_dout_en, //输出图像数据使能信号output wire[15:0] ov5640_dout, //输出16位图像数据output wire cfg_done, //寄存器配置完成信号 inout wire sda, //i2c数据总线output wire scl //i2c时钟总线);wire cfg_1_done; //单个寄存器配置完成信号wire cfg_start; //开始配置信号wire [23:0] cfg_data; //寄存器地址写入数据wire i2c_clk; //i2c驱动时钟 ov5640_data #(.PIC_CNT_MAX ( 4d10 ))u_ov5640_data (.rst_n ( rst_n init_done ),.pclk ( pclk ),.hsync ( hsync ),.vsync ( vsync ),.ov5640_din ( ov5640_din ),.ov5640_dout_en ( ov5640_dout_en ),.ov5640_dout ( ov5640_dout ) );ov5640_cfg #(.REG_NUM ( 8d0250 ),.CNT_WAIT_MAX ( 15d20000 ))u_ov5640_cfg (.clk ( i2c_clk ),.rst_n ( rst_n ),.cfg_1_done ( cfg_1_done ),.cfg_start ( cfg_start ),.cfg_data ( cfg_data ),.cfg_done ( cfg_done ) );i2c_drive #(.DEVICE_ADDR ( 7b0111_100 ),.SYS_CLK_FREQ ( 27d100_000_000 ),.I2C_FREQ ( 19d400_000 ))u_i2c_drive (.sys_clk ( clk ),.sys_rst_n ( rst_n ),.i2c_rw ( 1b0 ),.i2c_start ( cfg_start ),.i2c_num ( 1b1 ),.i2c_addr ( cfg_data[23:8] ),.i2c_data_w ( cfg_data[7:0] ),.i2c_clk ( i2c_clk ),.i2c_end ( cfg_1_done ),.i2c_data_r ( i2c_data_r ),.scl ( scl ),.sda ( sda ) );endmodule 5.1图像采集模块 模块输入信号有5路输入时钟信号为OV5640_pclk由OV5640摄像头自带晶振产生并传入频率24MHz作为模块工作时钟复位信号rst_n低电平有效OV5640_vsync为摄像头采集图像的场同步信号可类比与VGA场同步信号只在同步阶段为高电平其他时刻保持低电平OV5640_hsync为行有效图像使能信号信号只有采集图像行有效显示区域为高电平其他时刻为低电平最后的OV5640_data为摄像头采集到的图像数据要注意的是OV5640_data位宽为8bit采集的图像数据分两次传入模块先传入图像数据高字节下个时钟周期传入低字节。 系统上电后摄像头刚采集的前几帧图像数据不太稳定要先舍弃前10帧图像之后的图像才能用于显示。为了舍弃前10帧图像我们需要声明几个变量。首先要舍弃前10帧图像需要一个计数器来计数声明计数器pic_cnt对输入图像帧数进行计数接下来就要考虑以什么为标志进行计数这时我们想到每帧图像的传入帧同步信号必不可少那么声明帧同步信号寄存信号vsync_r此信号延后帧同步信号一个时钟周期利用两信号产生帧同步信号下降沿pic_flag作为帧计数器pic_cnt的计数标志信号该信号每拉高一次计数器自加1声明帧有效信号pic_valid当计数器计数到第10帧pic_flag为高电平将帧有效信号拉高并始终保持高电平。 前面说到像素点图像信息并不是在一个时钟周期传入而是在第一个时钟周期传入高8位下一个时钟周期传入低8位所以要正确显示图像就需要对传入图像数据进行拼接。实现数据拼接就需要声明若干变量。需要先声明一个寄存器对图像数据的高字节进行数据缓存待低字节数据传入时将图像数据进行拼接。首先声明寄存器OV5640_din_r对高字节数据进行缓存声明标志信号data_flag控制数据缓存与拼接在hsync信号有效时标志着输入图像数据有效data_flag不断取反当其为低电平时对高字节数据进行缓存当其为高电平时对数据进行拼接。将拼接后的数据赋值给OV_5640_dout_r。 timescale 1ns / 1psmodule ov5640_data#(parameter PIC_CNT_MAX 4d10 //舍弃前10帧数据)(input rst_n, //系统复位input pclk, //ov5640工作时钟input hsync, //行同步信号input vsync, //场同步信号input [7:0] ov5640_din, //ov5640输入数据output wire ov5640_dout_en, //输出图像数据使能信号output wire[15:0] ov5640_dout //输出16位图像数据);wire pic_flag; //帧图像标志信号拉高一次标志一帧图像传输完成reg vsync_r; //场同步信号打拍reg [7:0] ov5640_din_r; //暂存输入8位数据reg [15:0] ov5640_dout_r; //暂存输出16位数据reg pic_valid; //帧图像有效信号 reg [9:0] pic_cnt; //帧图像计数器reg data_flag; //图像拼接标志reg data_flag_r; //图像拼接标志打拍always (posedge pclk or negedge rst_n) beginif(!rst_n)vsync_r 1b0;else vsync_r vsync;endalways (posedge pclk or negedge rst_n) beginif(!rst_n)pic_cnt 10d0;else if(pic_cnt PIC_CNT_MAX pic_flag 1b1)pic_cnt pic_cnt 1b1;elsepic_cnt pic_cnt;endalways (posedge pclk or negedge rst_n) beginif(!rst_n)pic_valid 1b0;else if(pic_cnt PIC_CNT_MAX pic_flag 1b1)pic_valid 1b1;elsepic_valid pic_valid;endalways (posedge pclk or negedge rst_n) beginif(!rst_n)begindata_flag 1b0;ov5640_din_r 8d0;ov5640_dout_r 16d0;endelse if(hsync)begindata_flag ~data_flag;ov5640_din_r ov5640_din;ov5640_dout_r ov5640_dout_r;if(data_flag)ov5640_dout_r {ov5640_din_r,ov5640_din}; //像素数据拼接else ov5640_dout_r ov5640_dout_r;endelse begindata_flag 1b0;ov5640_din_r 8d0;ov5640_dout_r ov5640_dout_r;endendalways (posedge pclk or negedge rst_n) beginif(!rst_n)data_flag_r 1b0;elsedata_flag_r data_flag;endassign pic_flag (vsync 1b1 vsync_r 1b0) ? 1b1 : 1b0;assign ov5640_dout (pic_valid 1b1) ? ov5640_dout_r : 16d0;assign ov5640_dout_en (pic_valid 1b1) ? data_flag : 1b0;endmodule5.2SCCB协议 由于SCCB协议与i2c协议非常相似因此我们可以将i2c协议稍加改动便可进行寄存器配置利用之前的i2c驱动模块将应答信号直接拉高即可。然后还要将器件地址改成OV5640的器件地址即0111_100。 module i2c_drive #(parameter DEVICE_ADDR 7b0111_100 , //i2c从机地址parameter SYS_CLK_FREQ 27d100_000_000 , //系统时钟频率parameter I2C_FREQ 19d400_000 //i2c时钟频率400k ) ( //系统接口input sys_clk , //输入系统时钟,100MHzinput sys_rst_n , //输入复位信号,低电平有效 //I2C时序控制接口 input i2c_rw , //读写使能信号----1:读0写input i2c_start , //i2c开始信号input i2c_num , //i2c字节地址字节数----116位08位input [15:0] i2c_addr , //i2c字节地址input [7:0] i2c_data_w , //写入i2c数据output reg i2c_clk , //i2c驱动时钟output reg i2c_end , //i2c一次读/写操作完成output reg [7:0] i2c_data_r , //i2c读取数据 //I2C物理接口 output reg scl , //输出至i2c设备的串行时钟信号sclinout wire sda //输出至i2c设备的串行数据信号sda ); //状态机定义 localparam IDLE 4d0, //初始化状态START1 4d1, //发送开始信号状态1SEND_D_ADDR_W 4d2, //设备地址写入状态 控制写ACK1 4d3, //等待从机响应信号1SEND_R_ADDR_H 4d4, //发送寄存器地址高8位ACK2 4d5, //等待从机响应信号2SEND_R_ADDR_L 4d6, //发送寄存器地址低8位ACK3 4d7, //等待从机响应信号3WR_DATA 4d08, //写数据状态ACK4 4d09, //应答状态4START2 4d10, //发送开始信号状态12SEND_D_ADDR_R 4d11, //设备地址写入状态 控制读ACK5 4d12, //应答状态5RD_DATA 4d13, //读数据状态NACK 4d14, //非应答状态STOP 4d15; //结束状态//根据系统频率及IIC驱动频率计算分频系数 localparam CLK_DIVIDE SYS_CLK_FREQ / I2C_FREQ 2d3; //reg定义 reg [9:0] clk_cnt ; //分频时钟计数器最大计数1023 reg [3:0] cur_state ; //状态机现态 reg [3:0] next_state ; //状态机次态 reg i2c_clk_cnt_en ; //驱动时钟计数使能 reg [1:0] i2c_clk_cnt ; //驱动计数时钟方便在SCL的高电平中间采集数据和在SCL的低电平中间变化数据 reg sda_out ; //IIC总线三态输出 reg sda_en ; //IIC总线三态门使能 reg [2:0] bit_cnt ; //接收数据个数计数器 reg ack_flag ; //应答信号标志 reg [7:0] i2c_data_r_temp ; //读取数据寄存器暂存读到的数据//wire定义 wire sda_in ; //IIC总线三态输入 wire [7:0] addr_r ; //器件地址读控制位 wire [7:0] addr_w ; //器件地址写控制位assign addr_r {DEVICE_ADDR,1b1}; //器件地址读控制位 assign addr_w {DEVICE_ADDR,1b0}; //器件地址写控制位//双向口处理 assign sda_in sda; assign sda sda_en ? sda_out : 1bz;//scl4分频时钟IIC驱动时钟i2c_clk方便操作对采集数据及变化数据操作 always(posedge sys_clk or negedge sys_rst_n)beginif(~sys_rst_n)begini2c_clk 1b0;clk_cnt 10d0;endelse if(clk_cnt CLK_DIVIDE - 1b1)begini2c_clk ~i2c_clk;clk_cnt 10d0; endelse begini2c_clk i2c_clk;clk_cnt clk_cnt 1d1; end end//i2c_clk计数器使能 always(posedge i2c_clk or negedge sys_rst_n)beginif(!sys_rst_n)i2c_clk_cnt_en 1b0;//只有在发送完了结束信号或者没有接收到IIC开始传输信号的初始状态下才不停对i2c_clk计数器复位使能为0else if ((cur_state STOP i2c_clk_cnt 2d3 bit_cnt 2d3)||(cur_state IDLE !i2c_start ))i2c_clk_cnt_en 1b0; else if(i2c_start) i2c_clk_cnt_en 1b1; //接收到开始信号代表一次传输开始计数器开始计数else i2c_clk_cnt_en i2c_clk_cnt_en; //其他时候保持不变 end//i2c_clk_cnt计数器 always(posedge i2c_clk or negedge sys_rst_n)beginif(!sys_rst_n)i2c_clk_cnt 2d0;else if(i2c_clk_cnt_en) i2c_clk_cnt i2c_clk_cnt 1d1; //使能信号有效计数器开始计数else i2c_clk_cnt 2d0; //使能信号无效计数器清零 end//三段式状态机第一段 always(posedge i2c_clk or negedge sys_rst_n)beginif(~sys_rst_n)cur_state IDLE;elsecur_state next_state; end//三段式状态机第二段 always(*)beginnext_state IDLE;case(cur_state)IDLE:if(i2c_start)next_state START1; //接收到开始信号跳转到发送起始信号状态elsenext_state IDLE;START1:if(i2c_clk_cnt 2d3) //i2c_clk 计数到最大值3跳转到发送器件地址写标志位状态next_state SEND_D_ADDR_W;elsenext_state START1;SEND_D_ADDR_W:if(i2c_clk_cnt 2d3 bit_cnt 3d7) //发送了8位地址后跳转到从机响应状态next_state ACK1; elsenext_state SEND_D_ADDR_W; ACK1:if(ack_flag i2c_clk_cnt 2d3)begin //响应标志有效//根据地址状态位判断是16位地址还是8位地址从而跳转到不同状态if(i2c_num) //16位地址next_state SEND_R_ADDR_H; //跳转到寄存器高8位地址发送状态else //8位地址next_state SEND_R_ADDR_L; //跳转到寄存器低8位地址发送状态end else if(i2c_clk_cnt 2d3) //响应无效或者响应不及时则跳转回初始状态next_state IDLE;else next_state ACK1;SEND_R_ADDR_H: if(i2c_clk_cnt 2d3 bit_cnt 3d7) //发送了寄存器高8位地址后跳转到从机响应状态next_state ACK2;else next_state SEND_R_ADDR_H;ACK2:if(ack_flag i2c_clk_cnt 2d3) next_state SEND_R_ADDR_L; //响应标志有效则跳转到寄存器低8位地址发送状态else if(i2c_clk_cnt 2d3) //响应无效或者响应不及时则跳转回初始状态next_state IDLE; elsenext_state ACK2;SEND_R_ADDR_L:if(i2c_clk_cnt 2d3 bit_cnt 3d7) //发送了寄存器低8位地址后跳转到从机响应状态next_state ACK3;elsenext_state SEND_R_ADDR_L;ACK3:if(ack_flag i2c_clk_cnt 2d3)begin //响应标志有效 if(i2c_rw) //读状态next_state START2; //跳转到第二次发送起始信号else //写状态next_state WR_DATA; //跳转到写数据状态endelse if(i2c_clk_cnt 2d3) next_state IDLE; //响应无效或者响应不及时则跳转回初始状态elsenext_state ACK3;START2:if(i2c_clk_cnt 2d3) next_state SEND_D_ADDR_R; //第二次发送起始信号后跳转到发送器件地址读标志位状态elsenext_state START2;SEND_D_ADDR_R:if(i2c_clk_cnt 2d3 bit_cnt 3d7) //发送完了8位地址后跳转到从机响应状态next_state ACK5; elsenext_state SEND_D_ADDR_R; ACK5:if(ack_flag i2c_clk_cnt 2d3) next_state RD_DATA; //响应标志有效则跳转到读数据状态else if(i2c_clk_cnt 2d3) next_state IDLE; //响应无效或者响应不及时则跳转回初始状态else next_state ACK5; RD_DATA:if(i2c_clk_cnt 2d3 bit_cnt 3d7) //接收完了8位数据后跳转到主机发送非响应状态next_state NACK;elsenext_state RD_DATA; NACK:if(i2c_clk_cnt 2d3) next_state STOP; //发送完了非响应信号后跳转到发送结束信号状态elsenext_state NACK; WR_DATA:if(bit_cnt 3d7 i2c_clk_cnt 2d3) next_state ACK4; //写完了8位数据后跳转到从机响应状态elsenext_state WR_DATA;ACK4:if(ack_flag i2c_clk_cnt 2d3)next_state STOP; //响应标志有效则跳转到发送结束信号状态else if(i2c_clk_cnt 2d3)next_state IDLE; //响应无效或者响应不及时则跳转回初始状态elsenext_state ACK4;STOP:if(bit_cnt 2d3 i2c_clk_cnt 2d3) //结束信号发送完毕这里还预留了2个周期跳转到初始状态等待下一次传输开始信号next_state IDLE;elsenext_state STOP; default:next_state IDLE;endcase end//三段式状态机第三段 always(posedge i2c_clk or negedge sys_rst_n)beginif(~sys_rst_n)begin //初始状态sda_en 1b1;sda_out 1b1;bit_cnt 3d0;i2c_end 1b0;i2c_data_r 8d0;i2c_data_r_temp 8d0;endelse begini2c_end 1b0;case(cur_state)IDLE:beginsda_en 1b1; //控制总线sda_out 1b1; //拉高总线end START1:beginif(i2c_clk_cnt 2d3)begin //发送完了开始信号if(addr_w[7])begin //如果器件地址的最高位为1则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //如果器件地址的最高位为0则提前拉低总线sda_en 1b1;sda_out 1b0; endendelse begin //还没发送完开始信号则保持低电平sda_en 1b1;sda_out 1b0; endend SEND_D_ADDR_W:beginif(bit_cnt 3d7)begin if(i2c_clk_cnt 2d3)begin //发送了8个数据器件地址写标志位bit_cnt 3d0; //发送数据计数器清零sda_en 1b0; //释放总线endendelse if(i2c_clk_cnt 2d3)begin //发送完了一个数据bit_cnt bit_cnt 1d1; //发送数据计数器清零sda_en 1b1; //控制总线sda_out addr_w[6-bit_cnt]; //总线依次串行输出地址endendACK1:beginif(i2c_clk_cnt 2d3)begin if(i2c_num)begin //如果器件地址为16位if(i2c_addr[15])begin //如果器件地址的16位为1则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //如果器件地址的16位为0则提前拉低总线sda_en 1b1;sda_out 1b0; endendelse begin //如果器件地址为8位if(i2c_addr[7])begin //如果器件地址的8位为1则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //如果器件地址的8位为0则提前拉低总线sda_en 1b1;sda_out 1b0; endend end endSEND_R_ADDR_H:beginif(bit_cnt 3d7)begin //8个数据发送完了if(i2c_clk_cnt 2d3)beginbit_cnt 3d0; //发送数据计数器清零sda_en 1b0; //释放总线endendelse if(i2c_clk_cnt 2d3)beginbit_cnt bit_cnt 1d1; //发送数据计数器清零sda_en 1b1; //控制总线sda_out i2c_addr[14-bit_cnt];//总线依次串行输出地址end endACK2:beginif(i2c_clk_cnt 2d3)beginif(i2c_addr[7])begin //下一个要发送数据的首个数据为高则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //下一个要发送数据的首个数据为低则提前拉低总线sda_en 1b1;sda_out 1b0; end endend SEND_R_ADDR_L:begin if(bit_cnt 3d7)begin //8个数据发送完了if(i2c_clk_cnt 2d3)beginbit_cnt 3d0; //发送数据计数器清零sda_en 1b0; //释放总线endendelse if(i2c_clk_cnt 2d3)beginbit_cnt bit_cnt 1d1; //发送数据计数器清零sda_en 1b1; //控制总线sda_out i2c_addr[6-bit_cnt]; //总线依次串行输出地址end endACK3:beginif(!i2c_rw)begin //是写操作if(i2c_clk_cnt 2d3)beginif(i2c_data_w[7])begin //下一个要发送数据的首个数据为高则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //下一个要发送数据的首个数据为低则提前拉低总线sda_en 1b1;sda_out 1b0; end end endelse begin //是读操作if(i2c_clk_cnt 2d3)begin //提前拉高总线进入再次发送起始信号状态sda_en 1b1;sda_out 1b1; endelse beginsda_en 1b1;sda_out 1b0; end endendSTART2:beginif(i2c_clk_cnt 2d1)begin //拉低总线sda_en 1b1;sda_out 1b0; endelse if(i2c_clk_cnt 2d3)beginif(addr_r[7])begin //下一个要发送数据的首个数据为高则提前拉高总线sda_en 1b1;sda_out 1b1; endelse begin //下一个要发送数据的首个数据为低则提前拉低总线sda_en 1b1;sda_out 1b0; end endendSEND_D_ADDR_R:beginif(bit_cnt 3d7)begin //8个数据发送完了if(i2c_clk_cnt 2d3)beginbit_cnt 3d0; //发送数据计数器清零sda_en 1b0; //释放总线endendelse if(i2c_clk_cnt 2d3)beginbit_cnt bit_cnt 1d1; //发送数据计数器清零sda_en 1b1; //控制总线sda_out addr_r[6-bit_cnt]; //总线依次串行输出地址endend ACK5:sda_en 1b0; //下一个状态是接收数据所以释放总线RD_DATA:if(i2c_clk_cnt 2d3)beginif(bit_cnt 3d7)begin //接收了8个数据bit_cnt 3d0; //发送数据计数器清零sda_en 1b1; //控制总线sda_out 1b1; //拉高总线为了下一步发送非响应信号i2c_data_r i2c_data_r_temp; //将读取的数据输出 endelse begin //数据还未接收完毕 bit_cnt bit_cnt 3d1; end endelse if(i2c_clk_cnt 2d1)begin //在SCL的中间采集数据i2c_data_r_temp[7-bit_cnt] sda_in;//将总线上的数据依次串行采集 end NACK:if(i2c_clk_cnt 2d3)begin sda_en 1b1; //控制总线sda_out 1b0; //拉高总线 end WR_DATA:if(bit_cnt 3d7)begin //写完了8个数据if(i2c_clk_cnt 2d3)beginbit_cnt 3d0; //发送数据计数器清零sda_en 1b0; //释放总线endendelse if(i2c_clk_cnt 2d3)begin //没有写完8个数据bit_cnt bit_cnt 1d1; //发送数据计数器累加sda_en 1b1;sda_out i2c_data_w[6-bit_cnt]; //依次输出数据end ACK4:if(i2c_clk_cnt 2d3)beginsda_en 1b1; //控制总线sda_out 1b0; //拉低总线为了下一步发送终止信号 end STOP: if(i2c_clk_cnt 2d2 bit_cnt 2d0)begin //拉高信号作为终止信号 sda_en 1b1;sda_out 1b1; endelse if( i2c_clk_cnt 2d3 )beginif(bit_cnt 2d3)begin bit_cnt 2d0;i2c_end 1b1; //发送完了终止信号且延时一段时间发送IIC结束信号endelsebit_cnt bit_cnt 1d1;enddefault:;endcaseend end//i2c时钟生成 always(posedge i2c_clk or negedge sys_rst_n)beginif(~sys_rst_n)scl 1b1;else if(cur_state ! STOP)beginif(i2c_clk_cnt 2d2)scl 1b0;else if(i2c_clk_cnt 2d0)scl 1b1; endelse scl 1b1; end //从机响应信号标志 always(posedge i2c_clk or negedge sys_rst_n)beginif(~sys_rst_n)ack_flag 1b0;else case(cur_state)ACK1,ACK2,ACK3,ACK4,ACK5://if(i2c_clk_cnt 2d1 !sda_in) //在从机响应状态正确接收到了从机发送的响应信号则拉高响应标志ack_flag 1b1;//else if(i2c_clk_cnt 2d3) // ack_flag 1b0;default:ack_flag 1b0;endcase endendmodule 6.仿真结果 总体仿真如上图所示可以看到每一帧图像传输完成场同步信号拉高一次并且前10帧图像会被舍弃。 摄像头数据传输仿真如上图所示使能信号每翻转一次进行一次数据拼接。 寄存器配置如上图所示不需要从机发送应答信号。 7.问题总结 本次代码还未进行板级验证先说一说仿真遇到的问题其他问题后续再进行补充首先就是方针过程中出现了如下图所示的情况。行同步信号和场同步信号出现了未知态原因是有两个驱动我的testbench是自动生成的因此开始会将两个信号的值赋0后面我再对其进行赋值就会出现未知态。还有就是寄存器的配置在网上找了很多资料都没有一个确定的答案可能文中的说法也会有错欢迎大家批评指正代码参考正点原子。
http://www.hkea.cn/news/14395850/

相关文章:

  • 网站建设合同用贴印花税吗南宁企业门户网站建设价格
  • 网站 工信部备案 收回别人抄袭网站设计怎么办
  • 织梦做仿站时 为何会发生本地地址跳转网站地址大连网站制作机构
  • 企业做网站哪家公司好跨境电商知名网站建设
  • 兰州企业建设网站软文的概念
  • 可视化响应式网站建设物流网站大全
  • 成立公司有什么好处和坏处seo狂人
  • 最好的flash网站seo分析网站
  • 设计教学网站推荐设计师网络用语
  • 企业网站内使用了哪些网络营销方式58同城商业后台如何做网站
  • ftp给网站上传图片后图片的链接地址被改了制作网站站用的软件
  • 取名网站开发php wordpress开发教程
  • 手机网站后台Sensei wordpress插件
  • 手机购物网站建设辽宁鞍山网站建设公司
  • 做球服的网站有哪些任经理 徐州网站建设
  • 做游戏网站董明珠营收1500亿
  • 长沙在线建站模板亲情网络广告推广怎么做
  • 返利网 网站开发做互联网产品和运营必备的网站
  • 注册网络科技公司需要多少钱哈尔滨seo优化培训
  • 网络运营商wordpress标题title优化代码
  • 响应式网站的几种尺寸空气源热泵热水器网站建设
  • 大良网站智能推广如何网站搭建北京
  • 可以用自己的电脑做网站吗网站建设登录界面代码
  • 深圳网站建设网站制作网站设计在家做网站怎么赚钱
  • 防城港网站建设昆明建设网站的公司
  • 宝安网站建设制作青海省教育厅门户网站
  • 做美食网站的特点怎样建网站赚钱
  • 想找人做网站扬中网站建设流程
  • 二级单位网站建设青岛seo关键词
  • 最差网站设计云南工程建设总承包公司官网