cpld的verilog学习

以前浪费了太多机会了。以后就用这些来记录下自己到底学会了什么。用到了什么。做出了什么。

verilog的整体结构

模块的结构

verilog的基本设计单元是“模块”(block)。包括(接口描述、逻辑功能描述)

例子:

module block(a, b, c, d);

      input a, b;

       output c, d;

 

 

 

       assign c = a | b;                        【连续赋值:assign,问号表达式(?:)】

       assign d = a & b;

endmodule

由例子可以看出,verilog结构位于在module和endmodule声明语句之间,每个verilog程序包括4个主要部分:端口定义、I/O说明、内部信号声明和功能定义。

1、  模块的端口定义

模块端口声明了模块的输入输出。格式:

module 模块名(口1,口2,口3,口4,…..);

模块的端口表示模块的输入还是输出名。

引用模块时其端口可以用两种方法连接:

(1)    在引用时,严格按照定义的端口顺序连接,不用标明原模块定义时规定的端口

(2)    在引用时用”.”符号,标明原模块是定义时规定的端口名

2、  模块内容

模块的内容包括I/O说明、内部信号声明和功能定义。

(1)  I/O说明的格式

输入口:input [信号位宽-1 : 0] 端口名1;

输出口:output [信号位宽-1 : 0] 端口名1;

输入输出口:inout [信号位宽-1 : 0] 断口名1;

(2)  内部信号说明

在模块内用到的与端口有关的wire和reg类型变量的声明

 

 

Reg [width-1 : 0] R变量1,R变量2…;    【reg不和实际的电路如寄存器对应,高层次的描述时用】

Wire [width-1 : 0]W变量1,W变量2…;【与实际的物理连接对应】

(3)  功能定义

模块中最重要的部分时逻辑功能定义。由3种方法可以在模块中产生逻辑。

1)  用assign声明语句

如assign a = b&c;

2)  用实例元件

and #2 u1(q, a, b);

3)  用always块【变量必须声明为reg,还有initial。】

always @(posedge clk or posedge clr)

begin

if(clr) q <= 0;

else if(en) q <= d;

end

采用assign是描述组合逻辑最常用的方法之一。而always既可用来描述组合逻辑电路也可以用来描述时序逻辑。

(4)  要点

1)  在verilog模块中所有过程块(initial, always)、连续赋值语句、实例引用都是并行的

2)  他们表示的是一种通过变量名互相连接的关系

3)  在同一模块中这三者出现的先后顺序没有关系。

只有联系赋值的语句assign和实例引用语句可以独立与过程块而存在于模块功能定义部分

 

 

程序例子

                                      偶数分频器的verilog实现(先学习偶数,我用的单片机用到分频器)

 偶数倍分频:偶数倍分频应该是大家都比较熟悉的分频,通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。

module odd_division(clk,rst,count,clk_odd);
  input        clk,rst;
  output       clk_odd;
  output[3:0]  count;
  reg          clk_odd;
  reg[3:0]     count;
  parameter    N = 6;     【常数】            
  
    always @ (posedge clk)           【always模块:(敏感表可以为电平、沿信号posedge/negedge;通常和@连用)】
      if(! rst)                                              【任务定义:task……endtask】       
     begin
          count <= 1'b0;                        【 赋值符号:= <= (阻塞和非阻塞赋值,在具体设计中时很有讲究的)】           clk_odd <= 1'b0;
        end
      else      
        if ( count < N/2-1)
          begin         
            count <= count + 1'b1;           
          end
        else
          begin       
            count <= 1'b0;
            clk_odd <= ~clk_odd;     
          end
endmodule
注:数据结构详解
       整数、实数和时间寄存器类型

整数是一种通用的寄存器数据类型,用于对数量进行操作,使用integer进行声明。

integer counter;       //一般用途的变量用作计数器

initial

         counter = -1;    //-1存储到寄存器中

实数:实常量和实数寄存器数据类型使用关键字real来声明,可以用十进制或科学计数法来表示。实数声明不能带有范围,其默认值为0.如果将一个实数赋予一个整数,那么实数将会被取为最接近的整数。

real delta;         //定义一个名为delta的实型变量

时间寄存器:仿真是按照仿真时间进行的,verilog使用一个特殊的时间寄存器数据类型来保存仿真时间。时间变量通过使用关键字time来声明,其宽度与具体实现无关,最小为64位。通过调用系统函数$time可以取得当前的仿真时间。

2           数组

Verilog中允许声明regintegertimerealrealtime及其向量类型的数组,对数组的维数没有限制,即可声明任意维数的数组。线网数组也可用于连接实例的端口,数组中的每个元素都可以作为一个标量或者向量,以同样的方式来使用,形如<数组名>[<下标>]

Integer     count[0:7];       //由八位计数变量组成的数组

reg  bool [31:0];              //321位的布尔寄存器变量组成的数组

wire [7:0] w_array2 [5:0];        //声明8位向量的数组

 

