Verilog 入门(一)(Verilog 简介)

什么是 Verilog HDL?

Verilog HDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。

Verilog HDL 语言具有下述描述能力:

  • 设计的行为特性
  • 设计的数据流特性
  • 设计的结构组成
  • 包含响应监控和设计验证方面的时延和波形产生机制

所有这些都使用同一种建模语言。此外, Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。

Verilog 主要能力

  • 基本逻辑门,例如 andornand 等都内置在语言中。
  • 提供显式语言结构制定设计中的端口到端口的时延及路径时延和设计的时序检查。
  • 可采用三种不同方式或混合方式对设计建模。这些方式包括:行为描述方式——使用过程化结构建模;数据流方式——使用连续赋值语句方式建模;结构化方式——使用门和模块实例语句描述建模。
  • Verilog HDL中有两类数据类型:线网数据类型寄存器数据类型。线网类型表示构件间的物理连线,而寄存器类型表示抽象的数据存储元件。
  • Verilog HDL 还具有内置逻辑函数,例如 &(按位与)和 |(按位或)。
  • 对高级编程语言结构,例如条件语句、情况语句和循环语句,语言中都可以使用。

模块

模块是 Verilog 的基本描述单位,用于描述某个设计的功能或结构及其与其他模块通信的外部端口。一个设计的结构可使用开关级原语、门级原语和用户定义的原语方式描述; 设计的数据流行为使用连续赋值语句进行描述; 时序行为使用过程结构描述。一个模块可以在另一个模块中使用。

一个模块的基本语法如下:

module module_name(port_list);
  Declarations:
    reg, wire, parameter,
    input, output, inout,
    function, task,...
  Statements:
    Initial statement
    Always statement
    Module instantiation
    Continuous assignment
endmodule

时延

Verilog HDL 模型中的所有时延都根据时间单位定义。下面是带时延的连续赋值语句实例:

assign #2 Sum = A ^ B;

#2 指 2 个时间单位。使用编译指令将时间单位与物理时间相关联。这样的编译器指令需在模块描述前定义,如下所示:

` timescale 1ns/100ps

此语句说明时延时间单位为 1ns 并且时间精度为 100ps (时间精度是指所有的时延必须被限定在 0.1ns 内)。如果此编译器指令所在的模块包含上面的连续赋值语句, #2 代表 2ns。

数据流描述方式

用数据流描述方式对一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值语句中,某个值被指派给线网变量。连续赋值语句的语法为:

assign [delay] LHS_net = RHS_ expression

右边表达式使用的操作数无论何时发生变化, 右边表达式都重新计算, 并且在指定的时延后变化值被赋予左边表达式的线网变量。 时延定义了右边表达式操作数变化与赋值给左边表达式之间的持续时间。如果没有定义时延值, 缺省时延为 0。

例如,用数据流描述方式建模下图所示解码器电路模型:

在这里插入图片描述

`timescale 1ns/1ns
module Decoder2x4(A, B, EN, Z);
  input A, B, EN;
  output[3:0] Z;
  wire Abar, Bar;

  assign #1 Abar = ~ A;
  assign #1 Bbar = ~ B;
  assign #2 Z[0] = ~ (Abar & Bbar & EN);
  assign #2 Z[1] = ~ (Abar & B & EN);
  assign #2 Z[2] = ~ (A & Bar & EN);
  assign #2 Z[3] = ~ (A & B & EN);
endmodule

再次强调,连续赋值语句是并发执行的,也就是说各语句的执行顺序与其在描述中出现的顺序无关。

行为描述方式

设计的行为功能使用下述过程语句结构描述:

  1. initial 语句:此语句只执行一次
  2. always 语句:此语句总是循环执行,或者说此语句重复执行。

只有寄存器类型数据能够在这两种语句中被赋值。寄存器类型数据在被赋新值前保持原有值不变。所有的初始化语句和 always 语句在 0 时刻并发执行。

下列为 always 语句对 1 位全加器电路建模的示例:

在这里插入图片描述

module FA_Seq(A, B, Cin, Sum, Cout);
  input A, B, Cin;
  output Sum, Cout;
  reg Sum, Cout;
  reg T1, T2, T3;
  always@(A or B or Cin) begin
    Sum = (A ^ B) ^ Cin;
    T1 = A & Cin;
    T2 = B & Cin;
    T3 = A & B;
    Cout = (T1 | T2) | T3;
  end
