当前位置:首页 >> 信息与通信 >>

Verilog基础


Verilog 基础
一基本要素 (1)Verilog HDL 与 VHDL 1.它于 1995 年成为 IEEE 标准,即 standard 1364-1995。VHDL 于 1987 年成为 IEEE 标准。 2.类 C 语言,不允许自定义数据类型(VHDL 可以)。 3.可描述开关级电路模型,但信号初值不确定,必须由程序初始化;VHDL 系统数据定义后 没有赋值则

默认为 0,对系统级支持能力要强一些。 (2)IC 设计流程: 系统结构设计与仿真——>HDL 设计——>TestBench 功能模拟测试、逻辑仿真——>综合成 逻辑门(工艺库、约束文件)——>初步时序分析(静态、电压、温度)——>自动布线布 局——>后端报告(布局布线后增加的电阻、电容)——>动态(布局后)时序仿真,任何的建 立例外都必须通过优化产生该例外的路径, 以减小延迟; 任何保持例外都必须通过在产生例 外的路径上增加缓存,来增加延迟——>逻辑验证——>投片生产。 (3)标识符与关键字命名 1.标识符首字不能为数字或$,可以为字母和下划线, 2.命名长度不能超过 1024, 3.区分大小写(与 VHDL 不同); 4.系统任务和系统函数前必须在标识符前加上$。 5.转义标识符 \ 开头,以空格、制表符(tab 键)或换行符结尾,可显示打印 ASCII 字符。 (4)系统任务和系统函数 1.display(信息输出到标准输出设备,带行结束符)和 write(输出信息不带行结束符)。用 于显示输出的特殊字符: \\n 换行 \\t 制表符 \\\\ 字符\\\

\\" 字符" \\ddd 值为十六进制字符 %% 字符% 格式定义: %h 或%H: 十六进制 %d 或%D: 十进制 %o 或%O: 八进制 %b 或%B: 二进制 %c 或%C: ASCII 字符 %v 或%V: 线网信号长度 %m 或%M: 层次名 %s 或%S: 字符串 %t 或%T: 当前时间格式 缺省如$displayb: 显示二进制数, 2.monitor 监控和显示指定任务的参数值, 3.strobe 显示数据,保证数据只在所有赋值语句执行完毕时才被显示;(而$display()任务执 行通常是确定的)。 4.文件输入输出 a.文件打开和关闭:系统函数$fopen()和$fclose(), b.输出值到文件:$fdisplay,$fwrite,$fstrobe,$fmonitor, 这些任务的第一个参数都是文件指针, 其余参数为带有从参数表的格式定义序列。 c.从文件中读出数据并载入存储器:$readmemb,$readmenh 用于指定文件中读取并载入数据 到指定的存储器。可在模拟时间的任何时刻执行,读取的文件只能包含如下内容: 空格、换行符、制表符(tab 键)、换页;注释;二进制和十六进制;

5.模拟时间访问当前模拟时间, a.$time:返回 64 位的整型模拟时间值,由`timescale 激活; b.$stime:返回 32 位无负号整型时间值,在`timescale 中指定单位, c.$realtime:返回一个实数,在`timescale 中指定单位; 6.模拟控制 a.$finish[(n)];使模拟器窗口关闭并控制返回主机操作系统; b.$stop[(n)];将模拟进程挂起; 7.随机函数 $random[(seed)]; 产生随机数,每次调用时根据种子变量(seed)的取值返回一个新的 32 位有符号随机 数。种子变量必须是寄存器型、整型或时间寄存器型,种子变量来控制函数返回值,改变量 的值应该在调用$random 系统函数之前就已定义好。其他产生随机数函数: $dist_uniform(seed,start,end); $dist_normal(seed,mean,standard_deviation,upper); $dist_exponential(seed,mean); $dist_poisson(seed,mean); $dist_chi_square(seed,degree_of_freedom); $dist_t(seed,degree_of_freedom); $dist_erlang(seed,k_stage,mean); (5)编译指令 1.`difine,`undef,产生/取消文本替换的宏; 2.`ifdef,`else,`endif,条件编译; 3.`default_nettype,为隐式线网指定线网类型,在模块外使用,影响其后的所有模块;线网 类型的关键字有:

wire,tri,tri0,wand,triand,tri1,wor,trior,trireg; 4.`include,包含源文件,可以嵌套,如果文件 1 包含文件 2,文件 2 包含文件 3,则在文件 1 中用 2 条该指令包含且文件 3 出现在前; 5.`resetall,重设为缺省值; 6.`timescale,说明时间单位和精度,$printtimescale 显示模块的时间单位和精度; 7.`unconnected_drive,`nounconnected_drive, 出现在这两个指令之间的任何未连接的输入端口 呈现为正偏电路状态(连接到高电平)或反偏电路状态(连接到低电平)。 8.`celldefine,`endcelldefine,这两个指令之间为单元模块。 (6)空白符和注释 空格、制表符、换行符、走纸符没有特殊意义; 注释形式多行或单行用//, (7)数值和字符串 1. 4 种基本值:0,1,x 未知,z 高阻;x 和 z 不区分大小写;

