前言

注:本文首发自FPGA逻辑设计回顾(3)多比特信号上升沿检测的设计方式与陷阱?
在总结本文最后的多比特上升沿检测之前,我们先把备用知识讲清楚,摊开来,以免造成模糊不清的默许!

逻辑运算符与位元运算符

从表面上来看,逻辑运算符与位元运算符之间的区别就是一个符号写法的问题,例如:&&,&,||,|,!,~
事实上,我们应该真正的从含义上理解它们:

  • 所谓的逻辑运算符就是逻辑上的运算,那它的结果也就是真和假之分,即false and true,或者1’b1 and 1’b0,它是1比特的布尔值。
  • 而位元运算,其实就是单比特之间的逻辑运算而已,多比特的话就按位进行逻辑运算,例如按位与(&),按位或(|)以及按位非(~)。
    有关这方面的语法,我以前有很多博客,例如:
    Verilog中的逻辑运算符与按位运算符的区分

或者之前的专栏:
数字设计基础教程

由于逻辑运算符与位元运算符之间的区别在此,但这也仅仅是针对多比特信号才有的区别,对于单比特信号,其实结果是一样的,我们认为都行。

下面给出几组测试,来区分逻辑运算符以及位元运算符之间的区别:

下面给出仿真:

可见,逻辑运算符得到的结果总是1bit的,而位元运算符得到的结果和原输入数据位数一致,这和我们的认识也是相符合的。

下面给出上述设计以及仿真对应的RTL代码:

RTL设计代码:

module bitwise_test(input   [3:0]   in1,input   [3:0]   in2,output  [3:0]   out_bitwise_and,output  [3:0]   out_bitwise_or,output  [3:0]   out_bitwise_not,        output          out_logic_and,output          out_logic_or,output          out_logic_not           );assign out_bitwise_and = in1 & in2 ;assign out_logic_and = in1 && in2 ;assign out_bitwise_or = in1 | in2 ;assign out_logic_or = in1 || in2 ;assign out_bitwise_not = ~in1 ;assign out_logic_not = !in1 ;    endmodule

Testbench代码:


module sim_bitwise_test();reg [3:0] in1   ;reg [3:0] in2   ;wire  [3:0]   out_bitwise_and   ;wire  [3:0]   out_bitwise_or    ;wire  [3:0]   out_bitwise_not   ;        wire          out_logic_and     ;wire          out_logic_or      ;wire          out_logic_not      ;  initial beginin1 = 4'b1001;in2 = 4'b1100;#5in1 = 4'b1000;in2 = 4'b1101;endbitwise_test u_bitwise_test(.in1             ( in1             ),.in2             ( in2             ),.out_bitwise_and ( out_bitwise_and ),.out_bitwise_or  ( out_bitwise_or  ),.out_bitwise_not ( out_bitwise_not ),.out_logic_and   ( out_logic_and   ),.out_logic_or    ( out_logic_or    ),.out_logic_not   ( out_logic_not   )
);endmodule

其实说起位元运算符以及逻辑运算符,在硬件描述语言中,还要一种不得不谈起,这几者算是同宗兄弟,只是完成者不同的使命,那便是缩位运算符:

HDLBits 系列(6)(Reduction)缩位运算符

其运算方式也十分简单,例如:

  • &a [3:0] // AND:a [3]&a [2]&a [1]&a [0]

  • | b [3:0] //或:b [3] | b [2] | b [1] | b [0]。 相当于(b [3:0]!= 4’h0)

  • ^ c [2:0] // XOR:c [2] ^ c [1] ^ c [0]

具体看我的其他博文吧,这里就不细讲了。

单比特信号上升沿检测

对于一个bit信号的上升沿检测,十分容易理解,实现方式也只有一种,那就是延迟,再逻辑运算,打拍得到结果。
例如,如下RTL原理图可以很清楚的说明问题:
RTL原理图:


下面是对上述电路的仿真:

仿真波形:

对于上升沿检测,我们需要注意的是:FPGA设计心得(10)关于行为仿真的一点观点

我的观点只有一个,那就是我们在行为仿真的时候不要在正正好好时钟边沿处给数据,这是由于仿真工具对边沿处数据的不同处理方式,可能会导致得不到你想要的结果。具体还是看上面的链接吧,这里不再重提了。

下面附上上述设计以及仿真的RTL代码:

RTL设计:

module pos_detect(input   wire    clk     ,input   wire    rst     ,input   wire    in_a    ,output  reg     in_pos );reg     reg_in_a    ;always@(posedge clk or posedge rst) beginif(rst) beginreg_in_a <= 1'b0    ;endelse beginreg_in_a <= in_a    ;endendalways@(posedge clk or posedge rst) beginif(rst) beginin_pos <= 1'b0    ;endelse beginin_pos <= ~reg_in_a && in_a    ;endendendmodule

Testbench仿真:


module pos_detect_tb();reg     clk     ;reg     rst     ;reg     in_a    ;wire    in_pos  ;   always begin# 2 clk     = ~clk;endinitial beginclk     = 1'b0;rst     = 1'b1;in_a    = 1'b0;#10rst     = 1'b0;#20in_a    = #(0.1) 1'b1;#20in_a    = #(0.1) 1'b0;endpos_detect u_pos_detect(.clk   ( clk   ),.rst   ( rst   ),.in_a  ( in_a  ),.in_pos  ( in_pos  ));endmodule

