附录B

B 4.1 Verilog的数据类型和操作类型

  • 含两种基本数据类型
    • wire表示一个组合信号。
    • reg(寄存器)存储一个数据,数据随着时间的推移变化。
    • 尽管实际实现中reg常常与ー个寄存器相关连,但不是必须这样
  • wire:表示一个组合逻辑信号。
  • reg:表示一个寄存器。

设有一个wire或reg,命名为X

  • X为32位宽时,这样声明:reg[31:0] X或wire[31:0] X
  • 索引0来划定最低有效位。
  • 通过[起始位:结東位]访问reg或wire的一段连续位,其中的起始位和结東位必须为常数。

reg的一组阵列表示寄存器文件或存储器。

  • reg [31: 0] registerfile[0:31]
  • 声明了一个类似MIPS的寄存器文件
  • 寄存器0是第一个寄存器。
  • 访问存储阵列
    • 用registerfile[regnum]访问一个数据,与C一样。

reg或wire型数据可能的取值有

  • 0或1,表逻辑假或真。
  • X,表值未知,所有寄存器初始化数据、未被连接的wire数据均为X。
  • Z,表示三态门处于高阻态,在该附录中不对其进行讨论。

可十、二、八或十六。

  • 常量前加前缀来表示该常量含多少二进制
  • 4’b0100:含4位二进制常量的数据4,等价4’d4。
  • {A[31:16],B[15:0]}创建数值
    • 高16自A,低16自B。

Verilog从C中继承了一元组和二进制操作符,

  • +,-,*,/
  • &,|,~
  • ==,!=,>,<,<=,>=
  • <<,>>
  • 条件运算符
  • Verilog中增加了一组逻辑运算符(&,|,^)
    • 这类运算符对操作数的所有位均进行逻辑操作。
  • &A返回A中所有位进行与操作的结果。
  • ^A返回A中所有位异或的结果。

哪些定义了相同的数值?

  • 8’bimoooo
  • 8’hF0
  • 8’d240
  • { {4{1’b1}},{4{1’b0}} }
  • {4’b1,4’b0}

B.4.2 Verilog程序的结构

  • Verilog程序由模块的组合构成。
    • 模块最小是一个逻辑门,最大可以是一个完整的系统。
  • 模块与C++中的类类似,但没有类那样强大的功能。
    • 模块定义了它的输人和输出,输人和输出分别对应了模块与外部进行连接时的输入接口和输出接口。
  • 模块也可能声明一些附加的变量。
  • 一个模块的主体有以下几个部分构成:
    • initial结构,该结构对reg型变量进行初始化
    • 连续赋值语句,只出现在组合逻辑
    • always结构,该结构既可用在组合逻辑中,也可时序逻辑
    • 模块实例化,该结构用来对已经定义的模块进行实例化操作。

B.4.3 Verilog构造复杂的组合逻辑

  • assign表连续赋值语句
    • 连续赋值语句对应的组合逻辑:
      • 输出被连续赋值,只要输入变,输出也马上变
    • wire型变量只能通过连续赋值语句赋值
  • 用连续赋值语句,定义一个模块实现半加器,
    • 如图B-4-1
      附录B

用Verilog构造组合逻辑时

  • 推荐用连续赋值语句。
  • 当要构造更复杂结构时,连续赋值语句笨拙、乏味。
  • 另种可行方法是
    • 用模块中的always语句,来描述组合逻辑单元,但要小心使用。
  • always语句中允许使用控制语句,如if-then-else、case语句、for语句和 repeat语句。

always语言块指定一个信号列表,

  • 语句块对这些信号敏感(信号列表以@开始)。
  • 敏感信号列表中任一信号变,
    • 语句块都将重新执行。
  • 若省略敏感信号列表,则a1ways语句块将一直重新执行。
  • 当always语句块表组合逻辑时,敏感信号列表要包含所有的输人
  • 一个 always块如下:
    always @(list of signals that cause reevaluation)begin
    Verilog statements including assignments and other
    control statements end

reg型变量只能在a1ways内赋值,需用过程性赋值语句(与前面介绍的连续赋值不同)。

  • 有两种不同的过程赋值语句。
  • =,侧语句计算出结果,并赋值给左侧变量。且与C语言的执行一致,在下一个赋值语句执行前,该赋值语句
    完成执行。so=又称blocking assignment
    • =对构造时序逻辑来说很有用
  • 非阻塞赋值,<=。
    • 在a1ways块中的非阻塞赋值语句,当所有非阻塞赋值语句计算出右侧的结果时,就立即赋给左侧变量。
  • 图B-4-2为4选1多路选择器的实现,该例子为使用always语句块实现的组合逻辑,为简单化,我们用case语句。
  • case语句与C语言中的switch语句类似。
  • 图B-4-3是MIPS中ALU的实现,其中也使用了case语句。
  • 阻塞赋值: 在下一个赋值语句执行前,阻塞赋值完成执行。
  • 非阻塞赋值:只有计算出所有非阻塞语向右侧结果时,才进行赋值。

always中只能给reg型变量赋值,

  • 若想用一个always块描述组合逻辑,
  • 则须非常小心,
  • 以确保这个reg变量不被综合为一个寄存器,
  • 下面的“精解”中给出了许多“陷阱”。

图B-4-2

附录B

  • 用case语句实现的4选1,
  • 含32位输入。
  • Verilog中,只有被case选择到的语句会被执行(像每个case后面加break一样),
    • 且不能转到下一个分支去

图B-4-3

附录B

  • MIPS中ALU的 Verilog行为级定义。
  • 通过使用包含基本算术和逻辑操作的模块库,就可对其进行综合

精解

  • 组合逻辑常用连续赋值语句,
    • 但在其他一些Verilog结构中,
    • 逻辑综合中可能会产生想不到的结果,
    • 即使是a1ways块也有此问题。
  • 常见的问题是,
    • 用已存在的锁存器或寄存器来实现时序逻辑,
    • 这将导致生成的结果比预期的要慢,且开销要大。
  • 为保证你设计的组合逻辑可以按这种方式被综合,需按下面的注意事项操作:
    • 将所有的组合逻辑放在连续赋值语句或a1ways块中。
    • 保证作为输入的所有信号都出现在a1ways块的敏感信号列表中。
    • 保证每一个通过a1ways块的数据通路,都将值赋给同一位组。
  • 最后一点最容易被忽略。
  • 读图B-5-15中的例子,来说服自己为何要坚持最后这条准则。

所有变量都初始为0,下面Verilog含在a1ways中,

  • 则执行完下面语句后,A、B的值为多少?
    C=1;
    A<=C;
    B=C;

B.5 构建基本的算术逻辑单元