2. 3 种基本常量:整型,实型,字符串型;八进制(o 或 O),二进制(b 或 B),十进 制(d 或 D),十六进制(h 或 H);科学计数法,2_3.5e2 值为 2350.0 忽略下划线;字符 串在双引号内,不能分多行写; (8)线网类型 1.wire 和 tri:连线和三态线网,可描述多个驱动源驱动同一线网类型,具体值由下表决定: wire 0 1 x z 0 1 x z 0 x x 0 x 1 x 1 x x x x 0 1 x z

2.wor 和 trior:线或线网;

3.wand 和 triand:线与网; 4.trireg:三态寄存器,用于存储数值,并可用于电容节电建模; 5.tri0 和 tri1 线网:用于线逻辑的建模,若无驱动源驱动,则 tri0 的值为 0(tri1 的值为 1); 6.supply0 和 supply1:前对地建模,电平为 0;后者对电源建模,即高电平 1; (9)寄存器类型 1.reg:可以取任意长度,值通常被解释为无符号数; 2.integer:整型值,最多容纳 32 位;可以存储有符号数,且算术操作符提供 2 的补码运算结 果;不能位访问,一种截取位的办法是将整数赋值给一般的 reg 型变量,然后从中选取相应 的位,综从右向左截取(获得最低位),多余的(高位)被截断; 3.time:存储和处理时间,只存储无符号值,默认为 64 位值; (10)门类型 1.and/or:一个标量输出多个标量输入,门共有: and nand or nor xor xnor

2.buf/not:一个标量输入和多个标量输出; (11)操作符 优先级:由高到低, !(逻辑非), &,~&,|,~|,^,~^,规约操作符在单一操作数的所有位上进行操作,并产生 1 位结果; +,-,正负; *,/(只取整,余数丢弃),%(求余数,两侧均为整型); +,-,加减; <<,>>,移位操作,空位补 0,

>,<,>=,<=, ==,!=,===(等于),!==(不等于); &,~&,~,^(按位异或),^~(同或),位运算操作,右端对齐; |,~|, &&(逻辑与), ||,逻辑操作, ?:,条件操作,

{},连接操作,可把多个信号的某些位连接起来进行位运算操作表示一个新信号,还可 以嵌套; =,<=,赋值,

复制操作符,{重复数字{重复内容}};

二行为建模与基本的行为建模语句 1.过程语句 并发执行,时序条件或事件触发。每个模块中可以含任意个 initial 和 always 语句,块 内部可顺序执行,块间的语句可以交叉执行。较适合的做法是在 always 语句中描述硬件行 为,在年语句中模块初始化。 (a)initial:在仿真开始时,且该块仅执行一次,常用于测试和虚拟模块中,多个 initial 语 句之间并行;可以是下列语句之一: assign //阻塞或非阻塞过程赋值语句

continous //连续赋值语句 conditioal //条件语句 case //case 语句

loop wait disable

//循环 //等待 //终止

sequential //顺序执行块 parallel task //并行执行块 //任务使能语句

