FPGA开发流程:综合(二)

目录

1.连续赋值语句

2. 过程赋值语句

   2.1 阻塞赋值

   2.2 非阻塞赋值

   2.3 赋值对象

   2.4 赋值限制

3.逻辑运算符

4. 算术运算符

   4.1 无符号算术

  4.2 有符号数算术

  4.3  进位的建模

5. 关系运算符

  6. 相等性运算符

  7. 移位运算符

  8. 向量运算

  9. 部分选取

  10. 位选择

  11. 条件表达式

  12.  always语句

  13. if语句

  14. Case语句

  15. 再谈锁存器推导

  16. 循环语句

  17. 触发器建模

  18.  再谈阻塞与非阻塞

  19. 函数

   20.任务

   21. 使用X值和Z值

   22.门级建模

   23. 模块实例化语句

   24.参数化设计


              (2)从Verilog语句到硬件逻辑门的映射,解释了运算符、表达式和赋值语句是如何映射成硬件的


     介绍HDL语句向硬件逻辑门的映射

1.连续赋值语句

      连续赋值语句是Verilog数据流建模的基本语句,用于对线网进行赋值,等价于门级描述,是从更高的抽象角度来对电路进行描述。连续赋值语句必须以关键词assign开始。硬件中,连续赋值语句表示用等号右端的表达式所推导出的逻辑,驱动等号右边的网线。【注】连续赋值语句中被赋值的对象总是受组合逻辑驱动的网线

FPGA开发流程:综合(二)_第1张图片

      综合出的网表为图1所示

图1:连续赋值语句综合出的组合逻辑电路

延迟: 如果在连续赋值语句中加入延迟,综合器会选择忽略。比如

assign #2 StatOut = ~StatIn;

综合后也是图1所示。 

2. 过程赋值语句

      过程赋值语句只能出现在always块中(也能出现在初始化语句initial语句中,但initial 语句不可综合),而连续赋值语句需要用到关键词assign。过程赋值语句有两种方式:

  •      a) 阻塞赋值;
  •      b) 非阻塞赋值 。

   2.1 阻塞赋值

    阻塞赋值  “=”

module Blocing (Preset ,Count);
input [2:0] Preset ;
output[3:0] Count  ;

reg [3:0] Count ;

always@(Preset)
   Count = Preset+1 ;
endmodule

综合后的网表如下: 

FPGA开发流程:综合(二)_第2张图片 图2:阻塞赋值得到的组合逻辑电路

        会不会有疑问reg型Count为什么没有综合出触发器?看2.3节 

   2.2 非阻塞赋值

    非阻塞赋值  “<=   ”

module NonBlocking(RegA, RegB, Mask);
input [3:0] RegA ,Mask;
output[3:0] RegB;
reg [3:0]   RegB;

always@(RegA or Mask)
begin
    Reg <= RegA & Mask ;
end
endmodule

综合后的网表如下: 

FPGA开发流程:综合(二)_第3张图片 图3:由非阻塞赋值得到的组合逻辑电路

 

      会不会有疑问,reg型的RegB为什么没有综合出触发器?看2.3节。 

      上面的两种过程赋值都是在always块中,用不同的赋值方式实现组合逻辑。可以看出,单从一个赋值语句看,赋值语句的阻塞与非阻塞性质,并不会造成从赋值语句本身生成的组合逻辑电路有什么不同,但是会影响以后对赋值 结果的使用(后续介绍)。即其他组合逻辑或时序逻辑中才使用该赋值结果的时候,不同的赋值方式最终的结果会大不相同。

      一般建议是,组合逻辑采用阻塞赋值  =,而时序逻辑进行建模时会使用非阻塞赋值 <= 。但,这并不是说这是唯一的选择。

   2.3 赋值对象

      过程赋值在阻塞与非阻塞方式中,等号右边都会生成逻辑表达式所表达的组合逻辑电路,但等号左边的被赋值对象会被综合成连线、触发器、锁存器,这取决于赋值语句在Verilog HDL代码中上下文环境,这在综合(一)中就说过。如果将上面例子中always模块的敏感列表中换成在时钟控制下执行,那么综合后的网表结果不同。

module NonBlocking(Clk, RegA, RegB, Mask);
input [3:0] RegA ,Mask;
inout       Clk ;
output[3:0] RegB;
reg [3:0]   RegB;

always@(posedge Clk)
begin
    Reg <= RegA & Mask ;
end
endmodule

综合后的网表:

FPGA开发流程:综合(二)_第4张图片 图4: 赋值对象综合成触发器

   2.4 赋值限制

      延迟忽略:阻塞赋值与非阻塞赋值中   所指定的任何形式的延迟,包括延迟控制和语句内的延迟,都会被综合器所忽略。这可能就会导致设计模型与综合出的网表功能不一致。

