• 代码综合后的电路对比(不定期更新)


      这里来记录一下相似代码之间的不同差异,比如同步复位与异步复位触发器的对比,上升沿复位和下降沿复位的对比等等。这里主要使用ISE的综合引擎。直接附上代码和综合后电路图,有些会有部分讲解。

     

    一、异步复位与同步复位

      我在复位电路里面讲解了同步复位和异步复位的区别,这里就不详细介绍了,链接如下:http://www.cnblogs.com/IClearner/p/6683100.html  

      (1)异步复位

    异步复位的代码如下所示:

    module DFF1(
      input clk,
      input rst_n,
      input d,
      output reg q
    );
    
    always@(posedge clk or negedge rst_n)
      if(!rst_n)
        q <= 0; //异步清 0,低电平有效
      else
        q <= d;
    
    endmodule

     

     综合得到的电路图如下所示:

     

     可以看到使用了一个反相器单元和一个触发器单元;从代码中我们可以推断出,这是一个电平有效的、异步复位触发器。

     

      (2)同步复位

    同步复位触发器代码如下所示,注意黑体部分

     

    module DFF2(
      input clk,
      input rst_n,
      input d,
      output reg q
    );
    
    always@(posedge clk )//注意这里有所不同
      if(!rst_n)
        q <= 0; //同步清 0,低电平有效
      else
        q <= d;
    
    endmodule

     

     综合得到的电路如下所示:

     

    我们可以看到,也是由一个反向器单元和一个触发器单元构成,注意,这里的触发器跟上面的触发器显然不是同一个类型的触发器,管脚名称改变了;结合代码我们可以知道,这个触发器是电平触发、同步复位的触发器(由于是输入信号是低电平有效,所以加了个反相器)。

     

     

    二、不同电平之间的复位差异

      (1)高电平触发的异步复位VS低电平触发的异步复位

    ①高电平触发的异步复位(异步置位)

    代码如下所示:

     

     1 module DFF3(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 
     8 always@(posedge clk or posedge rst_r)
     9   if(rst_r)
    10     q <= 0; 
    11   else
    12     q <= d;
    13 
    14 endmodule
    DFF3

     

    综合得到的电路如下所示:

    根据代码,容易推断得出这是一个电平触发、异步复位的触发器(或者叫异步置位),这也与前面的内容相符合(高电平触发复位,所以不用加反相器)。

     

     

    ②低电平触发的异步复位

    代码和电路跟  一(1)的代码和电路相同,这里不进行重述。

     

      (2)高电平触发的同步复位VS低电平触发的同步复位

    ①高电平触发的同步复位

    代码如下所示:

     

     1 module DFF4(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 
     8 always@(posedge clk )
     9   if(rst_r)
    10     q <= 0; 
    11   else
    12     q <= d;
    13 
    14 endmodule

     

    综合得到的电路如下所示:

    可以知道,这是一个高电平有效、同步复位的触发器单元。

     

    ②低电平触发的同步复位

    代码和电路同一(2),这里不进行重述

     

     

    三、阻塞赋值和非阻塞赋值

      (1)阻塞赋值综合的触发器

    代码如下所示,这里为了使用高电平触发的触发器单元,写出高电平复位:

     1 module DFF_chain(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 reg reg_m ;
     8 always @(posedge clk )//high level reset,synchronization
     9   if(rst_r)begin
    10         reg_m = 0;//block
    11        q = 0; 
    12   end   else begin
    13         reg_m = d;
    14         q = reg_m ;
    15   end
    16 endmodule

    综合得到的电路如下所示:

    可以看到,综合得到只有一个触发器,中间的触发器变量reg_m被优化掉了,只剩下q这个触发器。

     

      (2)换个顺序的非阻塞赋值的触发器

    把后面的这两个语句对调一下,同时把中间的变量改个名字,改成reg_block(这里改名字只是为了区分后面的非阻塞赋值的情况)

    即要综合的代码如下所示:

     1 module DFF_chain(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 reg reg_block ;
     8 always @(posedge clk )//high level reset,synchronization
     9   if(rst_r)begin//block
    10         reg_block = 0;
    11        q = 0; 
    12   end   else begin //here has changed
    13         q = reg_block ;
    14         reg_block = d;        
    15   end
    16 endmodule

     

     综合得到的电路如下所示:

      可以看到,调换顺序之后,得到了我们我们想要的触发器链。

    结论:描述时序逻辑使用阻塞赋值可能得到正确的结果,也可以得到不正确的结果,因此时序逻辑不建议使用阻塞赋值

     

     

     

      (3)非阻塞赋值综合的触发器

     代码如下所示:

     1 module DFF_chain(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 reg reg_m ;
     8 always @(posedge clk )//high level reset,synchronization
     9   if(rst_r)begin
    10         reg_m <= 0;//non block 
    11        q <= 0; 
    12   end   else begin
    13         reg_m <= d;
    14         q <= reg_m ;
    15   end
    16 endmodule

     

      综合得到的电路如下所示:

    从电路图中可以看到,综合得到了两个触发器,中间的触发器reg_m被保留下来了,达到了我们预想中的触发器链。

     

      (4)换个顺序后的非阻塞赋值

    跟前面的阻塞赋值一样,我们换一下顺序,代码如下所示:

     1 module DFF_chain(
     2   input clk,
     3   input rst_r,
     4   input d,
     5   output reg q
     6 );
     7 reg reg_nonblock ;
     8 always @(posedge clk )//high level reset,synchronization
     9   if(rst_r)begin//non block
    10         reg_nonblock <= 0;
    11        q <= 0; 
    12   end   else begin
    13         q <= reg_nonblock ;
    14         reg_nonblock <= d;        
    15   end
    16 endmodule

     

    综合得到的电路如下所示:

    从电路中可以看到,即使调换了顺序,电路还是我们需要的触发器链。

     

    结论:描述时序逻辑,使用非阻塞赋值可以得到正确的结果,因此时序逻辑推荐使用非阻塞赋值

     

      (5)描述组合逻辑电路时的阻塞赋值和非阻塞赋值

    阻塞赋值描述组合逻辑(加法器),代码如下所示:

     1 module Adder(
     2   input a,
     3   input b,
     4   input c,
     5   output reg q
     6 );
     7 reg sum_block ;
     8 always @(* )
     9    begin
    10         sum_block = a + b  ;
    11         q = sum_block + c;        
    12    end
    13 endmodule

     

    综合得到电路如下所示:

      

    综合得到的电路是一个加法器。

    我们改成非阻塞赋值看看,代码如下所示:

     1 module Adder(
     2   input a,
     3   input b,
     4   input c,
     5   output reg q
     6 );
     7 reg sum_block ;
     8 always @(* )
     9    begin
    10         sum_block <= a + b  ;
    11         q <= sum_block + c;        
    12    end
    13 endmodule

    综合得到的电路:

    综合得到的电路也是一个加法器。

    因此可以冒险地得到一个结论,无论是阻塞赋值还是非阻塞赋值,都可以描述组合逻辑,但是一般情况下,我们推荐使用阻塞赋值,一方面是对仿真有用,另一方面是区别于描述时序逻辑的非阻塞赋值。

    最后我尝试着在同一个块中使用阻塞赋值和非阻塞赋值,ISE的综合器报错。

     

  • 相关阅读:
    Thinkphp的import使用方法
    bug1
    setTimeout关于函数名做参数的问题
    ubuntu-12.04.5安装cacti笔记
    第七周作业
    第六周作业
    第五周作业
    第四周编程总结
    2019年春季学期第三周作业
    第二周编程总结
  • 原文地址:https://www.cnblogs.com/IClearner/p/7188875.html
Copyright © 2020-2023  润新知