(b)always [@(timing_control)]:循环执行,触发条件由时序控制决定,可以电平触发也可 边沿触发(negedge,posedge),还可以多个信号用 or 连接,满足条件才执行,否则阻塞并 等待再次满足条件,所以输入的变化会影响输出;可用语句与 initial 类似;缺省条件则产生 一个仿真死锁。 边沿触发常用于描述时序行为,如有限状态机等;电平触发常用来描述组合逻辑行为。 2.条件语句 (a)if() else if() else; (b)条件操作符(?:)二选一; 3.case endcase 语句 多分支枚举选择,表达式长度要统一。派生的 casez 和 casex 语句,在 casex 句中值 x (未知)和 z(高阻)都被认为是无关位,if 句中表达式产生的 x 或 z 值将出错;在 casez 句中值 z 被认为是无关值。 如 casez (mask) 4`b1???:Dbus[4]=0;表示第 4 位是 1 忽略其他位。 4.循环语句 (a)forever:连续执行,跳出语句 disable 可与过程语句同使用; (b)repeat():执行固定次数,计数表达式值 X 或 z 不定是,按 0 处理; (c)while():执行过程赋值语句直到指定的条件为假,如果表达式开始就假,则不执行; (d)for: (e)循环的异常退出:disable,可退出任何循环,能终止任何 begin_end 块的执行,块名可 放在 begin 关键字后冒号后。

5.事件控制 在 verilog2001 新规范中@(a,b,c)和@(a or b or c)等价, (a)边沿触发事件 @event :posedge 和 negedge 表示上升沿转换的形式有: 0->x,0->z,0->1,x->1,z->1; 下降沿转换形式有: 1->z,1->x,1->0,x->0,z->0; (b)电平触发事件 wait() 6.持续赋值 赋值给预先定义好的网线,在模拟期间只要且只有等式右边有变化,就赋值给左边,且连 续、自动完成;若有指定赋值延迟,则在右边变化后过一定延迟时间再赋值给左边;用于数 据流行为建模,常用在组合逻辑设计。 assign a=b; 7.过程赋值语句 用来更新寄存器型、整型、时间型和存储器型变量;与持续赋值的区别: 一,在过程控制流下控制更新寄存器变量;assign 驱动线网,且在输入操作值变化时求 解新值并更新变量; 二,在过程块内部;assign 句在过程块外步; 三,通常用在 initial 和 always 块中,只能对寄存器型变量赋值; · 通常在 always 块中用阻塞性赋值来产生组合逻辑; · 通常在 always 块中用非阻塞性赋值来产生时序逻辑; (a)verilogHDL 的层次化事件模型:IEEE 标准中四个独立层次化事件队列: 动态事件队列 停止运行的事件队列()顺序可变:

阻塞赋值,计算非阻塞赋值右边的表达式,持续赋值,执行$display 命令,计算原语的 输入和输出变化; 非阻塞事件队列: #0 延迟阻塞赋值; 监控事件队列: 更新非阻塞赋值语句左边变量的值; 其他指定的 PLI 命令队列: 执行$monitor 命令,$strobe 命令; 所有事件可以加入到任何一个事件队列中,但只能从活跃事件队列中移出。 8 条可综合风格的 VerilogHDL 编码规则(尽量避免条件竞争): · 时序逻辑建模使用非阻塞赋值; · 锁存器建模使用非阻塞赋值; · 在 always 块中组合逻辑建模使用阻塞赋值; · 在同一个 always 块中对时序逻辑和组合逻辑同时建模使用非阻塞赋值; · 不要在同一个 always 块中混和使用阻塞和非阻塞赋值; · 不要在多个 always 块中对同一个变量赋值; · 使用$strobe 命令显示对非阻塞语句进行的赋值; · 不要使用零延迟赋值语句。 (b)阻塞性过程赋值 必须在顺序块中后续语句执行前执行完毕,但不能阻止并行块中后续语句执行;如: reg y1,y2; y1=0;y2=1; (c)非阻塞性过程赋值

在时钟拍开始时刻计算右边表达式的值, 在时钟拍结束时刻赋值给左边表达式, 即在计 算结果和更新变量期间可以计算其他语句表达式的值并更新, 就是非阻塞赋值语句不阻塞其 他语句的执行。 那么各条非阻塞语句各自独立,并行执行,不会阻塞其他语句执行。"<="为非阻塞赋值 符号,例:reg x1,x2;x1<=9;x2=5; 非阻塞赋值语句只能对寄存器操作,因此只能在过程块(initial 和 always)内部实现。 如果时序逻辑和组合逻辑同时在一个 always 块中出现,常用非阻塞赋值,把这个 always 块 当作时序逻辑来处理。 单独阻塞赋值表示的组合逻辑和单独非阻塞赋值表示的时序逻辑混合,例如: module ex1(q,a,b,clk,rst_n); output q; input clk,rst_n,a,b; reg q,y; always @(a or b) y=a^b; always @(posedge clk or negedge rst_n) if(!rst_n) q<=1`b0; else q<=y; endmodule 建议在所有的时序逻辑编码中使用非阻塞赋值。

三 结构化建模

1.三种示例化描述 结构级描述是在门级或更高级的层次上描述数字系统,有三种示例化的语句来描述: · 原语(primitive)示例,即逻辑门; · 用户自定义基元(UDP)示例,逻辑门的一种扩展; · 模块(module)示例。 VerilogHDL 定义了 14 种原语,分 4 大类:多输入门、多输出门、三态门和 pull 门。 不能在一个 module 内部定义 UDP,要在其外面,但 UDP 只能有一个输出,且输入中 不能出现总线结构。 模块比 UDP 更灵活,可支持任意复杂和任意端口数目,所有实际结构化描述中常用模 块化的结构级描述。 2.模块 (1)三种端口:input、output、inout;缺省的端口型默认为 wire 型,类型声明的长度必须 与端口声明的长度一致。定义与例化一致。 (2)使用参数定义语句,使模块定义内含参数, (3)示例化说明,使模块定义内含参数, (4)实例设计,分行为级、数据流、门级和开关级四种设计;示例化是建立在模块定义基 础上,一次模拟中至少有两个模块,设计模块和测试模块;测试模块一般是顶层模块,并且 一般用行为级描述。循环计数器顶层: module carry_counter4(q,clk,reset); output[3:0] q; input clk,reset; //4 instances of the module T_FF are created T_FF tff0(q[0],clk,reset); T_FF tff1(q[1],q[0],reset); T_FF tff2(q[2],q[1],reset); T_FF tff3(q[3],q[2],reset); endmodule 用到的 T 型触发器: module T_FF(q,clk,reset); output q; input clk,reset; wire d;

