hdm - FPGA知识点(6)

2025-07-14

与nmos和pmos相比,rnmos和rpmos在输入引线和输出引线之间存在高阻抗(电阻)。因此当数据从输入传输至输出时,对于rpmos和rmos,由于电阻带来的损耗,存在数据信号强度衰减。

pmos P1 (BigBus, SmallBus, GateControl); 实例名为P1 的pmos开关。 rnmos RN1 (ControlBit, ReadyBit, Hold); ?????

cmos和rcmos(cmos的高阻态版本)有4个端口:两个控制信号输入端。其形式如下:

(r)cmos[instance_name](OutputA, InputB, NControl, PControl); (r)cmos [instance_name] (OutputA, InputB, Ncontrol, PControl);

第三个端口为n通道控制输入,第四个端口为是P通道控制输入。

cmos(rcmos)开关行为与带有公共输入、输出的pmos(rpmos)和nmos(rnmos)开关组合十分相似。

6) 双向开关:tran rtran tranif0 rtranif0 tranif1 rtranif1

双向的,即数据可以双向流动,并且当数据在开关中传播时没有延时。后4个开关能够通过设置合适的控制信号来关闭。tran和rtran开关不能被关闭。不能关断的,始终处于打开状态,数据可以在两个端口之间自由流动。 tran或rtran(tran 的高阻态版本)

(r)tran [instance_name] (SignalA, SignalB ); 无条件地双向流动,即从SignalA向SignalB,反之亦然。

其它双向开关的实例语句的语法如下:

gate_type[instance_name] (SignalA, SignalB, ControlC);

前两个端口是双向端口,即数据从SignalA流向SignalB,反之亦然。第三个端口是控制信号。 对tranif0和rtranif0,ControlC是1;

对tranif1和rtranif1,Controlc是0;那么禁止双向数据流动。

对rtran、rtranif0和rtranif1,当信号通过开关传输时,信号强度减弱。

5.8 门时延

可以使用门时延定义门从任何输入到其输出的信号传输时延。 gate_type [delay] [instance_name] (terminal_list);

时延规定了门时延,即从门的任意输入到输出的传输时延。当没有强调门时延时,缺省的时延值为0。 门时延由三类时延值组成:

1) 上升时延 2) 下降时延 3) 截止时延

门时延定义可以包含0个、1个、2个或3个时延值。

无时延 1个时延(d) 2个时延(d1, d2) 3个时延 (dA, dB, dC)

not N1 (Qbar, Q); 没有定义时延,门时延为0。

nand #6 (Out, In1, In2); 所有时延均为6,上升时延和下降时延都是6 输出决不会是高阻态,截止时延不适用于与非门。转换到x的时延也是6

and #(3,5) (Out, In1, In2, In3); 上升时延被定义为3,下降时延为5,转换到x的时延是3和5中间的最小值,即3

notif1 #(2,8,6) (Dout, Din1, Din2); 上升时延为2,下降时延为8,截止时延为6,转换到x的时延是2、8和6中的最小值,即2。

对多输入门(例如与门和非门)和多输出门(缓冲门和非门)总共只能够定义2个时延(因为输出决不会是z)。 三态门共有3个时延

上拉、下拉电阻实例门不能有任何时延

门延迟也可采用min:typ:max形式定义。形式如下:

minimum: typical: maximum

nand #(2:3:4, 5:6:7) (Pout, Pin1, Pin2); 如果执行最大时延模拟,与非门单元使用上升时延4和 下降时延7。

4.3 模块实例化

调用低层子模块把所有模块连接成整个电路或者高层模块时,要使用模块实例化语句。

module_name instance_name(port_associations); 其中port_associations是端口关联声明。 4.3.1 端口关联声明

子模块的输入输出端口应该连接到高层模块中,完成这种连接的是高层模块中的线网和寄存器,其连接方式可以是“位置关联方式”和名称关联方式,二者形式如下:

port_expr //位置关联方式 .PortName(port_expr) //名称关联方式

Portname是子模块定义时给出的端口名称,port_expr是高层模块内定义的线网或寄存器变量,这个变量与子模块端口关联就实现了子模块与高层模块的连接。

在位置关联方式中,不需要给出子模块定义时给出端口名称PortName,只要把相应的prot_expr按指定的顺序排列就能和子模块的端口关联,这个排列顺序必须和子模块定义时给出的 端口顺序相同。

4.3.2 悬空端口

在模块实例化语句中,允许端口出现悬空,可以将端口表达式表示为空白来指定悬空端口。看下例: module DFF(Q, Qbar, Data, Preset, Clock); output Q, Qbar;

input Data, Preset, Clock; .............. endmodule

在高层模块中两次调用DFF模块,模块实例化语句如下:

DFF d1(.Q(Q), .Qbar( ), .Data(D), .Preset( ), .Clock(CK) );

//名称关联方式,其中输出端口Qbar和输入端口Preset的括号里都是空的,表明这两个端口被悬空。 DFF d2(QS, ,D, , CK); //位置关联方式,输出端口Qbar和输入端口Preset的位置空白,被悬空。 4.3.3 端口匹配

在端口关联时,如果出现关联端口长度不同的情况,处理方式是通过无符号数的右对齐并截断的方式进行匹配。 4.3.4 模块参数值

