用always过程语句描述组合逻辑

always语句

在alawys过程块中的赋值称为过程赋值(Procedural Assignment)。首先通过一个例子说明always块的结构和含义。

例 1. 用过程语句描述半加器
module HalfAdder
(
  input A, B,
  output reg Sum, Carry
);
always @ (A or B)
begin
  Sum <= A ^ B;
  Carry <= A & B;
end
endmodule

always语句中@ (A or B)称为敏感列表,其含义是,当输入A或B变化时,重新计算begin…end块中的表达式值,更新赋值结果;然后等待下次敏感列表的变化。always语句是不会停止的,要么在等待敏感列表的变化,要么在“执行”块中语句,这正是“always”这个词的含义。这里借用了软件的“执行”这个词,需要再次说明的是,并不存在一个处理器负责执行Verilog语句,Verilog语句描述的是硬件。

敏感列表

Verilog-2001标准对敏感列表的语法做了扩充,主要有两点。

(1) 用逗号代替“or”,可以使表达更简洁。如:

always @ (A, B)

(2) “*”通配符

用always语句描述组合逻辑,要求所有的输入变量都要出现在敏感列表中,否则综合工具有可能无法正确地推断出设计者的意图。假如例 1的敏感列表缺少了输入变量B,即

always @ (A)

意味着当B变化时,不会重新计算输出;综合出的逻辑特性可能会出现难以预料的结果。因此Verilog-2001增加了通配符*,以简化书写形式,减少设计工程师出错的可能性。举例如下:

always @ *

always @ (*)

case语句和七段译码器

七段数码管是电子设备中常见的显示器件,可以用来显示数字和少量字母符号。一位数码显示器由八个发光二极管组成,其中七个发光二极管a~g控制七个笔画(段)的亮或暗,另一个控制一个小数点的亮和暗,图 1是一种常见的笔画命名。对于共阴极的数码管,对某一段发光二极管驱动高电平即点亮该段;对于共阳极的数码管,则驱动低电平点亮。例 2是用于共阴极七段数码管的十六进制数-7段译码器。

image
图 1. 七段数码管的段定义
例 2. HEX-7段译码器
module decode4_7
(
  input [3:0] data,
  output reg [7:0] seg
);

always @ *
begin
  case(data)
    4'h0 : seg=8'h3f;
    4'h1 : seg=8'h06;
    4'h2 : seg=8'h5b;
    4'h3 : seg=8'h4f;
    4'h4 : seg=8'h66;
    4'h5 : seg=8'h6d;
    4'h6 : seg=8'h7d;
    4'h7 : seg=8'h07;
    4'h8 : seg=8'h7f;
    4'h9 : seg=8'h6f;
    4'ha : seg=8'h77;
    4'hb : seg=8'h7c;
    4'hc : seg=8'h39;
    4'hd : seg=8'h5e;
    4'he : seg=8'h79;
    4'hf : seg=8'h71;
    default : seg=8'hxx;
  endcase
end

endmodule

if-else语句和优先权编码器

优先权编码器常用于计算机的中断系统。如果有多个中断源提出中断请求,需要根据它们的优先权的高低进行排队,输出优先权最高的中断源编码。if-else语句非常适合这种优先级的描述,例 3是对8个中断源进行排队的逻辑描述,如果没有一个中断源提出中断请求,None_ON输出为1;否则None_ON输出为0,并且Out输出优先级高的中断源编码。

例 3. 优先权排队逻辑
module Priority
(
  input [7: 0] In,
  output [2: 0] Out,
  output None_ON
);

reg [2: 0] Out;
assign None_ON = ~|In;
always @ *
begin
  if (In[0]) Out = 3'b000;
  else if (In[1]) Out = 3'b001;
  else if (In[2]) Out = 3'b010;
  else if (In[3]) Out = 3'b011;
  else if (In[4]) Out = 3'b100;
  else if (In[5]) Out = 3'b101;
  else if (In[6]) Out = 3'b110;
  else if (In[7]) Out = 3'b111;
  else Out = 3'b000;
end

endmodule