D_FF dff0(q,d,clk,reset); not n1(d,q); //非门 endmodule 用到的带同步复位的 D 触发器: module D_FF(q,d,clk,reset); output q; input d,clk,reset; always @(posedge reset or negedge clk); if (reset) q<=1'b0; else q<=d; endmodule 测试模块: module stimulus; reg clk,reset; wire[3:0] q; //计数器例化 carry_counter4 r1(q,clk,reset); //生成时钟 initial clk=1'b0; always #5 clk=~clk;//主频 100Hz? //输入激励控制信号 //0ns--15ns 复位 initial begin reset=1'b1; #15 reset=1'b0; #180 reset=1'b1; #10 reset=1'b0; #20 $finish;//模拟结束 end //监视输出 initial $monitor($time,"Output q=%d",q); endmodule

四门级与开关级建模

行为级、寄存器传输级、门级、开关级建模针对系统的不同层次。Verilog HDL 提供了 18 个门级和开关级的基本基元,设计使用时只要例化并用线网连接起来即可。 门级基元 多输入门 and nand or nor xor xnor 1.三类门级基元 12 种 多输出门 buf 和 not 门,在加上控制信号后成为三态门, 2.开关级基元 14 种 是实际的 MOS 关的抽象表示,分电阻型(前缀 r 表示)和非电阻型; (1)MOS 开关 · nmos 开关:控制信号高,开关导通,否则关闭; · pmos 开关:控制信号低,开关导通,否则关闭; · cmos 开关:模拟了 nmos 和 pmos 开关的组合,一般 ncontrol 和 pcontrol 是互补信号:coms 实例名(out,data,ncontrol,pcontrol); (2) 双向开关: MOS 开关只提供了单向驱动能力, 双向开关的每个脚都声明为 inout 类型, 可做输入驱动或输出被驱动,即可以互相驱动且随时保持一致。 无条件双向开关 tran 和有条件双向开关 tranif0 (只有当 conrol 为 0 时两端互相驱动) 、 tranfi1 (当 control 为 1 时两端互相驱动): tranifx 实例名(inout1,inout2,control); 多输出门 buf not 三态门 bufif0 bufif1 notif0 notif1 开关级基元 MOS 开关 nmos pmos cmos rnmos rpmos rcmos 双向开关 tran tranif0 tranif1 rtran rtranif0 rtanif1

3. 门级建模 实际电路中逻辑门都有一定延迟,提供 3 种延迟: · 上升延迟(rise delay):门的输出态从(0、x、z)到 1 的所需时间; · 下降延迟(fall delay):门的输出态从(1、x、z)到 0 的所需时间; · 关断延迟(turnoff delay):三态门的输出从(0、1、x)到高阻态 z 所需时间。 门级建模:穷举输入输出->卡诺图->布尔函数,布尔函数的自变量就是逻辑门的输 入。 四位全加器例:一位全加器布尔函数为 sum=(a^b^cin);cout=ab+cin(a^b);门级建模: module fulladd(sum,c_out,a,b,c_in); output sum,c_out; input a,b,c_in; //internal nets wire s1,c1,c2; //instantiate logic gate primitive xor(s1,a,b); and(c1,a,b); xor(sum,s1,c_in); and(c2,s1,c_in); xor(c_out,c1,c2); endmodule 四位并行全加器: module fulladd4(sum,c_out,a,b,c_in); output[3:0] sum; output c_out; input[3:0] a,b; input c_in; wire c1,c2,c3; fulladd fa0(sum[0],c1,a[0],b[0],c_in); fulladd fa1(sum[1],c2,a[1],b[1],c1); fulladd fa0(sum[2],c3,a[2],b[2],c2); fulladd fa0(sum[3],c_out,a[3],b[3],c3); endmodule 4.开关级建模 表示开关导通与关断,还表示连接开关的线网上存储电荷的容量,即线网的强度,声明开关 示例连接时在声明说明后注明等级即可;定义的 8 种强度等级: 强度名称 强度等级 声明说明 打印缩写

Supply drive Strong drive

7 6