#5 RegB  <= RegA & Mask ;
//延迟控制 #5 会被综合器忽略

Reg = #2 RegA & Mask ;
//语句内的延迟 #2 也会被忽略

在当个综合模块中,对于阻塞非阻塞使用的另一个限制:对同一个赋值对象,不能既使用阻塞,又使用非阻塞赋值

也就是说,一旦赋值对象在第一次确定了赋值方式,在后面对该对象赋值的时候就只能继续使用这种方式了。下面这个情况就属于非法赋值,是会报错的。

Count = Preset +1 ;
...
...
Count <= Mask    ;

 

3.逻辑运算符

        逻辑运算符就是实现一些逻辑运算,能够直接映射成硬件当中的基本逻辑门。典型的全加器模型描述如下:

module full_adder(Ain ,Bin ,Cin ,Sum ,CarryOut );
input Ain , Bin , Cin ;
output Sum ,CarryOut ;

assign Sum      = (Ain ^ Bin) ^ CarryOut ;
assign CarryOut = (Ain & Bin) | (B & Cin) | (A & Cin) ;

endmodule

综合出网表: 根据逻辑表达式,综合出一一对应的基本逻辑门电路

FPGA开发流程:综合(二)_第5张图片 图5:全加器

4. 算术运算符

     在Verilog设计综合(一)中的介绍过,Verilog HDL中,寄存器类型被解释为无符号数,整数类型(integer型)被解释成二进制补码形式的有符号数,解释时都是最右端的位作为最低有效位。。因此,要综合成无符号算术算符就需要使用寄存器类型,而若是需要得到有符号的算术算符就需要使用整型。

    网线类型被解释为无符号数

   4.1 无符号算术

         下面是对无符号数使用算术运算符:对3位加法器进行建模。运算的操作数都是无符号数,因为输入信号Arb和Bet都是wire型(网线型)

module UnsignedAdder(
      Arb  ,
      Bet  ,
      Lot 
);

input [2:0] Arb  Bet   ;
output[2:0] Lot        ;

assign Lot = Arb + Bet ;

endmodule

综合后网表:

FPGA开发流程:综合(二)_第6张图片 图6: 3位加法器

 

  4.2 有符号数算术

        有符号数用整型表示。

module SignedAdder(
       Arb      ,
       Bet      ,
       Lot  
);
input  [1:0] Arb , Bet ;
output [2:0]   Lot     ;应使用标号

reg [2:0]      Lot     ;

always@(Arb or Bet)
begin : LABEL_A
   //内有局部声明的顺序块
    integer ArbInt , BetInt ;
      ArbInt = -Arb;   //保存负数仅用于表明对有符号数运算量做+运算
      BetInt = -Bet;
      Lot    = ArbInt + BetInt ;
 end
endmodule

综合出的网表 如下:

FPGA开发流程:综合(二)_第7张图片 图7: 有符号加法器

【注意】:有符号数运算的加法器逻辑与无符号数加法器逻辑相同,因为有符号数是用二进制补码形式来表示的,依旧是做加法。

  4.3  进位的建模

        对进位建模一般采取的方法是,输出结果位宽要比运算操作数中较大值的位宽大一位。 另一种可行办法是:加法结果赋值对象是采用进位位拼接(其中明确了哪一位是进位的位)。

FPGA开发流程:综合(二)_第8张图片

5. 关系运算符

        能够综合的关系运算符有: > 、< 、<= 、 >= 。关系运算符的建模与算术运算符相似。对于关系运算符,综合后会产生不同的结果这取决于 被比较的究竟是无符号数还是有符号数!!

  •          若比较的是寄存器类型或网线类型变量(无符号数),则综合出无符号关系运算符;
  •          若比较的是整型变量(integer),则综合出有符号关系运算符。
//无符号数关系运算符
module GreaterThan(A ,B ,Z );
input [3:0]  A ,B  ;
output          Z  ;

assign     Z  =  A[1:0] > B[3:2] ;
endmodule  

       综合后网表:

FPGA开发流程:综合(二)_第9张图片 图8: 无符号关系运算符“>”
//有符号关系运算符

module LessThan(
     ArgA       ,
     ArgB       ,
     ResultZ
);

input    [2:0]      ArgA,Argb ;
output                ResultZ ;
reg                   ResultZ ;
integer     ArgAInt , ArgBint ;

always@(ArgA or ArgB)
begin
    ArgAInt = -ArgA ;
    ArgBInt = -ArgB ;