如果子模块内定义了参数,当这个子模块被引用时,高层模块能够改变子模块的参数值。改变模块参数值可以采用两种方式:参数定义语句(使用关键词defparam)和带参数值的模块引用。

(1)参数定义语句

参数定义语句需要使用关键词defparam,其形式如下:

defparam hier_path_name1 = value1, hier_path_name2 = value2, ..........;看下面的例子: 子模块半加器的描述如下: module HA(A, B, S, C); input A, B; output S, C;

parameter AND_DELAY = 1, XOR_DELAY = 2; //定义了两个参数 assign #XOR_DELAY S = A^B assign #AND_DELAY C = A&B endmodule

高层模块描述如下:

module TOP(NewA, NewB, NewS, NewC); input NewA, NewB; output NewS, NewC;

defparam ha1.XOR_DELAY = 5, ha1.AND_DELAY = 2; HA ha1(NewA, NewB, NewS, NewC); end module

在这个高层子模块中,引用了子模块HA,并将其实例命名为ha1,通过defparam语句给ha1的连个参数重新赋值。 (2)代参数值的模块引用

在这种方法中,模块实例化语句自身包含有新的参数值。实现方式如下: HA #(5,2) HA1(NewA, NewB, NewS, NewC);

给出参数值的方式是“#(5,2)”,形式上与时延定义相似,但意义完全不同。在这种方式中,模块实例化语句中参数值的顺序 必须与子模块中 声明参数的顺序相同。

在verilog中,用户可以定义任务和函数,而且它还内置了一些系统任务和系统函数用于实现某些特定的操作 5.1 任务

任务就是一段封装在“task-endtask”之间的程序。任务是通过调用来执行的,而且只有在调用时才执行,如果定义了任务,但是在整个过程中都没有调用它,那么这个任务是不会执行的。调用某个任务时可能需要它处理某些数据并返回操作结果,所以任务应当有接收数据的输入端和返回数据的输出端。另外,任务可以彼此调用,而且任务内

还可以调用函数。

注意:任务是不可综合的,它只能用于仿真。 5.1.1 任务定义 任务定义的形式如下: task task_id [declaration] procedural_statement endtask

其中,task_id是任务名;可选项declaration是端口声明语句和变量声明语句,任务接收输入值和返回输出值就是通过此处声明的端口进行的;procedural_statement是一段用来完成这个任务操作的过程语句,如果过程语句多于一条,应将其放在语句块内。

任务调用语句可以在initial语句和always语句中使用,其语法形式如下: task_id[(expr1, expr2, ........, exprN)];

task_id是要调用的任务名,expr1, expr2, ........是参数列表。参数列表给出传入任务的数据(进入任务的输入端)和接收返回结果的变量(从任务的输出端接收返回结果),任务调用语句中参数列表的顺序必须与任务定义中的端口声明顺序相同。任务调用语句是过程性语句,所以任务调用中接收返回数据的变量必须是寄存器类型。来看下例:

module Has_Task; parameter MAXBITS = 8; task Reverse_Bits; input [MAXBITS-1:0] Din; output [MAXBITS-1:0] Dout; integer K; begin

for(K=0; K

Dout[MAXBITS-K] = Din[K];

end endtask end module

下面调用Reverse_Bits的代码: reg[MAXBITS-1:0] Reg_X, New_Reg; Reverse_Bits(Reg_X, New_Reg);

其中,Reg_X的值作为输入数据送到任务的输入端Din,任务的返回值从其输出端Dout输出并交给New_Reg,在寄存器new_reg中得到返回值。

调用任务时,可以引用任务声明所在的模块内定义的任何变量。

任务内可以带有时序控制,如时延。但要注意,任务的输出值必须等到整个任务的全部语句都执行完之后才能返回。

5.2 函数

“function-endfunction”之间。函数与任务的不同之处在于: ·函数只能返回一个值,而任务可以有多个返回值;

·函数一经调用就必须立即执行,其内部不能包含任何时序控制,而任务内部可以有时序控制; ·函数可以调用函数,但是不能调用任务,而任务即可以调用任务也可以调用函数; ·函数至少有一个输入,而任务可以没有输入端。 5.2.1 函数定义

函数定义和任务定义一样,可以出现在模块内的任何位置,其形式如下: function [range] function_id; input_declaration other_declarations procedural_statement endfunction

这里的range用于指定函数的取值范围,是可选项,若没有指定,默认缺省值为1。 module Function_Example; parameter MAXBITS = 8;

function [MAXBITS-1:0] Reverse_Bits; input [MAXBITS-1:0] Din; integer K; begin

for(K=0; K

Reverse_Bits[MAXBITS-K] = Din[K];

end

endfunction endmodule

注意到没有,函数的定义中并没有声明输出,那么函数执行得到的结果如何返回呢?事实上,函数定义时,在函数内部已经隐性的声明了一个寄存器变量,该寄存器变量与函数名同名并且取值范围也相同。那么函数如何通过这个寄存器返回值?注意上例中的“Rever_Bits[MAXBITS-K] = Din[K];”这条语句,就是通过这条语句把Din[K]的值赋给寄存器Reverse_Bits[MAXBITS-K],同时也实现了值的返回。

5.2.2 函数调用

和任务一样,函数也是在被调用时才被执行的,调用函数的语句形式如下:


hdm - FPGA知识点(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:几何12圆与扇形

相关阅读
本类排行
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 7

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219