Supply Strong

Su St

Pull drive 5 Pull Pu Large capacitor 4 Large La Weak drive 3 Weak We Medium capacitor 2 Medium Me Small capacitor High impedance 1 0 Small Highz Sm Hi

使用%v 格式可打印出来。为了模拟实际电路中晶体管开关自身带有电阻,就用电阻型开关 表示(名字中带有 r 的开关),但驱动强度相应降低。 通过电阻型开关后强度降低幅度表 输入强度 输出强度 Supply Strong Pull Large Weak Medium Small Highz Pull Pull Weak Medium Medium Small Small Highz

nmos 与 pmos 开关实现互补型 MOS 电路 nor 门例: module my_nor(out,a,b); output out; input a,b; wire c; //set up power and ground lines supply1 pwr;//pwr is connected to Vdd(power supply) supply0 gnd;//gns is connected to Vss(ground) pmos (c,pwr,a); pmos (out,c,b); nmos (out,gnd,a); nmos (out,gnd,b); endmodule

五用户自定义基元 UDP 通过它来实现门级基元的扩展,可模拟 2 种行为: · 组合行为,由 UDP 的组合基元来模拟; · 时序行为,由 UDP 的时序基元来模拟; 一个 UDP 可以有多个输入,但只能有一个标量输出,输出可有 3 种状态:0、1、x,不支持 高阻态 z,但输入的 z 态往往被当成 x 态。 1.定义

UDP 的定义与模块无关,与模块属同一层次。 规则: · 只允许有一个输出端口的声明,且必须定义在输入端口的定义之前; · 不准有 inout 端口,不能定义成向量的形式; · 在时序 UDP 中,输出端口必须定义成寄存器型,而在组合 UDP 中输出端口却不能定义成 寄存器型; · 逻辑实现主体全部在状态表格 table 中, 每一行所对应的输入激励的顺序都与前面输入端口 定义的次序一样, 且与端口的实际定义内容无关。 在 table 中每个输入/输出端口都有一个域, 输入域和输出域之间用冒号隔开,每一行定义了输入信号所产生的特定组合输出。在时序 UDP 中,还在输入域和输出域之间加入另一个域,指明 UDP 目前的状态,可认为是目前 UDP 的实际输出。没有列出的输入组合所对应的输出都为 x。 格式: primitive 名(接口信号表); output; //端口声明; input; table //状态表格描述; endtable endprimitive UDP 状态表格 符号 解释 注释 0 逻辑 0 1 逻辑 1 x 未知逻辑 ? 逻辑 0、1 或 x 不能用于输出 b 逻辑 0 或 1 不能用于输出 - 不变化 只用于时序基元 (vw) 从 v 到 w 可以是 0、1、x 或? * 同(??) 输入的任何变化 r 同(01) 输入上升沿 f 同(10) 输入下降沿 p 同(01)、(0x)、(x1) 含 x 的上升沿 n 同(10)、(1x)、(x0) 含 x 的下降沿 2.组合 UDP 例,定义一个组合 UDP 并例化, primitive mult(mux,control,data1,data2); output mux; input control,data1,data2; //control data1 data2:mux 0 1 0:1; 0 1 1:1; 0 1 x:1; 0 0 ?:0; //?表示 0、1、x 三种情况,可简化描述表

1 ? 1:1; 1 ? 0:0; x 0 0:0; x 1 1:1; endtable endprimitive 该多路选择器例化如下, module ex1(in1,in2,in3,out1); input in1,in2,in3; output out1; wire out1; mult mult1(out1,in1,in2,in3); endmodule 3.时序 UDP 将有一个存储元素来存储当前状态。分电平和边沿敏感 2 种。 (1)电平敏感的时序 UDP:比组合型多了一个寄存器,主要用来保存当前的状态,也可以 当成是当前的输出。当前的输入和状态确定下一个输出,例: primitive udp_latch(q1,data,clk); output q1; input data,clk; reg q1; initial q1=0; //初始化输出信号为 0 table //data clk : q1(current) q1(next state) 0 0 : ? : -; 0 1 : ? : 0; 1 0 : ? : -; //其中?表示并不关心当前状态 1 1 : ? : 1; //它可以是 0、1 或 x endtable endprimitive (2)边沿敏感的时序 UDP:某输入的跳变触发输出的改变,表格中每一行只能有一个输入 的跳变,D 触发器例如: primitive d_edge(q1,data,clk); output q1; input data,clk; reg q1; initial q1=0; table //data clk : q1(current) q1(next) 0 (01) : ? : 0;//选通,上升沿