//保存负值仅用于表明对有符号数进行比较
    ResultZ = ArgAInt <= ArgBint ;
end

     综合出的网表:

FPGA开发流程:综合(二)_第10张图片 图9:有符号关系运算符 <=

  6. 相等性运算符

        能够综合的相等性运算符: == 和!==。还有全等运算符(Case equality):===和非全等运算符(Case inequality):!==,但是这两个是不能综合的

       就 比较究竟是有符号比较还是无符号比较而言,相等性运算符建模的方式也与算术运算符类似。下例中使用了有符号数。注意,此列中相等性算符的运算量都是整型的,因为整型值表示的是有符号数。

module NotEquals(A , B , Z);
input [0:3] A, B ;
output         Z ;
reg            Z ;

always@(A or B)
begin: DF_LABEL
   integer IntA, IntB ;
           IntA = A ;
           IntB = B ;
              Z = IntA != IntB;        
end 
endmodule

综合后网表: 

FPGA开发流程:综合(二)_第11张图片 图10:有符号关系 运算“!=”

 

  7. 移位运算符

               Verilog HDL综合器支持左移“<<”和右移“>>”运算符。而经过移位后空出来的各个位都填补0。移位运算符右边表示移位的位数,可用常量,也可以是变量。这两种情况下,产生的都是组合逻辑。如果移位的位数是常量,则只需要重新连线即可,如果位移的数是变量,则会综合出通用的移位器

常量移位:

module ConstantShift(DataMux, Address);
input   [0:3] DataMux;
output  [0:5] Address;

assign Address = (~DataMux) << 2;

endmodule

 根据Veirlog的语法规则,ConstantShift模块中执行左移运算时,从DataMux中移位出去的位并没有被舍弃,而是被移到了Address的更高位上去了。如果Address和DataMux的位宽相同,这个时候被移走的高位就将会被舍弃掉。 

综合后的网表:

FPGA开发流程:综合(二)_第12张图片 图11: 位移位数为常量

 



//module VarShift(MemData , Amount , InstrReg);
input  [0:2] MemData  ;
input  [0:1] Amount   ;

output [0:2] InstrReg ;

assign InstrReg = MemDataReg >> Amount ;

endmodule

综合后网表:

FPGA开发流程:综合(二)_第13张图片 图12: 位移位数是变量

 

  8. 向量运算

         Verilog中,宽度为1的变量称为标量,如果在变量声明中没有指定位宽则默认为标量(1位)。线宽大于1位的变量称为向量。如 reg[5:0] data;即为定义一个位宽为6的向量。下面例子中 A的4个位与B的4个位逐位相与的结果,再同C的4个位逐位相或。运算结果被赋值给(从最右位开始)目标网线。

module VectorOperations(A, B, C, Result);
input   [3:0] A ,B , C ;
output  [3:0] Result   ;

assign Result = (A & B) | C;

endmodule

//综合出的网表:

FPGA开发流程:综合(二)_第14张图片 图13: 向量运算

下一示例中,逻辑运算符的操作数是向量。此时,针对向量的各个位生成了一系列的逻辑门

module VectorOperands(Bi, Stdy , Tap);
input  [0:3] Bi ,Stdy ;
output [0:3]      Tap ;

assign Tap = Bi^Stady ;

综合后网表:

FPGA开发流程:综合(二)_第15张图片 图14 一组逻辑门

因为右端的每一个操作数都是4位的,所有综合出4个异或门。

      以上的连续赋值示例中,连续赋值语句与综合出的逻辑电路之间存在着一一对应的关系,这是因为连续赋值语句隐式地描述了这种电路结构

  9. 部分选取(域选取)

       在建模时,可以使用部分选取。在表达式中可以任意的选取向量中的相邻几位。

  10. 位选择

            在表达式中可以任意的选取向量中的某一位。

            对向量进行位选取可采用:常量下标和非常量下标。 

           10.1 常量下标

             

module ConstantIndex( A, C, Reg_File, Zcat);
input [3:0] A, C     ;
input [3:0] Reg_File ;

output [3:0] Zcat;

assign Zcat[3:1] = {A[2] , C[3:2]};
assign zcat[0]   =  Reg_File[3]     ;

endmodule

 

  11. 条件表达式

 

  12.  always语句

     

  13. if语句

 

  14. Case语句

 

  15. 再谈锁存器推导

 

  16. 循环语句

 

  17. 触发器建模

 

  18.  再谈阻塞与非阻塞

 

  19. 函数

 

   20.任务

 

   21. 使用X值和Z值

 

   22.门级建模

 

   23. 模块实例化语句

 

   24.参数化设计

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Verilog)