endmodule

在顺序过程(begin-end 对)中出现的语句是过程赋值模块化的实例。模块化过程赋值在下一条语句执行前完成执行。过程赋值可以有一个可选的时延。时延可以细分为两种类型:

  1. 语句间时延:这是时延语句执行的时延。
  2. 语句内时延: 这是右边表达式数值计算与左边表达式赋值间的时延。

语句间时延的示例:

Sum = (A ^ B) ^ Cin;
#4 T1 = A & Cin;

在第二条语句中的时延规定赋值延迟 4 个时间单位执行。就是说,在第一条语句执行后等待 4 个时间单位,然后执行第二条语句。

语句内时延的示例:

Sum = #3 (A ^ B) ^ Cin;

这个赋值中的时延意味着首先计算右边表达式的值, 等待 3 个时间单位,然后赋值给 Sum

下面是一个 initial 语句的示例:

`timescale 1ns/1ns
module Test(Pop, Pid);
  output Pop, Pid;
  reg Pop, Pid;

  initial begin
    Pop = 0;
    Pid = 0;
    Pop = #5 1;
    Pid = #3 1;
    Pop = #6 0;
    Pid = #2 0;
  end
endmodule

这一模块产生如下图所示的波形:
在这里插入图片描述

结构化描述形式

在 Verilog HDL 中可使用如下方式描述结构:

  • 内置门原语(在门级);
  • 开关级原语(在晶体管级);
  • 用户定义的原语(在门级);
  • 模块实例(创建层次结构)。

下面的结构描述形式使用内置门原语描述上述全加器电路:

module FA_Str(A, B, Cin, Sum, Cout);
  input A, B, Cin;
  output Sum, Cout;
  wire S1, T1, T2, T3;

  xor
    X1(S1, A, B);
    X2(Sum, S1, Cin);

  and
    A1(T3, A, B);
    A2(T2, B, Cin);
    A3(T1, A, Cin);

  or
    O1(Cout, T1, T2, T3);
endmodule

4 位全加器可以使用 4 个 1 位全加器模块描述,描述的逻辑图如x下图所示:

在这里插入图片描述
下面是 4 位全加器的结构描述形式:

module FourBitFA(FA, FB, FCin, FSum, FCout);
  parameter SIZE = 4;
  input[SIZE:1] FA, FB;
  output[SIZE:1] FSum;
  input FCin;
  input FCout;
  wire[1:SIZE-1] FTemp;

  FA_Str FA1(.A(FA[1]), .B(FB[1]), .Cin(FCin), .Sum(FSum[1]), .Cout(FTemp[2]));
  FA_Str FA2(.A(FA[2]), .B(FB[2]), .Cin(FTemp[1]), .Sum(FSum[2]), .Cout(FTemp[2]));
  FA_Str FA3(.A(FA[3]), .B(FB[3]), .Cin(FTemp[2]), .Sum(FSum[3]), .Cout(FTemp[3]));
  FA_Str FA4(.A(FA[4]), .B(FB[4]), .Cin(FTemp[3]), .Sum(FSum[4]), .Cout(FCout));
endmodule

混合设计模式

在模块中,结构的和行为的结构可以自由混合。也就是说,模块描述中可以包含实例化的门、模块实例化语句、连续赋值语句以及 always 语句和 initial 语句的混合。它们之间可以相互包含。

下面是混合设计方式的 1 位全加器实例。

module FA_Mix(A, B, Cin, Sum, Cout);
  input A, B, Cin;
  output Sum, Cout,
  reg Cout;
  reg T1, T2, T3;
  wire S1;

  xor X1(S1, A, B);

  always@(A or B or Cin) begin
    T1 = A & Cin;
    T2 = B & Cin;
    T3 = A & B;
    Cout = (T1 | T2) | T3;
  end

  assign Sum = S1 ^ Cin;
endmodule

只要 AB 上有事件发生,门实例语句即被执行。只要 ABCin 上有事件发生,就执行 always 语句,并且只要 S1Cin 上有事件发生,就执行连续赋值语句。

猜你喜欢

转载自blog.csdn.net/myDarling_/article/details/134699135