1 (01) : ? : 1; //no change in output values 0 (0x) : ? : -;//不选通,没有上升沿 1 (0x) : ? : -; //no change for negedge ? (?0) : ? : -;//不选通,可能是下降沿 //no change for change in data (??) ? : ? : -;//输入的变化不影响输出 endtable endprimitive 例 2,T 触发器, primitive T_FF(q1,clk,clear); output q1; input clk,clear; reg q1; table //clk clear : q1(current) q1(next) ? 1 : ? : 0; ? (10) : ? : -;//忽略 clear 的下降沿 (10) 0 : 1 : 0;//下降沿触发翻转 (10) 0 : 0 : 1; (0?) 0 : ? : -;//忽略时钟的上升沿 endtable endprimitive 构成 4 位循环计数器: module counter4(Q,clk,clear); //IO ports output [3:0] Q; input clk,clear; T_FF tff0(Q[0],clk,clear); T_FF tff1(Q[1],Q[0],clear); T_FF tff0(Q[2],Q[1],clear); T_FF tff0(Q[3],Q[2],clear); endmodule (3)混合时序 UDP:允许同时定义 2 中表,当输入变化时,优先处理边沿触发事件,再处 理电平事件; 若某激励同时触发 2 种事件则输出结果以电平事件为准 (可理解为后修改的结 果)。 JK 触发器描述的混合时序 UDP: primitive jk_edge(q,clk,j,k,preset,clear); output q; input clk,j,k,preset,clear;

reg q; table //clk j k preset clear : q(state) q(output) ? ? ? 0 1 : ? : 1;//preset ? ? ? * 1 : 1 : 1; ? ? ? 1 0 : ? : 0;//clear ? ? ? 1 * : 0 : 0; r 0 0 0 0 : 0 : 1;//normal clocking case r 0 0 1 1 : ? : -; r 0 1 1 1 : ? : 0; r 1 0 1 1 : ? : 1; r 1 1 1 1 : 0 : 1; r 1 1 1 1 : 1 : 0; f ? ? ? ? : ? : -; b * ? ? ? : ? : -; b ? * ? ? : ? : -; endtable endprimitive

六复杂建模 数组、时延、函数、任务与协议。 1.数组 可用 reg、integer、time、real、realtime 和向量寄存器等数据类型,线网类型的数组还可以 用来连接多个示例端口;如 wire w1[7:0];wire w2[0:7];的最高位分别为 w1[0]、w2[7]; 2.延时 检查时序的方式之一是时序仿真,在仿真过程中计算与该模块相关的延迟值;之二是静态 时序验证。 (1)延迟类型 · 分布延迟:在每个独立的元件基础上定义一种建模方式是将延迟值赋给独立的门,另一种 是在单独的 assign 语句中指定延迟值。 · 集总延迟:定义在每个独立模块基础上,表面看来像是模块输出门的当延迟。它比分布延 迟更容易建模。 · 引脚到引脚(即路径)的延迟:分别把延迟赋给模块中从每个输入到每个输出之间的所有 路径。因此可以针对每条输入/输出路径分别指定延迟。对大规模电路而言,它比分布延迟 更容易建模,设计者只需了解模块的输入输出引脚,无需了解模块内部。

(2)路径延迟 · specify 块: 模块路径延迟:在模块的源引脚和目标引脚之间的延迟;在关键字 specify 和 endspecify 之 间给路径延迟赋值。块中包含:给穿过模块的所有路径指定引脚到引脚的时序延迟,在电路 中设置时序检查,定义 specparam 常量。例: module M(out,a,b,c,d); output out; input a,b,c,d; wire e,f; specify (a=>out)=9; (b=>out)=9; (c=>out)=11; (d=>out)=11; endspecify and a1(e,a,b); and a2(f,c,d); and a3(out,e,f); endmodule specify 块是块中一个独立部分,不在任何其他模块(如 initial 或 always)内出现,内部语 句含义必须非常明确。 · specify 块内部: 并行连接:每条路径语句都有一个源域和一个目标域,每一位都对应相连,如果是向量必 须是相同的位数,如例中(source=>destination)=;

全连接:位对位连接,如果源和目标是向量,则不必位数相同,即类似于交叉相连;用法 为:(souce*>destination)=delay_value;例: wire [31:0] e; wire [15:0] f; specify (a,b *> out)=9; (c,d *> out)=11; (e *> f)=9; //相当于 32× 16=352 条并行连接语句的功能; endspecify 边沿敏感连接:用于输入到输出延迟的时序建模,仅当源信号上出现特定边沿时才有用。 例: (posedge clock=>(out +: in))=(10:8); //时钟到输出信号用去上升延迟 10,数据路径从 in 到 out 下降延迟 8; specparam 声明语句:用在 specify 块中声明特殊参数,为了方便给延迟赋值;例: specify specparam d_to_q =9; specparam clk_to_q =11; (d=>q)=d_to_q; (clk=>q)=clk_to_q; endspecify 条件路径延迟:if 句表示,又称状态依赖路径延迟,如: if (a) (a=>out) =9; if (~(a&c)) (b=>out) =10; if ({c,d}==2'b01) (c,d *> out)=13;//拼接操作

