基于FPGA的图像采集之二 GEN_FRAME(成帧)模块

距离上次的博客已经有段时间了,这写些日子一直在调SDRAM的模块以及文档的书写,SDRAM的子模块比较多,包括init(初始化模块)、refresh(刷新模块)、write(写模块)、read(读模块),使用起来相比之前的USB控制模块、今天的GEN_FRAME(以下均表示为成帧模块)都稍显复杂一些。好了,接下来介绍我们今天的主角:成帧模块。成帧模块的作用有两个:

1.完成时钟域的转换:将缓存到sdram中的数据读出发送给USB,sdram芯片可以达到的时钟频率范围大致为24MHZ-256MHZ,该时钟由FPGA给出,具体的时钟还要看FPGA稳定工作可以达到的时钟。另一方面,USB控制器的时钟有USB芯片给出,为48MHZ。数据在不同时钟域间的传输就要用到时钟域的转换。
2.给数据加下帧头:发送数据之前,首先给数据加上一行帧头,表明我的一行数据开始发送,该帧头包含了图像的列信息,然后将加了帧头的数据发送给USB控制模块,由它通过USB芯片发给上位机。

1.跨时钟域的转换

下面我们来谈谈今天主角中的主角:跨时钟域的转换
1,不做时钟域的转换有什么危害?2.单bit的信号与多bit的信号的处理方式有何不同?
带着这两个疑问我们来看。我们在做项目的时候不免会遇到两个模块的时钟不同的情况,A用的时钟是48MHZ,B用到的时钟是133MHZ(这里的48跟133只是说明时钟不同)。
以单bit的信号为例,都以上升沿采样:
A.现在有一个由133MHZ产生的脉冲信号(一个时钟周期)flag,通过接口传给A(48MHZ),A要检测到它,可是现象是,你133MHZ太快了(太短),A的上升沿根本采不到它(也有概率可以采得到)。
B.反过来呢?A(48MHZ)的信号传给B(133MHZ),由于A的时钟频率比B慢,根本不会存在B采不到A信号的情况,但是还会有问题(就是不能让你好好传),亚稳态。
解释一下亚稳态:a.概念:指触发器无法在某个规定时间段内达到一个可确认的状态。(是不是还是有点不懂,没事看下面)。
b.什么情况会导致亚稳态:在同步系统中,建立时间、保持时间不满足就可能会产生,此时的输出端(Q端)在有效的时钟沿之后比较长时间处于不确定状态,毛刺、振荡或者是一个固定的某一电压(却不是D端的电压),这段时间成为决断时间,之后稳定在0、1上,但是这是随机的,跟输入没有必然的关系。
说了这么多,什么意思?就是每个频率的时钟都有自己的一个规则(建立时间、保持时间),我的地盘听我的,到了我的地盘就要按我的规矩办事,你不按我的规则来可以,后果就是,我随便给你输出一个值,这个值是什么,看心情,用了这个数据出不出问题就不是我的事了。
c.如何解决:1.减低时钟频率。2.将寄存器打两拍再使用。
跨时钟域的处理
A比较惨,A的情况包含了B,即包含采不到的情况,又存在亚稳态的问题,下面给出A的处理过程。有没有发现今天的图非常少,先上图。
1.gif

将数据打三拍,一共四个寄存器,通过一个or门,时钟域转换为48MHZ,再延时两拍得到稳定的标志位。通过or门产生的信号会有毛刺,打两拍还可以起到去毛刺的作用。

在这里插入图片描述

另外,多bit同频率,异相位的时钟域切换,使用双口ram进行同步(同频异相),不同频不同相时钟转换使用异步FIFO做同步。成帧模块用到了异步FIFO做处理。

2.GEN_FRAME模块描述

2.1 模块框图

在这里插入图片描述

1.SDRAM存储一帧数据后使能read_start信号,GEN_FRAME将帧头发给USB W_FIFO,同时SDRAM向GEN_FRAME的内部FIFO写入一行数据。
2.SDRAM写完一行数据后等待写下一行的命令(read_req),GEN_FRAME继续向USB W_FIFO写入数据(w_flag有效),直到写完一行后等待。当PC将W_FIFO中数据读完,即flag_C==0时,read_req有效。

3.当read_req有效时,下一行开始传输,GEN_FRAME中的FIFO同时进行读写(SDRAM向GEN_FRAME中的FIFO中写,同时将GEN_FRAME中的数据读出到USB W_FIFO)。

4.直到读完一帧图像后(即行计数row_cnt计满),read_req无效,w_flag无效,停止读写。

2.2 接口定义

4.gif

3关键信号时序

A)读GEN_frame数据到USB W_FIFO

5.gif

① Sdram存完一帧数据后发送read_start信号,经夸时钟域处理后得到read_start_48,在此信号后检测到flag_C为0(即W_FIFO为空),因此要将read_start_48做延展,得到read_start_buf,取它的下降沿为读一帧数据开始。

② 检测到read_start_buf的下降沿后将w_usb_flag_reg拉高,同时w_usb_cnt开始计数,由于数据给出客观上延时一拍才能读到,所以讲使能信号延时一拍发出,即w_usb_flag。该信号为传入下一级的使能信号。

③ 一行数据读出后,继续检测flag_C=0时,F_read_req(向GEN FIFO发送读请求),r_fifo_en与w_usb_flag一致,同时读出fifo中的数据r_fifo_data。

注意:根据同步fifo的经验,这里的r_fifo_en本应该提前数据一拍给出,但上面写到同时读出fifo数据。没错,根据代码发现,异步fifo的读使能r_fifo_en与读数据r_fifo_data居然是同一时刻给出来!!!!!

④ 每读完一行数据我们的行计数gen_cnt_row要加一。这里的行计数是由w_usb_flag_reg的下降沿来触发目的是保证不要丢数据。

⑤ 最终GEN_FRAME输出数据w_data根据行号来选择,gen_cnt_row=0选择zhen_data,否则选择fifo_data。

注意:这里面的gen_cnt_row要记到row_cnt+1(帧头)。

B)sdram向GEN_FRAME FIFO中写数据

6.gif

① 利用sdram时钟检测flag_C的下降沿,产生read_req,并输出到sdram控制模块中。

② 检测到read_req为高时,sdram将数据传入GEN模块,cnt_data开始计数,计数器由SD_data_v使能信号控制(读sdram被刷新打断,数据会被打断),计数到499停止。

③ 写入fifo的数据为512个16bit的数据,数据只有500个,所以要补12个16bit的数据零,cnt_12从cnt_data==499时开始计数,计到11为止。

将SD_data_v与cnt_12_flag作或操作,时序赋值给w_fifo_en。数据时序赋值给w_fifo_data。分别为写入fifo的使能信号与数据信号。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下一个雨天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值