|  | 
 
| 
一. 关于 IEEE 1364 标准" f  ]; M: ~# a' P
x
EDA365欢迎您登录!您需要 登录 才可以下载或查看,没有帐号?注册  Verilog 语言标准化的目的是将现存的通过 Verilog-XL 仿真器体现的 Verilog 语言标准化。IEEE 的 Verilog 标准与事实上的标准有一些区别。因此,仿真器有可能不完全支持以下的一些功能:
 2 R5 N- Y# _; U0 B' X●在UDP(用户自定义原语)和模块实例中使用数组(见Instantiation说明)。
 2 @9 ?4 {7 O* \% C: C/ [4 u●含参数的宏定义(见‘define)。
 & Q6 i) v5 }" q  U2 b3 m: q9 x: _2 |●IEEE标准不支持用数字表示的强度值(见编译预处理命令)。
 " M7 n$ L' Z6 M0 o# c/ Y●有许多Verilog-XL支持的系统任务、系统函数和编译处理命令在IEEE标准中不支持。8 G5 y( U6 z/ S7 G
 ●若在模块中其Net或寄存类型变量只有一个驱动,IEEE标准允许在一个指定块中, 延迟路径的最终接点可以是一个寄存器或Net类型的变量。而在此标准推出之前,对最终接点的类型有着严格得多的要求(见Specify说明)。
 4 R: M  @$ G  A; |. I& X0 t●指定路径的延迟表达式最多可以达到12个延迟表达式,表达式之间需用逗号隔开。而在此标准推出之前,最多只允许六个表达式(见Specify说明)。4 }- Q# U$ w: F6 N, G
 ●在Net类型变量的定义中,标量保留字scalared与矢量保留字 vectored的位置也做了改动。原先,保留字位于矢量范围的前面。在IEEE标准中,它应位于Net类型的后面(见Net说明)。
 9 i) i9 f7 I# z7 N●在最小-典型-最大常量表达式中,对于最小、典型与最大值的相对大小并无限制。而原先最小值必须小于或等于典型值,典型值必须小于或等于最大值。
 4 W$ ^9 K- Z% E. H! j●在IEEE标准中,表示延迟的最小-典型-最大表达式不必括在括号里。而原先,它必需括在括号里。
 6 R0 w/ v1 t" D/ p+ k! {, E0 m, y# E0 m, z6 ^7 p+ [7 t5 |
 二. Verilog 简介
 - V2 @( n4 d3 d在Verilog HDL 中,我们可通过高层模块调用低层和基本元件模块,再通过线路连接(即下文中的NET)把这些具体的模块连接在一起,来描述一个极其复杂的数字逻辑电路的结构。所谓基本元件模块就是各种逻辑门和用户定义的原语模块(即下文中的UDPs)。而所谓NET实质上就是表示电路连线或总线的网络。端口连接列表用来把外部NET连接到模块的端口(即引脚)上。寄存器可以作为输入信号连接到某个具体模块的输入口。NET和寄存器的值可取逻辑值0,1,x(不确定)和 z(高阻)。除了逻辑值外,NET还需要有一个强度(Strength)值。在开关级模型中,当NET的驱动器不止一个时,还需要使用强度值来表示。逻辑电路的行为可以用Initial和Always 的结构和连续赋值语句,并结合设计层次树上各种层次的模块直到最底层的模块(即UDP及门)来描述。 2 {+ C, W, N' d- T% w( m# B) Q1 ^
 模块中每个Initial块、Always块、连续赋值、UDP 和各逻辑门结构块都是并行执行的。而 Initial及Always块内的语句与软件编程语言中的语句在许多方面非常类似,这些语句根据安排好的定时控制(如时延控制)和事件控制执行。在Begin-End块内的语句按顺序执行,而在Fork-Join块中的语句则并行执行。 连续赋值语句只可用于改变NET的值。寄存器类型变量的值只能在Initial及Always块中修改。Initial及Always块可以被分解为一些特定的任务和函数。PLI (即可编程语言接口的英语缩写)是完整的Verilog语言体系的一个的组成部分,利用PLI便可如同调用系统任务和函数一样来调用C语言编写的各种函数。1 f5 p6 l7 L# V. M6 x
 
 . }: G0 p' @  L. H& \编译
 ! c6 ~* g8 {7 H- W9 ]Verilog的原代码通常键入到计算机的一个或多个文本文件上。然后把这些文本文件交给# ^' i- d2 r2 [0 n" t& s
 Verilog编译器或解释器处理,编译器或解释器就会创建用于仿真和综合必需的数据文件。
 1 k7 B) C. V) [1 O有时候,编译完了马上就能进行仿真,没有必要创建中间数据文件。
 $ ]2 E8 _5 v0 C! a9 D
 i7 d  S4 `+ [5 ^6 P  c) N. M三. 语法总结
 # {4 I$ o% A3 D% Q5 e# Q/ Y典型的 Verilog 模块的结构:
 - l  A5 |  {) ?) r( p( Ymodule M (P1, P2, P3, P4);
 / y  t' @, ^  I input P1, P2;
 5 ^% M" M0 z' b) ^8 T output [7:0] P3;
 ) T/ d5 U; d: l) M/ @ inout P4; * B6 `* q- O0 k
 reg [7:0] R1, M1[1:1024]; 9 N* R9 d4 H1 c$ ~
 wire W1, W2, W3, W4;
 ) Q- S3 F3 X: A0 ?8 [ parameter C1 = “This is a string”; " a' @! m8 v- u9 u4 U
 initial
 ) D2 p9 A$ \2 K( j9 Q begin : 块名
 - C0 @. N5 j; g9 t" O // 声明语句
 # r' _; R  |  W$ Q8 P: u end . ]& R# F: k# N( J
 always @ (触发事件)
 9 s, V4 d8 G  n/ i5 l: ]- @9 | begin & [& G  b) {) j7 q# k" w) Y
 // 声明语句
 " y/ I* |" r7 q7 T! zend * m, G3 X8 M4 J2 d/ A; V
 // 连续赋值语句..
 $ [. H7 ~0 Y# Zassign W1 = Expression;
 , ?3 |: J" S7 W5 Pwire (Strong1, Weak0) [3:0] #(2,3) W2 = Expression;
 7 Q: q- z6 \" G  x, H// 模块实例引用
 : {, o( j7 I1 N4 Y6 G COMP U1 (W3, W4); & t" a4 `6 e) I& k" t
 COMP U2 (.P1(W3), .P2(W4)); : [3 b5 ^$ z7 \8 Z
 task T1; //任务定义 0 X5 @  @9 T/ e. W$ x
 input A1; % i0 Q1 p+ v. z" n! n7 e$ l& l4 m$ v
 inout A2; * k  e- s9 R  K: L; q7 F
 output A3;
 9 A- [, @0 ~5 ^/ T7 c" C3 ] begin
 ; T9 i: f; c/ s: ] // 声明语句
 # d( w3 g% E- l& C4 n9 `......, _1 v9 A' }$ I  u0 e
 
 * ^6 Q7 v( a. ^# R1 R# i& k# Y四. 编写 Verilog HDL源代码的标准1 @- R" P% X1 t3 ?
 编写 Verilog HDL 源代码应按标准进行,其标准可分成两种类别。第一种是语汇代码的编写标准,标准规定了文本布局,命名和注释的约定,其目的是为了提高源代码的可读性和可维护性。第二种是综合代码的编写标准,标准规定了 Verilog 风格,其目的是为了避免常常碰到的不能综合和综合结果存在缺陷的问题,也为了在设计流程中及时发现综合中会发生的错误。' N% M5 |0 n2 |0 o: t% G8 ]
 下面列出的代码编写标准可根据所选择的工具和个人的爱好自行作一些必要的改动。
 * q% _, y! [9 n) E$ J语汇代码的编写标准:& C& e0 \8 ~) v: G1 A  w! n
 ●每一个Verilog源文件中只准编写一个模块,也不要把一个模块分成几部分写在几个源文件中。 ( x9 D! [6 J3 I* h, `
 ●源文件的名字应与文件内容有关,最好一致(例 ModuleName.v)。 & ]2 ]" G) _( y! v# ^  y0 z/ V' B
 ●每行只写一个声明语句或说明。 7 A4 S0 b$ S' G% i
 ●如上面的许多例子所示,用一层层缩进的格式来写。 3 w. o  v# r# j: `# |
 ●用户定义变量名的大小写应自始至终一致(例如,变量名第一个字母大写)。% U9 l' b  R) y9 B0 H
 ●用户定义变量名应该是有意义的,而且含有一定的有关信息。而局部名(例如循环变量)可以是简单扼要。8 s. q( F, o0 `8 t2 h
 ' E3 `1 r# u0 d+ ~/ m
 ) l+ }7 k! Z2 E0 X* J7 q6 m
 
 | 
 |