上升、下降和关断(turn-off)延迟:可给任意路径定义 1 个、2 个、3 个、6 个或 12 个延 迟参数,其他个数都是错误的;且必须严格按顺序定义;参数有: t_rise,t_fall,t_turnoff,t_delay,t_01,t_10,t_0z,t_z1,t_1z,t_z0,t_0x, t_x1,t_1x,t_x0,t_xz,t_zx;例: specparam t_delay=11; (clk=>q)=t_delay; specparam t_rise=9,t_fall=13,t_turnoff=11;//上升过程 0\z->1, (clk=>q)=(t_rise,t_fall,t_turnoff); //下降过程 1\z->0,关断过程 0\1->z specparam t_01=9,t_10=13,t_0z=11,t_z1=9,t_1z=11,t_z0=13,t_0x=4, specparam t_x1=13,t_1x=5,t_x0=9,t_xz=11,t_zx=7; (clk=>q)=(t_01,t_10,t_0z,t_z1,t_1z,t_z0,t_0x, t_x1,t_1x,t_x0,t_xz,t_zx); //必须严格按照顺序指定延迟参数

最小值、最大值和典型延迟值:每个延迟可指定 3 种形式的值 min:typ:max,如: specparam t_rise=8:9:10=11,t_fall=12:13:14,t_turnoff=10:11:12; (clk=>q)=(t_rise,t_fall,turnoff); 处理 x 状态转换:若没有显示的指定 x 转换的延迟,则保守的方法规定: :从 x 到已知状态转换应当消耗可能的最大时间; :从已知状态到 x 态转换应当消耗可能的最小时间; (3)时序检查 系统任务进行时序检查。$setup,$hold,$width;都只能在 specify 块里。 · $setup 和$hold,用来检查设计中时序元件的建立和保持约束。建立时间,是数据必须在有 效时钟边沿之前到达的最小时间; 保持时间, 是数据在有效时钟边沿之后保持不变的最小时 间。用法:

$setup (被检查的信号,用于检查的参考信号,需要的最小建立时间); 如果(T 检-T 被检查)<建立时间,则报告违反约束。如: specify $setup (data,posedge clk,3); endspecify $hold (reference,data,limit); 若(Tdata-Tref) specify $hold (posedge clr,data,5); endspecify · $width,检查脉冲宽度是否满足最小宽度要求;用法: $width(信号的边沿跳变,脉冲最小宽度); 不显示指定 data,它是 ref 信号的下一个反响跳变沿;若(Tdata-Tref) specify $width(posedge clk,6); endspecify (4)延迟反标注 流程中使用步骤: i.设计者写 RTL 描述,然后进行功能仿真; ii.逻辑综合工具将 RTL 描述转换成门级网表; iii.设计者用延迟计算器和 IC 制造工艺信息获取芯片制作版图前的延迟估 计,然后进行门级网表的时序仿真或者静态时序验证,初步估计检查门级

网表是否满足要求; iv.布局布线工具将门级网表转换成版图,根据版图中电阻和电容信息, 计算制作版图后的延迟值,R 和 C 信息是根据几何形状和 IC 制造工艺提取的 ; v.版图后得到的延迟值反标注到门级网表中,再次时序仿真或静态时序验 证网表; vi.若要改变设计,则返回 RTL 级,优化,再重复 2~5 步。 3.函数和任务 (1)区别 i.任务有或没有入、出和双向变量,函数至少有入变量; ii.任务可调用另一个任务或函数,函数可调用另一个函数不能调用任务; iii.任务可在非零仿真时刻执行,函数总在仿真只可 0 执行; iv.任务可包含延迟、事件、或时序控制声明语句,函数不能,只能代替纯组合逻辑 v 代码; v.任务不返回任何值,可通过 output 或 inout 传递多个值;函数只能返回一个值,不能有输 出变量。 vi.都必须在模块内部定义,可声明局部变量,但不能 wire 型; vii.只能用行为语句,但不能含 initial 和 always 块,但可在 initial 和 always 块中调用任务和 函数。 (2)任务 若满足:i.子程序中包含延迟、时序或者事件控制结构,ii.没有输出或者输出变量数目大于 1 个,iii.没有输入变量, 三个中任意一个条件,必须用任务而不能用函数。如: parameter delay=10; reg [15:0] A,B,AB_ADN,AB_OR,AB_XOR;

