情境:

  FPGA里面计数器需要复位(计数值置零),与计数器状态有关的行为是状态机控制的,即状态机为CLEAR_TIMER状态时,计数器才完成清零动作。

  清零有两个条件:(1)计数器值溢出(达到OVF门限);(2)清零信号有效(1有效)。这两个条件是独立的,没有先后关系的约束。

问题是:如何写Verilog语句,才使得这两个触发的优先级相同?

有两个思路:

一个是:

  1. always@(posedge clk)begin
      if(!rst_n)begin
        stat_preload <= STAT_IDLE;
      end
      else begin
        //*** Combined Transition
        if((tim_cnt >= TIIM_OVF) || (1'b1 == tim_rst))begin // OR
          stat_preload <= STAT_CLEAR_TIMER;
        end
        else begin
          stat_preload <= stat_preload; // Status Latch
        end
      end
    end

另一个:

  1. always@(posedge clk)begin  
      if(!rst_n)begin
        stat_preload <= STAT_IDLE;
      end
      else begin
        //*** Separate Transition
        if(tim_cnt >= TIM_OVF)begin
  2.       stat_preload <= STAT_CLEAR_TIMER;
  3.     end
  4.     else begin
  5.       stat_preload <= stat_preload; // Stay
  6.     end
  7.     if(1'b1 == tim_rst)begin
  8.       stat_preload <= STAT_CLEAR_TIMER;
  9.     end
  10.     else begin
  11.       stat_preload <= stat_preload; // Stay
  12.     end
      end
    end

这两种写法的区别在于:第一种,状态转移语句放在两个条件参与的单个if选择结构里面;第二种,状态转移语句放在分别的两个if选择结构里面。

状态转移图中表现为这样的两种情况:

实现和测试:

上述两种的代码和综合结果如下:

  1. module top(
  2. rst_n,
  3. clk,
  4. X,
  5. Y,
  6. din_A,
  7. dout
  8. );
  9.  
  10. //****************************************
  11. // Port Def.
  12. //****************************************
  13. input wire rst_n;
  14. input wire clk;
  15.  
  16. input wire X; // Conditions
  17. input wire Y;
  18.  
  19. input wire[:] din_A;
  20.  
  21. output wire[:] dout;
  22.  
  23. //****************************************
  24. // Variables
  25. //****************************************
  26. reg[:] dout_reg;
  27.  
  28. //****************************************
  29. // Behaviour
  30. //****************************************
  31.  
  32. assign dout = dout_reg;
  33.  
  34. always@(posedge clk)begin
  35. if(!rst_n)begin
  36. dout_reg <= 'b0;
  37. end
  38. else begin
  39. if(('b1 == X) || (1'b1 == Y))begin
  40. dout_reg <= din_A;
  41. end
  42. else begin
  43. dout_reg <= dout_reg;
  44. end
  45. end
  46. end
  47.  
  48. endmodule

  1. module top(
  2. rst_n,
  3. clk,
  4. X,
  5. Y,
  6. din_A,
  7. dout
  8. );
  9.  
  10. //****************************************
  11. // Port Def.
  12. //****************************************
  13. input wire rst_n;
  14. input wire clk;
  15.  
  16. input wire X; // Conditions
  17. input wire Y;
  18.  
  19. input wire[:] din_A;
  20.  
  21. output wire[:] dout;
  22.  
  23. //****************************************
  24. // Variables
  25. //****************************************
  26. reg[:] dout_reg;
  27.  
  28. //****************************************
  29. // Behaviour
  30. //****************************************
  31.  
  32. assign dout = dout_reg;
  33.  
  34. always@(posedge clk)begin
  35. if(!rst_n)begin
  36. dout_reg <= 'b0;
  37. end
  38. else begin
  39. if('b1 == X)begin
  40. dout_reg <= din_A;
  41. end
  42. else begin
  43. dout_reg <= dout_reg;
  44. end
  45. if('b1 == Y)begin
  46. dout_reg <= din_A;
  47. end
  48. else begin
  49. dout_reg <= dout_reg;
  50. end
  51. end
  52. end
  53.  
  54. endmodule

综合器是Quartus 15.1内置的。

可以看到,第二种写法的综合结果让输入信号X没有驱动逻辑了,这样就与需求不符。

原因是什么?

第二种(分开if)情况下,虽然赋值语句都是非阻塞的<=,但是由于if语句放在顺序的begin::end结构内,所以判断和执行都是顺序处理的,状态转移和状态停留操作是一模一样的,所以X条件被省略了。

为了验证这个结论,在X,Y两个条件的基础上再加R,S两个条件,进行X,Y,R,S的顺序if,然后查看结果:

  1. module top(
  2. rst_n,
  3. clk,
  4. X,
  5. Y,
  6. R,
  7. S,
  8. din_A,
  9. dout
  10. );
  11.  
  12. //****************************************
  13. // Port Def.
  14. //****************************************
  15. input wire rst_n;
  16. input wire clk;
  17.  
  18. input wire X; // Conditions
  19. input wire Y;
  20. input wire R;
  21. input wire S;
  22.  
  23. input wire[:] din_A;
  24.  
  25. output wire[:] dout;
  26.  
  27. //****************************************
  28. // Variables
  29. //****************************************
  30. reg[:] dout_reg;
  31.  
  32. //****************************************
  33. // Behaviour
  34. //****************************************
  35.  
  36. assign dout = dout_reg;
  37.  
  38. always@(posedge clk)begin
  39. if(!rst_n)begin
  40. dout_reg <= 'b0;
  41. end
  42. else begin
  43. if('b1 == X)begin
  44. dout_reg <= din_A;
  45. end
  46. else begin
  47. dout_reg <= dout_reg;
  48. end
  49. if('b1 == Y)begin
  50. dout_reg <= din_A;
  51. end
  52. else begin
  53. dout_reg <= dout_reg;
  54. end
  55. if('b1 == R)begin
  56. dout_reg <= din_A;
  57. end
  58. else begin
  59. dout_reg <= dout_reg;
  60. end
  61. if('b1 == S)begin
  62. dout_reg <= din_A;
  63. end
  64. else begin
  65. dout_reg <= dout_reg;
  66. end
  67. end
  68. end
  69.  
  70. endmodule

显然,只有S条件有效了。

结论:顺序块begin::end中的语句是顺序执行的。

Verilog的非阻塞语句放到顺序块中,综合出来怎样的逻辑电路?的更多相关文章

  1. verilog中阻塞复制,非阻塞复制,顺序块,并行块之间的关系

    这几个概念是不一样的 顺序块:顺序块中的语句是按顺序执行的,每条语句中的延迟值是与其前一条语句执行的仿真时间有关. 并行块:并行块语句是并行执行的,它里面的每条语句中指定的延迟值都是相对于语句块开始执 ...

  2. Verilog HDL中阻塞语句和非阻塞语句的区别

    在Verilog中有两种类型的赋值语句:阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”).正确地使用这两种赋值语句对于Verilog的设计和仿真非常重要. Verilog语言中讲的阻塞赋值与非 ...

  3. Verilog-FPGA硬件电路设计之一——if语句优先级(always块中的阻塞赋值生成的组合逻辑电路是按照顺利执行的)

    出处:http://bbs.ednchina.com/BLOG_ARTICLE_3013262.HTM 综合软件:Quartus II 一.有优先级的if语句 if..else if.. else i ...

  4. Verilog中的阻塞与非阻塞

    这篇文档值得阅读 按说阻塞与非阻塞是Verilog中最基本的东西,也是老生常谈.但是最近看到很多程序里用到阻塞语句竟然不是很明白,说到底是从来没有自己仔细分析过.当然一般情况程序中也是推荐用非阻塞的. ...

  5. Verilog之阻塞赋值非阻塞赋值

    verilog设计进阶 时间:2014年5月6日星期二 主要收获: 1. 阻塞赋值与非阻塞赋值: 2. 代码测试: 3. 组合逻辑电路和时序逻辑电路. 阻塞赋值与非阻塞赋值: 1. 阻塞赋值" ...

  6. 07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的:掌握阻塞赋值与非阻塞赋值的区别 实验平台:无 实验原理:     阻塞赋值,操作符为"=","阻塞"是指在进程语句( ...

  7. 用Java实现非阻塞通信

    用ServerSocket和Socket来编写服务器程序和客户程序,是Java网络编程的最基本的方式.这些服务器程序或客户程序在运行过程中常常会阻塞.例如当一个线程执行ServerSocket的acc ...

  8. 非阻塞同步算法与CAS(Compare and Swap)无锁算法

    锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...

  9. 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法

    转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...

随机推荐

  1. Follow somebody

    networkersdiary A personnel blog with Network Engineering articles https://networkersdiary.com/cisco ...

  2. Embedded Packet Capture (EPC)

    Embedded Packet Capture (EPC)是一个很好的抓包工具,在排障的时候,需要在线抓包的情况下,是一个非常好的选择. EPC在IOS和IOS-XE都是支持,不过,不同平台下有版本的 ...

  3. 开源代码License

    参考:https://mp.weixin.qq.com/s/Q29NGDIbyCwm6KiAKqI46A

  4. 01背包第k最优解

    附题目链接:Bone Collector II Input The first line contain a integer T , the number of cases.Followed by T ...

  5. Python3.5学习之旅——day4

    本节内容 1.装饰器 2.迭代器与生成器 3.内置方法 4.软件目录结构规范 一.装饰器 装饰器是一个用来装饰其他函数的工具,即为其他函数添加附加功能,其本质就是函数. 装饰器需要遵循的以下两个原则: ...

  6. Vulnhub_DC8 记录

    目录 DC8 经验 & 总结 步骤流水 信息搜集 80端口 获取Shell 提权 DC8 经验 & 总结 对页面的功能和对应的url要敏感. 所有的功能都要测试,要雨露均沾. 提示说的 ...

  7. Ubuntu将Python3软连接到Python

    sudo ln -s /usr/bin/python3 /usr/bin/python

  8. sparkRDD:第3节 RDD常用的算子操作

    4.      RDD编程API 4.1 RDD的算子分类 Transformation(转换):根据数据集创建一个新的数据集,计算后返回一个新RDD:例如:一个rdd进行map操作后生了一个新的rd ...

  9. Codeforces Round #580 (Div. 2)D(思维,Floyd暴力最小环)

    #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;const int maxn=300;cons ...

  10. kafka控制测试发送接收消息

    kafaka,生产者:./kafka-console-producer.sh --broker-list localhost:9092 --topic testTopic 消费者:./kafka-co ...