多比特信号上升沿检测

对于多比特上升沿的检测,就要区分使用使用逻辑运算符和位元运算符了,如果用错了的话,肯定得不到想要的结果,这也就是所谓的小陷阱吧,专坑基础不牢或者马马虎虎的人。

除此之外,还有对于对比特的设计方式有如下几种,设计到for循环的使用,generate for循环的使用以及正常用法。
对于for循环以及generate for循环的含义,我在过去的博客上也多次写过,例如:
HDLBits 系列(7)对for循环以及generate for的各种实践

这篇文章对于generate for的使用提到一句比较关键的话就是generate for内部的语句要有一个名字:它的含义就是讲一个模块多次使用,形成多个模块的效果,属于并行的效果;可具体见博文,体会含义。
例如,使用generate for对全加器的多次例化,得到的文件结构是这样的:

相应的RTL原理图也如此:

使用三种方式对同一逻辑进行实现,部分RTL设计如下:
使用generate for形式:

    genvar j;generate for(j = 0; j <= 3; j = j + 1) beginalways@(posedge clk or posedge rst) begin:pos_detect3if(rst) beginreg_in3[j] <= 1'b0;out_pos3[j] <= 1'b0;endelse beginreg_in3[j] <= in1[j];out_pos3[j] <= ~reg_in3[j] & in1[j];endend            end

至于使用for语句:

 always@(posedge clk or posedge rst) begin : pos_detect1if(rst) beginreg_in1 <= 4'h0;out_pos1 <= 4'b0;end else beginfor(i = 0; i <= 3; i = i + 1) begin : bits_pos_reg_in1[i] <= in1[i]    ;out_pos1[i] <= ~reg_in1[i] & in1[i]   ;endend       end

以及普通的实现方式:

always@ (posedge clk or posedge rst) begin : pos_detect2if(rst) beginreg_in2 <= 4'b0;out_pos2 <= 4'b0;endelse beginreg_in2 <= in1;out_pos2 <= ~reg_in2 & in1;endend

也能实现同样的功能,例如对其仿真示意图一致:

生成的RTL原理图虽略有差异:

但本质上还是一致的,且看综合示意图:

可见综合出来的结果,三者的结果采样了同一个中间过程,也就是最终在FPGA上的实现方式完全一致。

再给出implementation后的结果:


不用多想,结果也是一致的,虽然第2级触发器分开使用了不同的触发器,那是因为要分配给不同的输出,同时输出而非分时输出,也在意料之内,结构一致。

最终在FPGA中实现的电路也是这样的,实现是最接近底层的一级。

下面给出上述设计以及仿真的代码:

module bits_pos_detect(input   wire          clk,input   wire          rst,input   wire [3:0]    in1,output  reg  [3:0]    out_pos1,output  reg  [3:0]    out_pos2,output  reg  [3:0]    out_pos3   );reg     [3:0]   reg_in1 ;reg     [3:0]   reg_in2 ;reg     [3:0]   reg_in3 ;integer     i   ;always@(posedge clk or posedge rst) begin : pos_detect1if(rst) beginreg_in1 <= 4'h0;out_pos1 <= 4'b0;end else beginfor(i = 0; i <= 3; i = i + 1) begin : bits_pos_reg_in1[i] <= in1[i]    ;out_pos1[i] <= ~reg_in1[i] & in1[i]   ;endend       endalways@ (posedge clk or posedge rst) begin : pos_detect2if(rst) beginreg_in2 <= 4'b0;out_pos2 <= 4'b0;endelse beginreg_in2 <= in1;out_pos2 <= ~reg_in2 & in1;endendgenvar j;generate for(j = 0; j <= 3; j = j + 1) beginalways@(posedge clk or posedge rst) begin:pos_detect3if(rst) beginreg_in3[j] <= 1'b0;out_pos3[j] <= 1'b0;endelse beginreg_in3[j] <= in1[j];out_pos3[j] <= ~reg_in3[j] & in1[j];endend            endendgenerateendmodule

测试平台:

module bits_pos_detect_tb();reg                 clk;reg                 rst;reg     [3:0]       in1;wire    [3:0]       out_pos1;wire    [3:0]       out_pos2;wire    [3:0]       out_pos3;initial beginclk = 0;forever begin#5 clk = ~clk;endend   initial beginrst = 1;in1 = 4'h0;#18 rst = 0;in1 = #(0.5) 4'b1011;#20in1 = #(0.5) 4'b0000;#18in1 = #(0.5) 4'b1101;#20in1 = #(0.5) 4'b1001;#18in1 = #(0.5) 4'b1010;endbits_pos_detect u_bits_pos_detect(.clk      ( clk      ),.rst      ( rst      ),.in1      ( in1      ),.out_pos1 ( out_pos1 ),.out_pos2 ( out_pos2 ),.out_pos3  ( out_pos3  ));endmodule