always @(A or B) begin bitwise_oper(AB_AND,AB_OR,AB_XOR,A,B);//变量必须按任务定义时的次序 end task bitwise_oper; output [15:0] ab_and,ab_or,ab_xor; input [15:0] a,b; begin #delay ab_and=a&b; ab_or=a|b; ab_xor=a^b; end endtask 任务本质是静态的,其中所有声明项的地址分配是静态分配的,同时并发执行的多个任务 共享这些存储区。为避免在不同地方被同时调用而导致出错,在 task 前加 automatic 字,成 为自动可重入任务,这样调用时是动态分配存储空间,建议使用。如: task automatic bitwise_oper; ... endtask (3)函数 如果一个子程序 i.内不含延迟、 时序和控制结构, ii.只有一个返回值, iii.至少一个输入量, iv.没有输出和双向量,v.不含非阻塞赋值语句, 条件全部成立,则可以使用函数。隐含一个 reg 型的函数标识符传递输出结果。如:

reg [31:0] addr;//地址值 reg parity; always @(addr) begin parity=calc_parity(addr);//第一次启动 $display("parity calculated=%b",clac_parity(addr));//第二次启动 end function calc_parity;//偶校验位计算 input [31:0] address; begin calc_parity=^address;//返回所有地址位的异或值 end endfunction 可以的 ANSI C 风格的定义: function calc_parity(input [31:0] address); begin calc_parity=^address;//返回所有地址位的异或值 end endfunction 例子,左右移位:根据控制信号每次将一个 32 位数左或右移移位, module shifter; `define LEFT_SHIFT 1'b0

`define RIGHT_SHIFT 1'b1 reg [31:0] addr,left_addr,right_addr; reg control; always @(addr) begin left_addr=shift(addr,`LEFT_SHIFT); right_addr=shift(addr,`RIGHT_SHIFT); end function [31:0] shift; input [31:0] address; input control; begin shift=(control==`LEFT_SHIFT)?(address<<1):(address>>1); end endfuncton endmodule


相关文章:
Verilog语言基础知识
Verilog语言基础知识_电子/电路_工程科技_专业资料。有关Verilog语言的一些基础知识和语法相关语言基础知识 Verilog HDL 语言基础知识先来看两个 Verilog HDL 程序。 ...
Verilog HDL语法基础
Verilog HDL语法基础_信息与通信_工程科技_专业资料。Verilog HDL语法基础Verilog HDL 语法基础(1) Verilog 的词法约定 1 2 3 4 5 6 7 Verilog 是大小写相关...
Verilog基础
Verilog基础_计算机软件及应用_IT/计算机_专业资料。数据类型 常量的数据类型 1、二进制 b 八进制 o 十进制 d 十六进制 h <位宽> <进制> <数字>; <进制> ...
Verilog语法基础讲解之参数化设计
小梅哥 FPGA 设计思想与验证方法系列视频教程 Verilog 语法基础讲解之参数化设计在 Verilog 语法中,可以实现参数化设计。所谓参数化设计,就是在一个功能模块中, ...
Verilog+HDL+入门教程(华为)
文档编号文档中心 版本 1.0 密级内部公开 资源类别: HDL语言 共41页 Verilog HDL入门教程 (仅供内部使用) 拟制: 批准: 批准: 中研基础 中研基础 日期: 日期...
Verilog语言基础教程
Verilog语言基础教程_计算机硬件及网络_IT/计算机_专业资料。Verilog最基本知识详解Verilog HDL Verilog HDL 是一种硬件描述语言,用于从算法级、门级到开关级的多种抽...
_Verilog_HDL的基本语法
如果读者已经掌握C语言编程的基础,那么学习 Verilog HDL并不困难,我们只要对Verilog HDL某些语句的特殊方面着重理解,并加强上机练习就 能很好地掌握它,利用它的强大...
Verilog_HDL学习资料
Verilog HDL 允许一个内部端口跟多个外部端口连接; 第八部分 数据流模型化 连续赋值 assign 用于数据流行为建模,过程赋值用于顺序行为建模;组合逻辑电路的行为 最好...
Verilog-A 30分钟快速入门教程
总结这几天的学习,觉得效率太 低,我以前有一定 Verilog 基础,研一时学过一点 VHDL-AMS,学到现在这个 状态应该半天就够了;入门的话,30 分钟足矣;跟着这个教程...
verilog的基础语法总结
赋值语句分为阻塞赋值和非阻塞赋值 阻塞赋值也就是说它阻塞了其他赋值语句的执行,只能进行一步一步的执行, a=b 非阻塞赋值允许其他 verilog 语句同时进行操作,a<...
更多相关标签:
verilog基础视频教程 | verilog语言基础 | verilog基础教程 | verilog | verilog教程 | verilog可综合 | verilog hdl | verilog case |