0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

触发器的应用案例

FPGA开源工坊 来源:FPGA开源工坊 2023-11-13 09:55 次阅读

今天群友遇到一个在综合的时候报错ambiguous clock in event control的问题,我们就来看看一个always块会生成什么样的电路。

案例一

首先从最简单的一段代码来看:

always @(posedge clk ) begin
    c <= b;
end

在上面的代码里面敏感信号只有一个posedge clk,begin end中间也只有一个赋值语句,仅仅是一个打拍的操作,那么我们来看一下,他生成的电路是什么样子的。

67497840-81c0-11ee-939d-92fbcf53809c.png

可以看到,clk和b经过一个IBUF后接入触发器的C端(时钟端)和D端(数据输入端),然后输出Q端经过一个OBUF连接到c。其中IBUF和OBUF以及BUFG是vivado自动帮我们插入的,当信号是顶层信号的时候vivado就会帮我们自动插入IBUF和OBUF,时钟信号帮我们自动挂到了时钟树上面。

案例二:

那么vivado是怎么认出来我们代码里面写的clk就是时钟信号呢,是靠clk这个名字吗,让我们把clk换成rst来看一下,代码如下:

always @(posedge rst ) begin
        c <= 1'b1;
end

676e6178-81c0-11ee-939d-92fbcf53809c.png

可以看到上面代码生成的电路和案例一中的电路是一样的,vivado也是把posedge rst认为是时钟信号接到了触发器的时钟端,可见vivado并不是靠名字来识别哪个信号是时钟,哪个信号是复位的。

案例三:

那么我们应该怎么生成一个复位信号呢,先看一下同步复位的情况,代码如下:

always @(posedge clk ) begin
    if(rst == 1'b1)begin
        c <= 1'b0;
    end
    else begin
        c <= b;
    end       
end

678d0eac-81c0-11ee-939d-92fbcf53809c.png

可以看到复位端rst接到了触发器的复位信号上。注意在上述代码中是高电平复位的,那么我们再看一下如果是低电平复位会产生什么样子的电路,代码如下:

always @(posedge clk ) begin
    if(rst == 1'b0)begin
        c <= 1'b0;
    end
    else begin
        c <= b;
    end       
end

67a927e0-81c0-11ee-939d-92fbcf53809c.png

可以看到在rst信号之后多了一个LUT,这个LUT的目的是将rst信号取反,也就是说我们想让rst为0的时候进行复位,但是vivado在生成电路的时候会将其取反变为1之后接到触发器的复位端,这里在复位端插入一级LUT便会影响我们的时序,这也是为什么我们常说FPGA推荐同步高复位的原因之一。

在UG901中有相关的描述如下:

67d1b5f2-81c0-11ee-939d-92fbcf53809c.png

案例四:

在案例三中展示了同步复位的情况,注意这里生成的触发器都是FDRE,在xilinx的FPGA中一共有四种触发器,在UG901中有说明,如下图:

67ea9a7c-81c0-11ee-939d-92fbcf53809c.png

可以看到对于同步复位的触发器有FDSE和FDRE两种,两者的区别就是FDSE在复位的时候输出是1,FDRE是0。,这也是为什么在案例三中无论是高复位还是低复位生成的都是FDRE。

那么我们改变一下代码,让c在复位的时候变为1,也就是c <= 1'b1,来看看生成的电路是什么样子的,代码如下:

always @(posedge clk ) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end       
end

680e3ab8-81c0-11ee-939d-92fbcf53809c.png

可以看到在这种情况下,我们的代码就映射到了一个FDSE上。

案例五:

第五个案例就来看一下vivado是怎么把rst认为是复位信号的。我们先来看如下代码:

always @(posedge clk ) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    if (a == 1'b1)begin
        c <= b;
    end       
end

68314a94-81c0-11ee-939d-92fbcf53809c.png

可以发现复位信号没有了,FDRE是复位端直接接了地,那么我们有理由怀疑是不是vivado在处理if else的时候会把if里面的信号认为是复位信号呢。上述代码里面两个if语句并列,生成的电路也是a b rst经过一大段组合逻辑之后接入到FDRE是D端。

案例六:

将案例五的代码稍将改变,也就是在第二个if前面增加一个else,代码如下

always @(posedge clk ) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else if (a == 1'b1)begin
        c <= b;
    end       
end

68510c8a-81c0-11ee-939d-92fbcf53809c.png

可以看到我们的复位端又重新回来了,那么也就印证了在案例五中的猜想,他是靠if else, if elseif这样的结构来识别是不是复位的,怎么映射过去的,需要注意的是案例六中因为我们写了a==1时才把b的值给到c,那么a就被接入到了触发器的CE端,当a的值是0时,CE端为0,Q端保持上一次的值不变。注意在时序电路里面,我们不写else也不会生成latch。

案例七:

上面代码都是在敏感信号里面只有一个posedge clk,那么如果我们写多个敏感信号呢,会变成什么样子。

always @(posedge clk or posedge rst) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    if (a == 1'b1)begin
        c <= b;
    end       
end

我们先来看一下上述代码,敏感列表里面有两个信号,posedge clk和posedge rst。并且在begin end里面也没有if else或者if else if这种结构的语句,按照我们同步复位的几个案例的推断,他会把clk和rst都推断为时钟信号,而实际上我们不可能给一个xilinx的FPGA的触发器同时接两个时钟信号,这个时候vivado在综合的时候就给我们报错了。

因为我们知道一个触发器只能有一个时钟信号,如果有多个时钟信号我们也需要做时钟切换电路,来确保在同一时刻只有一个时钟接到上面。vivado推断不出来上述代码究竟哪个信号是时钟信号,那他只能报错了,告诉我们当前时钟信号是模棱两可的。

686a33f4-81c0-11ee-939d-92fbcf53809c.png

案例八:

那么案例七中的代码怎么改呢,第一种选择案例五中的方式,将敏感列表变为一个,那么时钟信号自然就明确了。

第二种就是敏感列表中另一个信号变为复位信号。这两种改法取决于我们想要实现的逻辑是什么样子的。

always @(posedge clk or posedge rst) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end       
end

6887df6c-81c0-11ee-939d-92fbcf53809c.png

第二种改法被综合为一个FDPE。

案例九:

always @(posedge clk) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
    
    if(a == 1'b1)begin
        c <= d;
    end
         
end

我们再来看一段代码:

有一组if else,如果只有这一组的话,他就应该和案例4一样生成一个FDSE,但是我们下面又给他加了一句if,那么他便不会将rst认为是一个复位信号了,而是和其他if else一起生成一大堆组合逻辑。

68a2c8fe-81c0-11ee-939d-92fbcf53809c.png

案例十:

在案例九里面是对同一个信号进行赋值,如果我们对不同的信号进行赋值呢。

always @(posedge clk) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
    
    if(a == 1'b1)begin
        e <= d;
    end
         
end

上述代码和案例九里面,只有当a==1时的操作不同,一个是对c进行赋值,另一个是对新的寄存器e进行赋值,那么vivado就会对c和e两个寄存器分别处理,生成如下电路:

68c48a02-81c0-11ee-939d-92fbcf53809c.png

这个代码和我们分成两个always写是一样的:

always @(posedge clk) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
   
         
end


always @(posedge clk) begin
    if(a == 1'b1)begin
        e <= d;
    end
         
end

案例十一:

如果我案例九中的代码换成异步复位呢,会发生什么:

always @(posedge clk or negedge rst) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
    
    if(a == 1'b1)begin
        c <= d;
    end
         
end

68f7e302-81c0-11ee-939d-92fbcf53809c.png

综合完直接报错了,那么为什么案例九中没报错呢。是因为我们敏感列表里面有clk和rst,他们肯定不是复位就是时钟信号嘛,vivado也会这么考虑,但是在begin end里面写的代码块,按第一个if else结构应该生成带复位的触发器,而第二个if结构,他又不应该生成,vivado就傻眼了,只能报错啊。而案例九里面,rst不在敏感列表里面,vivado还有一种选择就是将其当成普通信号,所以案例九生成了一大堆的组合逻辑。

案例十二:

也许会有一种想法就是把案例十一的代码像案例十那样改,也就是对两个寄存器进行赋值,如下代码:

always @(posedge clk or posedge rst) begin
    if(rst == 1'b1)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
    
    if(a == 1'b1)begin
        e <= d;
    end
         
end

不过不好意思,这种写法也是错误的,会报错

691afeb4-81c0-11ee-939d-92fbcf53809c.png

这是因为我们在敏感列表里面写两个信号,但是对于e这个寄存器又都没有使用,不会生成复位信号,那可不就接着报ambiguous clock in event control了。在上述代码中对c的操作是不会出错的。

案例十三:

看到这里不知道大家有没有注意到,在异步复位里面,我们都是posedge rst和if(rst == 1'b1)也就是高电平复位,注意这两个是需要匹配的,如果我们写个posedge rst但是紧接着写if(rst == 1'b0),这样写是会报错的。

always @(posedge clk or posedge rst) begin
    if(rst == 1'b0)begin
        c <= 1'b1;
    end
    else begin
        c <= b;
    end  
   
         
end

6935550c-81c0-11ee-939d-92fbcf53809c.png

如上代码和报错,vivado也不知道他应该是生成一个高电平复位还是一个低电平复位的电路了,所以他报错了。

关于异步复位还是同步复位可以参考UG949中的描述:

69519cb2-81c0-11ee-939d-92fbcf53809c.png

697c6ece-81c0-11ee-939d-92fbcf53809c.png

69a33a0e-81c0-11ee-939d-92fbcf53809c.png

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 触发器
    +关注

    关注

    14

    文章

    1996

    浏览量

    61055
  • 代码
    +关注

    关注

    30

    文章

    4752

    浏览量

    68362
  • 时钟信号
    +关注

    关注

    4

    文章

    445

    浏览量

    28512
  • Vivado
    +关注

    关注

    19

    文章

    808

    浏览量

    66341
  • 复位信号
    +关注

    关注

    0

    文章

    53

    浏览量

    6302

原文标题:小议触发器

文章出处:【微信号:FPGA开源工坊,微信公众号:FPGA开源工坊】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    JK触发器 D触发器 RS触发器 T触发器 真值表

    D触发器真值表分析: 1. D 触发器真值表   Dn   
    发表于 09-11 23:15 1.9w次阅读

    JK触发器,JK触发器是什么意思

    JK触发器,JK触发器是什么意思 1.主从JK触发器主从结构触发器也可以彻底解决直接控制,防止空翻。这里以性能优良、广泛使用的主从JK触发器
    发表于 03-08 13:36 6772次阅读

    D触发器,D触发器是什么意思

    D触发器,D触发器是什么意思   边沿D 触发器:  电平触发的主从触发器工作时,必须在正跳沿前加入输入信号。如果在CP 高
    发表于 03-08 13:53 4897次阅读

    什么是RS触发器,RS触发器的工作原理是什么?

    什么是RS触发器,RS触发器的工作原理是什么? 主从RS触发器
    发表于 03-08 14:00 3.1w次阅读

    施密特触发器,施密特触发器是什么意思

    施密特触发器,施密特触发器是什么意思 施密特触发器也有两个稳定状态,但与一般触发器不同的是,施密特触发器采用电位
    发表于 03-08 14:14 1937次阅读

    触发器的分类, 触发器的电路

    触发器的分类, 触发器的电路 双稳态器件有两类:一类是触发器,一类是锁存。锁存触发器的原
    发表于 03-09 09:59 1658次阅读

    什么是边沿触发器_边沿D触发器介绍

    边沿触发器,指的是接收时钟脉冲CP 的某一约定跳变(正跳变或负跳变)来到时的输入数据。在CP=l 及CP=0 期间以及CP非约定跳变到来时,触发器不接收数据的触发器。具有下列特点的触发器
    发表于 01-31 09:02 7.2w次阅读
    什么是边沿<b class='flag-5'>触发器</b>_边沿D<b class='flag-5'>触发器</b>介绍

    触发器的作用_触发器的特点介绍

    本文开始介绍了触发器的定义和触发器的特点,其次阐述了触发器的分类和触发器的作用,最后介绍了触发器的工作原理。
    发表于 03-27 17:35 2.2w次阅读

    电平触发器,脉冲触发器和边沿触发器触发因素是什么

    脉冲触发器由两个相同的电平触发的SR触发器组成,其中左SR触发器成为主触发器,右手侧称为从触发器
    的头像 发表于 02-11 10:56 9244次阅读
    电平<b class='flag-5'>触发器</b>,脉冲<b class='flag-5'>触发器</b>和边沿<b class='flag-5'>触发器</b>的<b class='flag-5'>触发</b>因素是什么

    t触发器和jk触发器的区别和联系

    触发器是数字电路中常用的组合逻辑电路,在现代电子系统中有着广泛的应用。其中,最常用的两种触发器是T触发器和JK触发器。本文将详细介绍T触发器
    的头像 发表于 02-06 14:04 5784次阅读

    t触发器与d触发器的区别和联系

    在数字电路设计中,触发器是一种非常重要的存储元件,用于存储一位二进制信息。触发器的种类很多,其中最为常见的是T触发器(Toggle Flip-Flop)和D触发器(Data Flip-
    的头像 发表于 08-11 09:37 2194次阅读

    t触发器变为d触发器的条件

    在数字电路设计中,触发器是一种非常重要的存储元件,用于存储一位二进制信息。触发器的种类很多,其中最为常见的有JK触发器、D触发器和T触发器
    的头像 发表于 08-22 10:33 1099次阅读

    d触发器和jk触发器的区别是什么

    引言 数字电路是现代电子技术的基础,广泛应用于计算机、通信、控制等领域。触发器是数字电路中的一种基本逻辑元件,具有存储和传递信息的功能。 触发器的基本概念 触发器是一种具有记忆功能的数字电路元件
    的头像 发表于 08-22 10:37 1266次阅读

    怎么用jk触发器变成t触发器

    将JK触发器变成T触发器,主要涉及到对JK触发器的输入端口进行适当的连接和配置,以实现T触发器的逻辑功能。以下是将JK触发器转换为T
    的头像 发表于 08-28 09:41 1671次阅读

    rs触发器的工作原理 rs触发器和sr触发器的区别

    RS触发器(Reset-Set触发器)和SR触发器(Set-Reset触发器)是数字电路中常用的两种基本触发器。它们在逻辑功能和应用上有所不
    的头像 发表于 10-21 10:06 1746次阅读