FPGA逻辑设计回顾(3)多比特信号上升沿检测的设计方式与陷阱?相关推荐

  1. 卫星跟踪算法c语言,以SoC FPGA为设计平台的北斗卫星信号跟踪算法的设计

    0 引言 全球导航卫星系统(Global Navigaon Satellite System,GNSS)是维护国家安全.发展经济的重要基础设施,是体现国家综合国力以及现代化大国国际影响力的重要标志 . ...

  2. Verilog信号上升沿检测

    在FPGA开发的面试中可能会碰到检测上升沿和下降沿的题目.以上升沿为例进行分析. 上升沿是信号从低电平变化为高电平的时候,因此我们可以将信号的上一个状态和下一个状态进行采样保存,然后来判断是都是从0变 ...

  3. FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之Toggle同步器

    文章目录 前言 脉冲反馈展宽同步器技术补充说明 RTL代码 行为仿真 低电平脉冲的展宽处理 切换同步器的原理与实现 RTL实现 前言 本文首发自:FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之 ...

  4. FPGA逻辑设计回顾(6)多比特信号的CDC处理方式之异步FIFO

    文章目录 前言 异步FIFO的概念 异步FIFO为什么可以解决CDC问题? 异步FIFO的RTL实现 参考资料 前言 异步FIFO是处理多比特信号跨时钟域的最常用方法,简单来说,异步FIFO是双口RA ...

  5. FPGA逻辑设计回顾(1)新手易犯的逻辑综合错误之always块

    前言 注:本文首发自FPGA逻辑设计回顾(1)新手易犯的逻辑综合错误之always块 本文中用到了如下的小标题: "心中有路"与综合推断 "心中无路"与无从推断 ...

  6. FPGA逻辑设计回顾(12)RAM以及ROM的RTL设计及其验证

    前言 本文首发:FPGA逻辑设计回顾(12)RAM以及ROM的RTL设计及其验证 RAM以及ROM在FPGA中的实现大体有两种方式,一种是使用IP核定制,一种是RTL设计. 也许有人会反驳,那原语呢? ...

  7. FPGA逻辑设计回顾(9)DDR的前世今生以及演变过程中的技术差异

    文章目录 前言 DDR的前世SDRAM DDR的今生以及演变版本:DDR/DDR2/DDR3 DDR/DDR2/DDR3/DDR4之间简单对比 速度对比 电压对比 延迟对比 预取差异 电阻端接对比 物 ...

  8. FPGA逻辑设计回顾(10)DDR/DDR2/DDR3中的时序参数的含义

    前言 本文首发自:FPGA逻辑设计回顾(10)DDR/DDR2/DDR3中的时序参数的含义 上篇文章:FPGA逻辑设计回顾(9)DDR的前世今生以及演变过程中的技术差异有提到,制造商会以一系列由破折号 ...

  9. FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

    文章目录 前言 RAM IP的定制 Xilinx的IP定制位置 Block RAM的定制过程 第一页 第二页 第三页 第四页 第五页 Block RAM的延迟讨论 ROM IP核的定制 总结 前言 本 ...

最新文章

  1. python ftp文件传输服务端
  2. 单链表中如何快速删除p指向的节点?( 简单方法:复杂度为O(1) )
  3. java log 配置,java日志系统--log4j配置解析过程,源码分析
  4. Windows 8最值得期待的8大特性
  5. Boost:bimap双图的structured_pair的测试程序
  6. linux 433发送驱动
  7. TCP 协议如何解决粘包、半包问题
  8. Google-Guava-EventBus源码解读
  9. leetcode100. 相同的树
  10. treeReduce和reduce
  11. Spring和Quartz配合实现定时任务
  12. springCloud工作笔记090---SpringCloud_redis配置多数据源_redis多数据源
  13. DBS-Function:f_GetPy
  14. aspen plus v11使用教程_Aspen Plus11.0安装教程
  15. prime算法-最小生成树
  16. 白话空间统计之二十五:空间权重矩阵(四)R语言中的空间权重矩阵(3):反距离权重
  17. 百度杀毒软件2013低调发布 仅面向泰国市场推出
  18. Gazebo [Err] [REST.cc:205] Error in REST request 问题的解决
  19. html 按钮 水波纹,点击按钮出现水波纹动画
  20. 【面试】腾讯优图-计算机视觉

热门文章

  1. OpenGL选择机制的一点讨论
  2. 客户需求分析8个维度_CRM准确数据分析,把控客户需求
  3. final修饰的变量是引用不能改变还是引用的对象不能改变
  4. json 字符串传到action之后的处理,遍历. 练习代码片
  5. java s0 s1_Java GC 变量含义(S0 S1 E O P YGC YGCT FGC FGCT GCT)详解
  6. mybatis对mysql if函数_Mybatis使用mysql函数if出现错误
  7. ie对java的设置字体,css3文字特效和浏览器兼容性
  8. oracle负载均衡方案,Oracle负载均衡配置代码
  9. r语言ggplot怎么把多个维度数据合并在一个图中表示_R语言作图——Histogram
  10. 利用计算机技术教学图片,教育教学论文 科学学科如何利用计算机技术提高教学效率.doc...