注意:不要把数组和线网或寄存器向量混淆起来。向量是一个单独的元件,它的位宽是n,数组由多个元件组成,其中每个元件的位宽为n1.

3           存储器【重点】

Verilog中使用寄存器一维数组来表示存储器。数字的每个元素成为一个元素或一个字(word),由一个数组索引来指定。每个字的位宽为1位或者多位。注意n1位寄存器和一个n位寄存器是不同的。如果需要访问存储器中的一个特定的字,则可通过子的地址作为数组的下标来完成。

reg   mem1bit[0:1023];             //1k1位存储器

reg   [7:0] membyte [0:1023]; //1k的字节(8位)存储器membyte

membyet[511]          //取出membyte中地址511所处的字节

4           参数

Verilog使用关键字parameter在模块内定义常数。参数代表常数,不能像变量那样赋值,但是每个模块实例的参数值可以在编译阶段被重载。通过参数重载使得用户可以对模块实例进行定制。除此之外还可以对参数的类型和范围进行定义。

parameter port_id = 5;    //定义常数port_id 5

 

5           字符串

字符串保存在reg类型的变量中,每个字符占用8位(一个字节),因此寄存器变量的宽度应足够大,以保证容纳全部字符。如果寄存器变量的宽度大于字符串的大小,则verilog0来填充左边的空余位。如果寄存器变来那个的宽度小于字符串的大小,则verilog截去字符串最左边的位。 
 
Verilog HDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。
  Verilog HDL 语言具有下述描述能力:设计的行为特性、设计的数据流特性、设计的结构组成以及包含响应监控和设计验证方面的时延和波形产生机制。所有这些都使用同一种建模语言。此外,Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。
  Verilog HDL语言不仅定义了语法,而且对每个语法结构都定义了清晰的模拟、仿真语义。因此,用这种语言编写的模型能够使用Verilog仿真器进行验证。语言从C编程语言中继承了多种操作符和结构。Verilog HDL提供了扩展的建模能力,其中许多扩展最初很难理解。但是,Verilog HDL语言的核心子集非常易于学习和使用,这对大多数建模应用来说已经足够。当然,完整的硬件描述语言足以对从最复杂的芯片到完整的电子系统进行描述。
===============================
中文版Verilog HDL简明教程:第1章 简介

  
 
  
  Verilog HDL是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。被建模的数字系统对象的复杂性可以介于简单的门和完整的电子数字系统之间。数字系统能够按层次描述,并可在相同描述中显式地进行时序建模。
  Verilog HDL 语言具有下述描述能力:设计的行为特性、设计的数据流特性、设计的结构组成以及包含响应监控和设计验证方面的时延和波形产生机制。所有这些都使用同一种建模语言。此外,Verilog HDL语言提供了编程语言接口,通过该接口可以在模拟、验证期间从设计外部访问设计,包括模拟的具体控制和运行。
  Verilog HDL语言不仅定义了语法,而且对每个语法结构都定义了清晰的模拟、仿真语义。因此,用这种语言编写的模型能够使用Verilog仿真器进行验证。语言从C编程语言中继承了多种操作符和结构。Verilog HDL提供了扩展的建模能力,其中许多扩展最初很难理解。但是,Verilog HDL语言的核心子集非常易于学习和使用,这对大多数建模应用来说已经足够。当然,完整的硬件描述语言足以对从最复杂的芯片到完整的电子系统进行描述。

历史

  Verilog HDL语言最初是于1983年由Gateway Design Automation公司为其模拟器产品开发的硬件建模语言。那时它只是一种专用语言。由于他们的模拟、仿真器产品的广泛使用,Verilog HDL 作为一种便于使用且实用的语言逐渐为众多设计者所接受。在一次努力增加语言普及性的活动中,Verilog HDL语言于1990年被推向公众领域。 Open Verilog International (OVI)是促进Verilog发展的国际性组织。1992年, OVI决定致力于推广Verilog OVI标准成为IEEE标准。这一努力最后获得成功,Verilog 语言于1995年成为IEEE标准,称为IEEE Std 1364-1995。完整的标准在Verilog硬件描述语言参考手册中有详细描述。

主要能力

  下面列出的是Verilog硬件描述语言的主要能力:
* 基本逻辑门,例如and、or和nand等都内置在语言中。
* 用户定义原语(UDP)创建的灵活性。用户定义的原语既可以是组合逻辑原语,也可以是时序逻辑原语。
* 开关级基本结构模型,例如pmos 和nmos等也被内置在语言中。
* 提供显式语言结构指定设计中的端口到端口的时延及路径时延和设计的时序检查。
* 可采用三种不同方式或混合方式对设计建模。这些方式包括:行为描述方式—使用过程化结构建模;数据流方式—使用连续赋值语句方式建模;结构化方式—使用门和模块实例语句描述建模。
* Verilog HDL中有两类数据类型:线网数据类型和寄存器数据类型。线网类型表示构件间的物理连线,而寄存器类型表示抽象的数据存储元件。
* 能够描述层次设计,可使用模块实例结构描述任何层次。
* 设计的规模可以是任意的;语言不对设计的规模(大小)施加任何限制。
* Verilog HDL不再是某些公司的专有语言而是IEEE标准。
* 人和机器都可阅读Verilog 语言,因此它可作为EDA的工具和设计者之间的交互语言。
* Verilog HDL语言的描述能力能够通过使用编程语言接口(PLI)机制进一步扩展。PLI是允许外部函数访问Verilog 模块内信息、允许设计者与模拟器交互的例程集合。
* 设计能够在多个层次上加以描述,从开关级、门级、寄存器传送级(RTL)到算法级,包括进程和队列级。
* 能够使用内置开关级原语在开关级对设计完整建模。
* 同一语言可用于生成模拟激励和指定测试的验证约束条件,例如输入值的指定。
* Verilog HDL 能够监控模拟验证的执行,即模拟验证执行过程中设计的值能够被监控和显示。这些值也能够用于与期望值比较,在不匹配的情况下,打印报告消息。
* 在行为级描述中,Verilog HDL不仅能够在RTL级上进行设计描述,而且能够在体系结构级描述及其算法级行为上进行设计描述。
* 能够使用门和模块实例化语句在结构级进行结构描述。
* Verilog HDL 的混合方式建模能力,即在一个设计中每个模块均可以在不同设计层次上建模。
* Verilog HDL 还具有内置逻辑函数,例如&(按位与)和(按位或)。
* 对高级编程语言结构,例如条件语句、情况语句和循环语句,语言中都可以使用。
* 可以显式地对并发和定时进行建模。
* 提供强有力的文件读写能力。
* 语言在特定情况下是非确定性的,即在不同的模拟器上模型可以产生不同的结果;例如,事件队列上的事件顺序在标准中没有定义。

习题

1. Verilog HDL 是在哪一年首次被IEEE标准化的?
2. Verilog HDL支持哪三种基本描述方式?
3. 可以使用Verilog HDL描述一个设计的时序吗?
4. 语言中的什么特性能够用于描述参数化设计?
5. 能够使用Verilog HDL 编写测试验证程序吗?
6. Verilog HDL 是由哪个公司最先开发的?
7. Verilog HDL中的两类主要数据类型什么?
8. UDP代表什么?
9. 写出两个开关级基本门的名称。
10. 写出两个基本逻辑门的名称。
======================================
中文版Verilog HDL简明教程:第2章 HDL指南

  
 
  
  本章提供HDL语言的速成指南。

2.1 模块

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

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

  说明部分用于定义不同的项,例如模块描述中使用的寄存器和参数。语句定义设计的功能和结构。说明部分和语句可以散布在模块中的任何地方;但是变量、寄存器、线网和参数等的说明部分必须在使用前出现。为了使模块描述清晰和具有良好的可读性, 最好将所有的说明部分放在语句前。本书中的所有实例都遵守这一规范。
  以下为建模一个半加器电路的模块的简单实例。

module HalfAdder (A, B, Sum, Carry);
input A, B;
output Sum, Carry;

assign #2 Sum = A ^ B;
assign #5 Carry = A & B;
endmodule

  模块的名字是HalfAdder。 模块有4个端口: 两个输入端口A和B,两个输出端口Sum和Carry。由于没有定义端口的位数, 所有端口大小都为1位;同时, 由于没有各端口的数据类型说明, 这四个端口都是线网数据类型。
模块包含两条描述半加器数据流行为的连续赋值语句。从这种意义上讲,这些语句在模块中出现的顺序无关紧要,这些语句是并发的。每条语句的执行顺序依赖于发生在变量A和B上的事件。
  在模块中,可用下述方式描述一个设计:
  1) 数据流方式;
  2) 行为方式;
  3) 结构方式;
  4) 上述描述方式的混合。
  下面几节通过实例讲述这些设计描述方式。不过有必要首先对Verilog HDL的时延作简要介绍。

2.2 时延

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

  assign #2 Sum = A ^ B;

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

  ` timescale 1ns /100ps

此语句说明时延时间单位为1ns并且时间精度为100ps (时间精度是指所有的时延必须被限定在0.1ns内)。 如果此编译器指令所在的模块包含上面的连续赋值语句, #2 代表2ns。
  如果没有这样的编译器指令, Verilog HDL 模拟器会指定一个缺省时间单位。IEEE Verilog HDL 标准中没有规定缺省时间单位。

2.3 数据流描述方式

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

assign [delay] LHS_net = RHS_ expression;

右边表达式使用的操作数无论何时发生变化, 右边表达式都重新计算, 并且在指定的时延后变化值被赋予左边表达式的线网变量。时延定义了右边表达式操作数变化与赋值给左边表达式之间的持续时间。如果没有定义时延值, 缺省时延为0。
下面的例子显示了使用数据流描述方式对2-4解码器电路的建模的实例模型。

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

assign #1 Abar = ~ A; / / 语句 1。
assign #1 Bbar = ~ B; / / 语句 2。
assi

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值