触摸usb信号开关ic经过什么ic可以转usb信号开关ic

扇出过大你就把信号复制几个,逻辑复制。
UID871234&帖子232&精华1&积分1194&资产1194 信元&发贴收入1460 信元&推广收入0 信元&附件收入50 信元&下载支出1846 信元&阅读权限30&在线时间237 小时&注册时间&最后登录&
& & 扇出过大:
& && && & 1.复制逻辑,用多个相同的信号来驱动。这个一般在综合器中设置MAX_FANOUT的值,超出这个值就会自动复制逻辑实现;
& && && & 2.将扇出过大的信号放入全局时钟网络,走全局网络,这样延时和驱动能力都不会有问题;
自尊,自重,自强
UID1106072&帖子11&精华0&积分75&资产75 信元&发贴收入85 信元&推广收入0 信元&附件收入0 信元&下载支出70 信元&阅读权限10&在线时间58 小时&注册时间&最后登录&
挂在天边的鱼
将扇出过大的信号放入全局时钟网络,走全局网络,这样延时和驱动能力都不会有问题;
这个没怎么看明白呢?不是时钟信号也能放到什么时钟网络么?谢谢答复
UID1106072&帖子11&精华0&积分75&资产75 信元&发贴收入85 信元&推广收入0 信元&附件收入0 信元&下载支出70 信元&阅读权限10&在线时间58 小时&注册时间&最后登录&
挂在天边的鱼
& & 看到你之前的帖子了~~“下降沿触发的信号(复位rst_n等)在上全局网络时,不同综合工具的实现结果”好像明白了!!果然是高手呀!!
UID767887&帖子179&精华0&积分1894&资产1894 信元&发贴收入1095 信元&推广收入0 信元&附件收入130 信元&下载支出1777 信元&阅读权限30&在线时间130 小时&注册时间&最后登录&
如果没有时序问题,可以不关注。
或者在QUARTUS中是可以设置FANOUT的最大值的,操作该值部分,软件会做寄存器复制之类操作
UID871234&帖子232&精华1&积分1194&资产1194 信元&发贴收入1460 信元&推广收入0 信元&附件收入50 信元&下载支出1846 信元&阅读权限30&在线时间237 小时&注册时间&最后登录&
嗯,fpga内部的信号基本都可以放到全局时钟网络上,除了少部分特殊走线的
自尊,自重,自强
UID950567&帖子7&精华0&积分67&资产67 信元&发贴收入35 信元&推广收入0 信元&附件收入0 信元&下载支出18 信元&阅读权限10&在线时间6 小时&注册时间&最后登录&
挂在天边的鱼
UID138670&帖子341&精华0&积分8014&资产8014 信元&发贴收入2085 信元&推广收入50 信元&附件收入4448 信元&下载支出10585 信元&阅读权限50&在线时间887 小时&注册时间&最后登录&
set_max_fanout,这个综合工具就能解决fanout的问题,不用修改rtl代码。
[通过 QQ、MSN 分享给朋友]
下载医疗电子精品资料,赢取小爱智能音箱!还可获取300信元!高手们我想实现信号每计数一次改一次电压,有没有什么IC可以实现?_百度知道
高手们我想实现信号每计数一次改一次电压,有没有什么IC可以实现?
上升沿工作,每一次脉冲可以改变一次输出信号。可以看做将信号频率减半。
我想通过一个简单的电路实现如下转换给空心杯电机供电用的,没有时间限制,不是周期的(虽然画的挺像),谢谢各位啦。
我有更好的答案
采纳率:45%
来自团队:
不就是2分频么,一个JK触发器就行,J,K都接高电平,时钟输入,Q端输出
我想用四路集合到一起,有什么推荐的型号吗?
什么四路啊,听不懂
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。&>&信号转换IC数据手册
信号转换IC数据手册
上传大小:4.79MB
NCS8801S( ADV7280,GM7122,GM7123,GM7150,GM8284DD,GM8285C,GM8905C,NCS8801S)
综合评分:0
{%username%}回复{%com_username%}{%time%}\
/*点击出现回复框*/
$(".respond_btn").on("click", function (e) {
$(this).parents(".rightLi").children(".respond_box").show();
e.stopPropagation();
$(".cancel_res").on("click", function (e) {
$(this).parents(".res_b").siblings(".res_area").val("");
$(this).parents(".respond_box").hide();
e.stopPropagation();
/*删除评论*/
$(".del_comment_c").on("click", function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_invalid/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parents(".conLi").remove();
alert(data.msg);
$(".res_btn").click(function (e) {
var parentWrap = $(this).parents(".respond_box"),
q = parentWrap.find(".form1").serializeArray(),
resStr = $.trim(parentWrap.find(".res_area_r").val());
console.log(q);
//var res_area_r = $.trim($(".res_area_r").val());
if (resStr == '') {
$(".res_text").css({color: "red"});
$.post("/index.php/comment/do_comment_reply/", q,
function (data) {
if (data.succ == 1) {
var $target,
evt = e || window.
$target = $(evt.target || evt.srcElement);
var $dd = $target.parents('dd');
var $wrapReply = $dd.find('.respond_box');
console.log($wrapReply);
//var mess = $(".res_area_r").val();
var mess = resS
var str = str.replace(/{%header%}/g, data.header)
.replace(/{%href%}/g, 'http://' + window.location.host + '/user/' + data.username)
.replace(/{%username%}/g, data.username)
.replace(/{%com_username%}/g, data.com_username)
.replace(/{%time%}/g, data.time)
.replace(/{%id%}/g, data.id)
.replace(/{%mess%}/g, mess);
$dd.after(str);
$(".respond_box").hide();
$(".res_area_r").val("");
$(".res_area").val("");
$wrapReply.hide();
alert(data.msg);
}, "json");
/*删除回复*/
$(".rightLi").on("click", '.del_comment_r', function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_comment_del/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parent().parent().parent().parent().parent().remove();
$(e.target).parents('.res_list').remove()
alert(data.msg);
//填充回复
function KeyP(v) {
var parentWrap = $(v).parents(".respond_box");
parentWrap.find(".res_area_r").val($.trim(parentWrap.find(".res_area").val()));
评论共有0条
VIP会员动态
CSDN下载频道资源及相关规则调整公告V11.10
下载频道用户反馈专区
下载频道积分规则调整V1710.18
spring mvc+mybatis+mysql+maven+bootstrap 整合实现增删查改简单实例.zip
资源所需积分/C币
当前拥有积分
当前拥有C币
输入下载码
为了良好体验,不建议使用迅雷下载
信号转换IC数据手册
会员到期时间:
剩余下载个数:
剩余积分:0
为了良好体验,不建议使用迅雷下载
积分不足!
资源所需积分/C币
当前拥有积分
您可以选择
程序员的必选
绿色安全资源
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
您的积分不足,将扣除 10 C币
为了良好体验,不建议使用迅雷下载
无法举报自己的资源
你当前的下载分为234。
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可返还被扣除的积分
被举报人:
举报的资源分:
请选择类型
资源无法下载 ( 404页面、下载失败、资源本身问题)
资源无法使用 (文件损坏、内容缺失、题文不符)
侵犯版权资源 (侵犯公司或个人版权)
虚假资源 (恶意欺诈、刷分资源)
含色情、危害国家安全内容
含广告、木马病毒资源
*详细原因:
信号转换IC数据手册触摸信号经过什么ic可以转信号_百度知道
触摸信号经过什么ic可以转信号
我有更好的答案
本人用的是使用早期电容屏的里程碑1,已经使用两年多了,因为对于配置要求不高所以一直没换,从使用一年开始,本人里程碑屏幕就开始出现漂移的问题,那一次的原因是因为手机里面进水了,用电脑侧面的散热孔吹吹就好了,随后还有几次发生漂移的问题,吹风机的方法并不好使,因为原因并不是湿度大,而是因为静电的影响,在网上看了一下电容屏的工作原理就明白了,北方在冬天空气湿度极低,导致静电特别的大,当手上有静电的时候就容易导致电容屏失灵,这个时候我采用的方法是利用空调扇的“加湿”和“负离子”两种功能对着手机吹,大概2分钟手机就正常了(加湿是消除静电的法宝,静电大部分是正电荷,空调扇产生的负电荷可以与其中和),解决的办法是消除静电,消除对电容屏正常使用不利的条件,而不是说一定要用空调扇去解决,这是本人小小的经验,有的时候不需要换屏幕花冤枉钱的,多看看资料,了解其工作原理,你就会知道该怎么去解决生活当中的问题了,忘采纳!
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。posts - 70,&
comments - 78,&
trackbacks - 0
PS:转载请标明出处 ;本文如有错误,欢迎留言更正。
因为学习了其他方面的知识,耽搁了更新。今天我们就聊聊跨时钟域中的数据信号传输的问题。主要内容预览:
   &使用握手信号进行跨时钟域的数据传输
  &FIFO的介绍
  &在进行FIFO的RTL设计前的问题
  &FIFO的RTL设计(与仿真测试)
  &跨时钟域中的数据信号传输总结
一、使用握手信号进行跨时钟域的数据传输
  下面叙述的意义相同:前级时钟=发送时钟; 后级时钟=采样时钟=接收时钟
  使用握手信号传输数据不是我们的重点,重点是FIFO的设计。在使用握手信号进行数据传输之前,我们说说为什么双D触发器链不应该用于数据的传输。
  一般情况下,我们要传输的数据都是多位的,也就是以数据总线的形式传播的。如果我们使用简单的多组D触发器链进行同步数据的话,由于每一种D触发器链第一级触发器都有可能出现亚稳态,稳定下来之后的电平可能出错;由于有多组D触发器链,就有可能发送多个电平出错,因而导致数据出错,如下图所示:
&        
可以看到,原来前面的时钟域发送的0111数据变成1000的时候,捕获时钟的时钟采样本来要才到0111的,由于保持时间不足,导致了b[2]、b[1]出现亚稳态,而且b[2]稳定后的电平是错误的电平,由此就传输了错误的数据。因此直接使用触发器链进行同步数据是不建议的。
  于是乎,我们就看看使用握手信号是怎么进行传输数据的。
  &数据变化速率比采样时钟域低
  当数据的速率比采样时钟域慢时,也就是说,数据速率相对于采样时钟域(接收数据的时钟域)来说是慢时钟,可以使用控制信号进行同步,在采样到慢时钟域的控制信号后,接收采样数据,时序图如下所示:
&   & & & & & &&
这里只给出了时序图,电路可以按照时序图进行设计。需要注意的是,这个额外的控制信号(wr_en_s)是由前面的逻辑产生的。这与下面的电路不一样:
在下面的这个电路中,控制信号是由上升沿检测电路产生的,而且是接收时钟驱动的上升沿检测电路(也就是说这个控制信号是由后级的逻辑产生的),电路如下所示:
& & & & & & & & &
下面我们来分析一下这个电路吧,时序图如下所示:
& & & & & & & & &
  从时序图中可以看到,可以用上升沿检测电路,检测发送时钟的上升沿,然后这个沿相当于使能信号。上面中,检测到了第二个发送时钟的上升沿,之后就有了使能信号,采样的数据也是第二时钟发送的数据DB,因此对应起来是没有问题。这里由于没有检测到EN1第一个上升沿,所以没有采样到DA也是正常的,这是因为前面的波形没有画出的缘故。
  &当数据的速率(或者说发送时钟的频率)略高于接收时钟端
  由于发送时钟比接收时钟快,于是对于接收时钟,发送时钟就相当于窄脉冲信号,这样我们就有思路了。我们还是上面一样,采用上升沿检测信号当做使能信号;但是问题来了,发送时钟是快的,可能会错过上升沿。于是乎,我们就把窄脉冲捕获电路和上升沿检测电路结合起来。先是窄脉冲捕捉电路,把时钟的沿捕捉到,然后进行边沿检测,检测得到的结果作为使能信号,电路图如下所示:
& & & & & & & &
具体就不分析了,需要强调的是,这个是发送时钟也不能太快。
  &数据变化速率比采样时钟快很多
  当数据的速率比采样的时钟的速率快很多时,对应到时钟的关系就是&&发送时钟和比接收时钟快很多时,这个时候采样时钟就采样不到数据,或者说会采漏部分数据,因此这时候就不能用握手信号了。也许有人说我可以增加使能信号,把数据拉长啊,等后面的采样时钟采样到使能信号、接收到数据之后,我再改变时钟。这种方法的实质就是硬生生地把数据变化率盖满,也就是把发送时钟域的时钟改慢,跟前面的数据变化速率比采样时钟域低的实质是一样的。因此当数据变化率比采样时钟快很多时,就要采样下面介绍的FIFO了。
二、FIFO的介绍
  终于写到FIFO了,FIFO 是first in first out的缩写,也就是&先进先出&;从字面理解,就是说,数据先进来的,就先出去。前面说了当快时钟域传输数据到慢时钟域时,就推荐用FIFO了。FIFO无论是快到慢,还是慢到快,都可以使用它进行数据的缓冲,可谓是&快慢皆宜&啊。
  FIFO的工作流程如下:
  FIFO在写时钟和状态信号的控制下,根据写使能信号往FIFO里面写数据,当写到一定程度后,FIFO存不下新数据的了(或者要以牺牲丢弃旧数据为贷款),这时候就不能往FIFO里面写数据了;在读时钟和状态信号的控制下,根据读使能信号从FIFO里面读出数据,当读到一定程度后,FIFO里面没有数据了,就不能继续读了,不然就会读出错误的数据。根据读写时钟是否一致(同步),FIFO的种类又可以分成同步FIFO和异步FIFO。FIFO能够读写数据,肯定需要数据的存储单元,这里存储数据的单元往往是双口RAM。
  FIFO的写过程:在复位的时候,FIFO(双口RAM)里面的数据被清零(也就是不存在数据)。复位之后,只能进行写操作,因为什么都没有,读数据会读出错误的值。这个时候,当外部给FIFO写使能信号了,在时钟的驱动下,数据就会被写入FIFO里面的RAM存储单元(存储单元的地址由写指针寄存器的内容确定,写指针寄存器中的内容称为写地址,复位的时候为0),写完数据之后(或者在允许写数据之后),这个写指针寄存器就会自动加一,指向下一个存储单元。当写到一定程度的时候(写指针寄存器到达一定的数值),旧数据还没有被读出的时候,再写入新数据就会把旧数据给覆盖,这个时候称为写满,需要产生写满的状态信号(full,简称满)。在写满的时候,需要禁止继续写数据。
  FIFO的读过程:在复位的时候,FIFO里面没有数据,因此这个时候是禁止读数据的。当里面有数据之后,外部读信号到来后,在时钟信号到来的时候,FIFO就会根据读地址(由读指针寄存器的内容确定,读指针寄存器里面的内容称为读地址,复位的时候为0)读出相应的数据,读出数据之后(或者说允许RAM读之后),读指针寄存器自动加一。指向下一个存储单元。当读到一定的程度的时候,也就是FIFO里面没有数据了,这个时候称为读空,需要产生读空的状态信号(empty,简称空)。在读空的时候,需要禁止继续读数据。
  根据前面的描述,我们就可以知道,在复位的时候,FIFO空有效、满无效,禁止读数据,只能往里面写数据。当把FIFO里面的内容都写满的时候,FIFO满有效,空无效,这时候只能读数据,而不能继续往里面写数据。
三、在进行FIFO的RTL设计前的问题
  根据FIFO的介绍内容,我们试着来推导一下FIFO大致由哪些部分构成。
  首先,FIFO需要存储数据,因此就需要存储器;由于需要读,也需要写,于是乎就需要一个DPRAM(double &port &RAM,双端口RAM)。
  然后,RAM需要读/写地址,它才知道在哪里读/写数据,因此需要读/写地址产生模块,也就是需要读/写地址寄存器。什么时候进行写,什么时候进行读,因此需要读/写控制逻辑和空满状态的信号产生逻辑。
  最后,空满信号的产生需要通过对读地址和写地址的比较,由于读写地址在不同的时钟域,因此需要同步电路进行同步。
  通过上面的简单介绍,我们就得到了FIFO的大致框图如下(主要是告诉大家为什么会有这么一个框图):
& & & & & &&
现在来看看这些信号是什么意思吧:
w:写时钟域一方的信号;r:读时钟域一方的信号
wclk:写时钟
wrst_n:写复位,低有效
rclk:读时钟
rrst_n:读复位,低有效
winc:外部输入的写使能信号
rinc:外部输入的读使能信号
wdata :要写进数据,要写进FIFO里面存储的数据。
rdata:读数据,从FIFO里面读取出来的数据。
wdata:要读出的数据,要读出FIFO里面存储的数据
wfull:写满的状态信号
rempty:读空的状态信号
wclken:RAM的允许写信号,在这个信号有效的情况下,RAM才能写得进数据。
rclken:RAM的允许读信号,在这个信号有效的情况下,RAM才能读得出数据。
waddr:RAM的写地址。
raddr:RAM的读地址
wptr:要同步到写时钟域的读指针(读地址)。
rptr:要同步到读时钟域的写指针(写时钟)
wq2_rptr:读地址rptr同步到写时钟域的读地址(格雷码,后面会说为什么用格雷码)
rq2_wptr:写地址rptr同步到读时钟域的读地址(格雷码,后面会说为什么用格雷码)
syn_r2w:读同步到写触发器链中间信号。
syn_w2r:写同步到读触发器链中间信号。
介绍完这些信号之后,我开始聊聊FIFO设计前的一些问题。
  &FIFO的空满信号产生
空状态信号:
  一开始复位的时候,空信号是有效的,当写了数据之后,空信号就无效了。然后当数据被读取完之后,空信号就有效了。那么什么时候数据被读取完了呢,也就是数据被读取完的时候有什么特征呢?特征就是读地址和写地址相等,如下所示:
& & & & & & & & &
  由于读地址要追赶写地址,在赶上的时候,地址全等就证明了读空了。
  也许有人会问:写地址由于要同步到读时钟域去,会存在同步延时的,比如 说t=0s的时候同步过去,此时写地址为A;在t=2s的时候A同步过来了,但是这个 时候写地址已经变为A+2,而你同步过来的这个写地址为A。如果在t=2s这个时候读地址=A,即读地址=写地址,读赶上了写,按照上面的设计想法就会产生读空信号,但是实际上是不相等的,也就是实际上读并没有赶上写,即没有读空的,这不就是产生错误的读空信号了吗?
  首先,是存在这样的情况,但是这种情况不是设计错误。一方面由于我们要产生读空信号,目的是也就是防止继续读从而读出错误的数据;实际上没有读空,即使产生了读空信号,也是没有影响,相当于提前判断产生读空信号而已。另一方面由于是读时钟域采样的读的地址,这个读地址是实时的;写地址是延时的,当这个两者相等时,我们这个实时的地址在比实际的写地址小的时候就产生读空信号,防止了读空。因此即使产生读空信号,也不会因为读空而产生错误的数据。因此是没有设计错误的。
写满状态:
  一开始复位之后,进行写数据;由于地址(假设地址是4位,也就是深度是4位)是可以回卷的,也就是说,写指针从3写到15后,继续写又会返回到3那里;假如复位后读操作只读到地址3那里就不读了,那么这个时候就写满了。也就是说,写满的时候,写地址和读地址是相等的,如下所示:
& & & & & & &
于是乎,我们该怎么区分在读地址和写地址相同的时候是读空还是写满呢?下面来介绍一种常用的方法:
  将地址深度拓宽1位当做标志位,回卷一次标志位取反。比如上面的例子中,4bit地址拓宽为5bit,那么读地址就是3(由于读地址没有回卷,所以是(0)0011)那里,当写地址回卷之后与读地址相同(由于写地址回卷了,最高位取反,所以是(1)0011),因此这就是写满了。当读地址回卷之后,变成10011,这个时候,就读空了。也就说,虽然DPRAM的深度还是4bit,但是我们在进行设计地址寄存器的时候,增多一位当做状态。然后读写地址全相等的时候,表示是读空;除了标志位外,剩余的地址为全部相等,那么就表示是写满。
  这里还是会产生与前面的空信号一样的问题,也就是同步过来的读信号是延时的值,与前面一样,是不会影响写满信号的,不属于设计错误。
  除了上面这种方法之外,在同步FIFO中,还可以使用计数器的方法。设置一个状态计数器,复位的时候为0。写的时候,计数器加1;读的时候,计数器减1。那么很容易得出,计数器为0的时候,就是读空就有效了;当计数器等于FIFO的深度(2^n &- &1)时,就说明写满了。这种方法如果FIFO深度很大的话,就需要很大的计数器了,所以有局限性。
  从上面的分析中,由此也可以知道,空信号的产生需要把写地址同步到读时钟域,然后进行比较(比较之后产生);满的信号需要把读地址同步到写时钟域,然后进行比较(比较之后产生)。
  &为什么要选择格雷码作为同步地址的编码
  首先,我们知道,读地址需要跟写地址比较来产生空和满信号,然后对于异步FIFO,读写为不同时钟,如果直接采样,就会有:类似前面数据产生多位亚稳态的问题,(时序图就不画了)比如写地址从00111改变从01000的时候,读时钟恰好采样,那么除了最高位外,其它的4位都有可能产生亚稳态,有可能同步得错误的地址。这是引入格雷码的一个原因。另外一个原因就是:无论是读地址还是写地址,在(允许)进行读和写之后,地址都是加1,而不是加2或者加3等其他的值。为什么会这样呢?我们来看看格雷码的编码:
& & & & & & & &
  从上图中我们可以知道,从地址0变成地址1,格雷码和二进制码都是0000变成0001;地址从1变成地址2,格雷码是0001变成0011,而二进制是0010......我们很容易得到,在相邻地址变化中,格雷码只有一位发生变化,如地址从7变为8时,格雷码是0100变成1100,也就是只有最高位发送变化;我们再来看看二进制编码,二进制编码则有可能全部都改变,地址从7变为8时,二进制码是0111变成1000,4位都发生了变化。假如采样的时候地址恰好从7变为8时,那么二进制编码就有多位发生亚稳态,稳定后的值什么都有可能;而格雷码由于只有最高位跳变,第三位由于没有跳变,不会产生亚稳态可以稳定正确采样,稳定后的值只有,地址只差数值1,是不会影响判断的结果的(因为是同步过来的,是个延时的值,不打紧)。
  知道了格雷码的优点之后,我们就要使用各格雷码了。由于RAM的读写地址都是(传统)二进制编码,这里使用格雷码有两种使用方法,第一种使用方式是,将二进制编码转换成格雷码,然后把格雷码同步过去,再把同步过来的格雷码反转换成二进制码,进行二进制地址和二进制地址的比较;另外一种使用方式是,将二进制编码转换成格雷码,然后把格雷码同步过去,然后使用格雷码进行比较。这里使用第一种方式,虽然这种方式比较需要多两块格雷码转二进制的电路,但是我们可以实时比较,能将寻址的二进制马上与同步过来的&延时&二进制进行比较;使用格雷码比较的话,实际值会慢一拍(因为实时方的格雷码需要寄存输出,会慢一拍,如果不寄存输出,就有可能产生毛刺)。
然后格雷码的与二进制的互相转换如上图,下面是转换讲解(左边为格雷转二进制,右边为二进制转格雷):
& & & & & && & & &
在布尔代数里面有A^B=C &A=B^C
  &FIFO的深度选择
  首先,FIFO是有宽度和深度的。FIFO的宽度就是RAM的位宽,也是要存入/取出数据的位宽;然后深度就RAM的地址深度,也就是最多可以存多少个数据。例如FIFO的宽度是8bit,那么FIFO每个时钟存入的数据的宽度也是8bit;FIFO的深度是10bit,那么FIFO就最多可以存2^10=1024个8bit的数据。
  我们要存储数据,FIFO的深度选小了,在写的时候就很有可能写溢出;深度选大了,就会浪费存储面积。选择一个合适的深度,最主要的就是防止写溢出;由于FIFO要读也要写,那么FIFO的(地址)深度该选多少合适呢?
  这就和你的读写速度有关了,根据读写速度来选择FIFO深度,此外需要注意的是,在使用FIFO的时候,写的平均吞吐量要和读的平均吞吐量相等。
现在举例来说明:设你的写时钟频率为100M,读时钟为200M;写速度为:100个时钟写如60个数据,读速度为:100个时钟读出30个数据 。
①首先验证你的数据吞吐量是否相等:
    写的平均吞吐量=100M*60/100=60M个数据/S
    读的平均吞吐量=200M*30/100=60M个数据/S
因此这两个是相等的,不会发生写溢出;如果写大于读,那么FIFO早晚会很快写满溢出;如果读大于写,那么FIFO迟早会读空。因此需要读写吞吐量相同。
②求最低深度
  我们知道读写速度之后,就可以判断FIFO要多少深度才合适了,由于FIFO的深度考虑是出于我们要防止写溢出(写满),因此我们考虑写的情况:
写的时候是100个时钟写60个数据,我们不知道它是怎么样子写的,我们从悲观的角度出发,也就是从写得最密集的角度出发:前100个写时钟的最后60个时钟写60个数据,然后后100个写时钟的最前60个时钟写入60个数据,也就是在120个写时钟内写入了120数据。
这120个写时钟的时间是:
& & & & & & & & & & &&
在这段时间内,根据读写的速率要求,肯定是要读数据的,读出的数据为:
& & & & & & & & & & &&
因此我们FIFO需要的深读就等于没有读出的数据的个数就是:
                  120-72 =48
然而由于上面读的方式是一个平均的方式,此外FIFO的深度一般是2的整数次幂,要符合格雷码的编码转换规则,因此我们深度一般不选择48,而是选择比它大的2的整数次幂的数,比如64或者128。FIFO深度的选择过程就如上面所述,(这里参考《FPGA深度解析》)。
四、FIFO的设计(与仿真测试)
接下来我们就要设计一个异步FIFO了,这里我们设计的FIFO跟上面的有点不同,整体结构如下所示:
& & & & & & & & &
这里主要是多出了两个状态信号:
  wfull_almost:将满信号。为了预防万一,FIFO要满的时候,使这个信号有效,当面的模块时钟(前级电路)检测到这个信号有效后,就把winc变为无效,用来提供给前面电路的指示信号。这个信号要比full信号提前,因为考虑到在判断出满之后,还需要一些动作(延时),才能不写;于是乎我们就用将满信号来补充这些延时,而不是等到满信号才做出反应。
  rempty_almost:将空信号。这个也是为了考虑在空信号判断出来之后,到禁止继续读可能有延时,从而设立这个标识,在将空的时候就禁止继续读数据。
将满信号和将空信号的关键因素就是读写地址之间的举例(间隔),那我们来看看写和读的间隔怎么产生:
对于写时钟域,我们是要产生几乎满信号,这对应的间隔就是看看写地址还有多少就赶上了读地址,求出这两个地址之间的间隔,然后再与预设的间距比较,如果这个间隔小于预设的间距,那么就产生几乎满的信号。那么我们这个间隔怎么求:
  &当读写状态位相同的时候,如下图所示:
& & & & & & & & & &&
  由于最高位相同,所以写需要回卷才能最上读,那么间隔也就是A+B;假设FIFO的深度是D,写地址为waddr,读地址为raddr,那么间隔就是D-C=D-(waddr-raddr)=D+raddr-waddr.(注意,这里的读/写地址不包括状态位)
  &当读写状态不同位时,如下图所示:
& & & & & & & & & &
这时候waddr再有C就追上raddr了,因此间隔就是raddr-waddr。
上面是对于写区域间隔的生成,下面就来说说读区域的间隔怎么产生吧:
  &状态位一样的时候,也就是没有回卷的时候,如下图所示:
& & & & & & & & & & &
很显然,无论是加不加状态位,都是间隔都是waddr-raddr,也就是说,还有waddr-raddr的举例,raddr就追上了waddr。
  &当状态位不一样时:
& & & & & & & & & &
  需要回卷才能追上写,因此间隔就是:
  FIFO的深度-(raddr-waddr)=FIFO+waddr-raddr(这里的读写地址不包括状态位)。
  当加上状态位之后,我们发现,间隔是可以用raddr-waddr来表示的,比如raddr=1011,waddr是0011,间隔是8;加上状态位后,Raddr=01011,Waddr=10011,间隔也可以表示为=01000=8(借位是会被省略掉的),因此用加上状态位后,间隔可以表示为waddr-raddr。
因此在读时钟域,间隔的表示就是带状态位的waddr-raddr。
  说完了几乎满和几乎空信号,我们再聊聊上面的框图,整个FIFO可以分成写逻辑模块、读逻辑模块、写/读同步读/写模块。其中
&写逻辑的模块的功能是:根据状态信号和外部的写信号产生对RAM的写控制信号、产生RAM的地址信号、产生空和将空的状态的状态信号。因此写逻辑模块可以分成3个部分:①(RAM)写控制逻辑部分;②RAM写地址产生部分;③状态产生部分。
  ①RAM写控制逻辑部分的功能就是,产生RAM的写使能信号:wclken有效的条件是:外部信号写使能信号winc来了,而且此时满信号没有效,这个时候就允许往RAM里面写数据了。
  ②RAM写地址产生部分的功能就是产生RAM的地址和产生格雷码地址(产生的格雷码地址传输给同步模块):复位的时候,RAM的地址waddr为0;此后,在写时钟上升沿检测到RAM的写使能wclken有效之后,waddr自动加一,指向下一个单元,wclken无效waddr则不变。我们使用比RAM地址宽1位的地址寄存器进行递增,地址寄存器的最高位充当空满信号时候的状态比较位。
  ③状态产生部分的功能就是:将同步模块过来的格雷码转换成二进制,然后跟RAM写地址产生部分传来的地址进行比较,产生将满信号和满信号。(将满信号的产生就是两个地址小于某个间隔时有效,满信号产生则是间隔等于0或者:间隔只有一个地址只差,但是这个时候RAM的写信号还有效)。
&读逻辑也是一样,这里不再详述,具体细节我们在代码后面进行讨论。
&写/读同步读/写模块其实就是双D触发器(链)。
代码如下所示:
1 //Async_FIFO ,4bit字宽,4bit深度
2 module Async_FIFO #(
parameter DATA_WIDTH = 4
parameter DEEP_WIDTH = 4
//写时钟域信号
wfull_almost
[DATA_WIDTH-1:0]
//读时钟域信号
rempty_almost
[DATA_WIDTH-1:0]
21 //中间的连线信号
22 wire [DEEP_WIDTH-1:0]
23 wire [DEEP_WIDTH:0]
24 wire rcl
25 wire [DEEP_WIDTH:0] rq2_
27 wire [DEEP_WIDTH-1:0]
28 wire [DEEP_WIDTH:0]
29 wire wcl
30 wire [DEEP_WIDTH:0] wq2_
32 Read_Data
inst_Read_Data(
( rempty ),
.rempty_almost
( rempty_almost ),
( raddr ),
( rclken ),
( rq2_wptr ), //input,同步过来写格雷码指针
( rrst_n )
44 DFF_Sync
( wq2_rptr ),
.dff_rst_n
( wrst_n )
52 Write_Data
inst_Write_Data(
( wfull ), //几乎满信号
.wfull_almost
( wfull_almost ), //几乎空信号
( waddr ), //输出给RAM的地址
( wptr ), //格雷码地址指针
( wclken ), //写RAM信号
( wq2_rptr ), //同步过来的读格雷码指针
( winc ), //外部输入的使能信号
( wclk ), //写时钟
( wrst_n )
65 DFF_Sync
( rq2_wptr ),
.dff_rst_n
( rrst_n )
72 ram_16x16
ram_16x16_inst (
.data ( wdata ),
.rdaddress ( raddr ),
.rdclock ( rclk ),
.rden ( rclken ),
.wraddress ( waddr ),
.wrclock ( wclk ),
.wren ( wclken ),
.q ( rdata )
84 endmodule
1 module Write_Data #(
parameter DEEP_WIDTH = 4
parameter FIFO_DEEP
parameter GAP_WIDTH
, //几乎满信号
wfull_almost
, //几乎空信号
[ DEEP_WIDTH-1:0]
, //输出给RAM的地址
[ DEEP_WIDTH:0]
, //格雷码地址指针
, //写RAM信号
[ DEEP_WIDTH:0]
, //同步过来的读格雷码指针
, //外部输入的使能信号
, //写时钟
17 reg [ DEEP_WIDTH:0] waddr_//地址寄存器,5位
[ DEEP_WIDTH:0] wq2_rptr_//读指针同步到写时钟域后,从格雷码转换成二进制
19 reg [ DEEP_WIDTH:0] wgap_//寄存间隔的距离
21 //第一部分,写RAM使能信号的生成
22 assign wclken = winc &&(~ wfull );
24 //--------------------------------------//
26 //第二部分,产生RAM的地址和格雷码
27 always @(posedge wclk or negedge wrst_n)
28 if(wrst_n == 1'b0) begin
31 else if( wclken )begin //地址自增一
&= waddr_reg + 5'd1 ;
35 //生成RAM地址
36 assign waddr = waddr_reg[ DEEP_WIDTH-1:0];
38 //生成格雷码
39 always @(posedge wclk or negedge wrst_n)
40 if(wrst_n == 1'b0) begin
43 else begin
waddr_reg ^( waddr_reg && 1'b1); //其实也就是位错之后的异或
//移位操作不代表移位寄存器
48 //-----------------------------------//
50 //第三部分
52 //将格雷码转换成二进制编码
53 always @( * )begin
wq2_rptr_bin[4]
= wq2_rptr[4]
wq2_rptr_bin[3]
= wq2_rptr[4] ^ wq2_rptr[3]
wq2_rptr_bin[2]
= wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2]
wq2_rptr_bin[1]
= wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2] ^ wq2_rptr[1]
wq2_rptr_bin[0]
= wq2_rptr[4] ^ wq2_rptr[3] ^ wq2_rptr[2] ^ wq2_rptr[1] ^ wq2_rptr[0]
61 //产生满的间隔
62 always @(*)begin
if( waddr_reg[4] ^ wq2_rptr_bin[4] ) //最高位不相等的时候,也就是有一个是回卷了
= wq2_rptr_bin[3:0] - waddr_reg[3:0] ;
else //最高位相等的时候,也就是没有回卷,那么间隔就是FIFO_DEEP-( waddr_reg - wq2_rptr_bin)
wgap_reg = FIFO_DEEP + wq2_rptr_bin - waddr_
69 //根据间隔产生几乎满信号
70 always @(posedge wclk or negedge wrst_n)
71 if(wrst_n == 1'b0) begin
wfull_almost
74 else if( wgap_reg & GAP_WIDTH)begin
wfull_almost
wfull_almost
80 //产生满信号
81 assign wfull = (~(|wgap_reg ))||(( wgap_reg == 1)&&( winc ));//间隔为0的时候为满,间隔是1的时候还要写,也为满
83 endmodule
1 module Read_Data #( parameter DATA_WIDTH = 4
parameter DEEP_WIDTH = 4
parameter GAP_WIDTH
rempty_almost
[DEEP_WIDTH-1:0]
//给 DPRAM的地址
[DATA_WIDTH:0]
//给写时钟域的读格雷码
//DPRAM的读使能信号
//外部输入的读使能信号
[DEEP_WIDTH:0]
16 reg [ DEEP_WIDTH:0] raddr_//地址寄存器,5位
[ DEEP_WIDTH:0] rq2_wptr_//写指针同步到读时钟域后,从格雷码转换成二进制
18 reg [ DEEP_WIDTH:0] rgap_//寄存间隔的距离
20 //第一部分,读RAM使能信号的生成
21 assign rclken = rinc &&(~ rempty );
23 //--------------------------------------//
25 //第二部分,产生RAM的地址和格雷码
26 always @(posedge rclk or negedge rrst_n)
27 if(rrst_n == 1'b0) begin
30 else if( rclken )begin //地址自增一
&= raddr_reg + 5'd1 ;
34 //生成RAM地址
35 assign raddr = raddr_reg[ DEEP_WIDTH-1:0];
37 //生成格雷码
38 always @(posedge rclk or negedge rrst_n)
39 if(rrst_n == 1'b0) begin
42 else begin
raddr_reg ^( raddr_reg && 1'b1); //其实也就是位错之后的异或,移位操作不代表移位寄存器
46 //-----------------------------------//
48 //第三部分
50 //将格雷码转换成二进制编码
51 always @( * )begin
rq2_wptr_bin[4]
= rq2_wptr[4]
rq2_wptr_bin[3]
= rq2_wptr[4] ^ rq2_wptr[3]
rq2_wptr_bin[2]
= rq2_wptr[4] ^ rq2_wptr[3] ^ rq2_wptr[2]
rq2_wptr_bin[1]
= rq2_wptr[4] ^ rq2_wptr[3] ^ rq2_wptr[2] ^ rq2_wptr[1]
rq2_wptr_bin[0]
= rq2_wptr[4] ^ rq2_wptr[3] ^ rq2_wptr[2] ^ rq2_wptr[1] ^ rq2_wptr[0]
59 //产生读空的间隔
60 always @(*)begin
//无论状态位是否相同,都可以用带状态位的写地址减读地址
rgap_reg = rq2_wptr_bin - raddr_
65 //根据间隔产生几乎满信号
66 always @(posedge rclk or negedge rrst_n)
67 if(rrst_n == 1'b0) begin
rempty_almost
70 else if( rgap_reg & GAP_WIDTH)begin
rempty_almost
rempty_almost
76 //产生满信号
77 assign rempty = (~(|rgap_reg ))||(( rgap_reg == 1)&&( rinc ));//间隔为0的时候为空,间隔是1的时候还要读,也为空
81 endmodule
1 module DFF_Sync #(parameter DEEP_WIDTH = 4
output reg
[DEEP_WIDTH:0]
[DEEP_WIDTH:0]
9 reg [DEEP_WIDTH:0] sync_ //两级同步D触发器
10 always @(posedge dff_clk or negedge dff_rst_n)begin
if( dff_rst_n == 1'b0)begin
else begin
21 endmodule
1 //timescale
2 `timescale
parameter DATA_WIDTH = 4
5 //the Internal motivation variable(register) and output wire
[DATA_WIDTH-1:0]
//读时钟域信号
[DATA_WIDTH-1:0]
External motivation storage variable
24 //Sub module signal,example: wire [1:0] xxx == xxx_inst.xxx_inst.
26 // Global variable initialization ,such as 'clk'、'rst_n'
27 initial begin
#0 rrst_n = 0;
wrst_n = 0 ;
rinc = 0 ;
winc = 0 ;
//wdata = 0 ;
#20 rrst_n = 1 ;
#25 wrst_n = 1 ;
39 //Internal motivation variable initialization
40 //initial begin
42 // winc generate
43 always @(posedge wclk or wrst_n)begin
if( wrst_n == 1'b0 )begin
winc = 1'b0;
else if( wfull_almost )
winc = 1'b0;
winc = 1'b1 ;
53 // rinc generate
54 always @(posedge rclk or rrst_n)begin
if( rrst_n == 1'b0 )begin
rinc = 1'b0 ;
else if( rempty )
rinc = 1'b0;
rinc = 1'b1 ;
64 // wdata
65 always @(posedge wclk or negedge wrst_n)begin
if( wrst_n == 1'b0 )begin
wdata = 4'd0 ;
else if( winc )begin
wdata = wdata + 1'b1;
74 //cloclk signal generation
75 always #15 rclk = ~
76 always #10 wclk = ~
78 //Cases of sub module xxxx xxxx_inst(.(),.(), ... ,.());
79 Async_FIFO Async_FIFO_inst(
//写时钟域信号
.wfull_almost
( wfull_almost
//读时钟域信号
.rempty_almost
( rempty_almost
96 // Internal motivation variable assignment
using task or random
98 task data_assign(xx);
rand_bit();
xx,xx,...;
for( ; ; )begin
for(i=0; i&255; i=i+1)begin
@(posedge clock)
@(posedge sclk);
Internal motivation variable &=
Internal motivation variable &={$random} %2;
106 endtask
110 endmodule
简单的仿真代码
这里的简单仿真代码仿真了写时钟间隔写,读时钟一直读的情况,使用modelsim的仿真波形如下所示:
&最后我们来小节一下:
  异步FIFO,主要用于跨时钟域的数据信号传输,它的基本架构如下所示(纯手工画):
根据从上面电路架构图,就可以写代码实现。
需要注意的是问题有:一个就是地址同步的问题,另外一个是空满信号产生的问题。(深度选择问题这里就不说了)
地址同步主要是用格雷码同步实现;空满信号则通过拓宽地址寄存器来实现。
格雷码与二进制的转换关系上面说了。格雷码的优点就是相邻之间只有一位信号变化,因此常常用来异步设计的编码;缺点就是需要增加相应的组合逻辑。
五、跨时钟域中的数据信号传输总结
&  跨时钟域的数据信号传输到这里就结束了,在这里进行总结一下:
  &数据变化速率比采样速率低、或者比采样速率略快时,可以使用握手信号进行。
  &无论是快到慢,还是慢到快,FIFO通吃。
  &FIFO的设计需要注意FIFO空满信号产生问题、格雷码的应用问题、深度选择问题等。
  &说到格雷码的应用问题,也许会想到能不能先把数据变成格雷码,然后再通过双D触发器同步过去呢?这明显是不能的啊,你的数据不像FIFO的地址产生那样,是具有相邻性的,也就是只差一个1;因此不能把数据变成格雷码,再传输。
PS:本文部分图片来自网络
阅读(...) 评论()

我要回帖

更多关于 旋转触摸ic 的文章

 

随机推荐