用户自定义基元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