本文主要是介绍Verilog语法回顾--用户定义原语,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
用户定义原语
UDP定义
UDP状态表
状态表符号
组合UDP
电平敏感UDP
沿敏感时序UDP
参考《Verilog 编程艺术》魏家明著
用户定义原语
用户定义原语(User-defined primitive,UDP)是一种模拟硬件技术,可以通过设计新的原语单元扩大门原语集合。UDP可以和门原语一样使用,用于表示要模拟的电路。
UDP分为两种:
1.组合UDP:使用输入值决定下一个输出值。
2.时序UDP:使用输入值和当前值决定下一个输出值,他可以模拟边沿敏感和电平敏感的行为,所以可以用来模拟触发器和锁存器。
每个UDP只能有一个输出,只能有3种状态:0,1和x。不支持z,如果输入值是z,那就就被当作x。对于时序UDP,输出值总是和内部状态保持一致。
UDP定义
UDP的定义独立于模块,它们和模块定义具有同样的语法层次,不能出现在关键字 module 和 endmodule 之间。
1.使用 primitive 和 endprimitive 定义UDP
2.使用与模块一样的方式声明端口和内部变量
3.使用内部状态表(State table)模拟UDP行为
4.UDP的实例化与模块的实例化类似,但是实例名是可选的,还可以使用延迟值。
UDP状态表
用于定义UDP的行为
1.状态表处于关键字 table 和 endtable 之间,每一行要用分号 ;结束。
2.状态表的每一行都由一些字符组成,用于指出输入值和输出状态,支持0,1和x,不支持z。
3.状态表每一行输入状态的顺序要和UDP端口列表的顺序保持一致。
4.对于组合UDP,输入信号一个区,输出信号一个区,输入区和输出区要用:分开。每一行用于定义在特定输入下的输出
5.对于时序UDP,在输入区和输出区之间要插入一个附加区。附加区用于表示当前UDP的状态,等价于当前输出值。这三个区同样用:分开。每一行用于定义在当前状态和特定输入组合下的输出。
6.如果所有输入都是x,那么输出值也是x。
7.没有必要清晰地列出所有输入组合,因为对于没有列出的输入组合,输出值默认x
8.不能对同样输入值的组合指定不同的输出值。
状态表符号
组合UDP
primitive tsmc_mux(q, d0, d1, s);output q;input d0, d1, s;table// d0 d1 s q0 ? 0 : 0;1 ? 0 : 1;? 0 1 : 0;? 1 1 : 1;0 0 X : 0;1 1 X : 1;endtable
endprimitive
电平敏感UDP
与组合UDP的行为类似,只不过输出是reg类型,而且状态表表中要增加一个附加区。附加区用于表示当前UDP的状态,输出区用于表示UDP的下一个状态。
例子:简单的latch
primitive simple_latch(q, clock, data);output reg q;input clock, data;table//clock data q q+0 1 : ? : 1;0 0 : ? : 0;1 ? : ? : -;endtable
endprimitive
例子: 带有复位和置位的Latch
primitive complex_latch(q, d, e, cdn, sdn, notifier);output reg q;input d, e, cdn, sdn, notifier;table1 1 1 ? ? : ? : 1;0 1 ? 1 ? : ? : 0;0 (10) 1 1 ? : ? : 0;1 (10) 1 1 ? : ? : 1;* 0 ? ? ? : ? : -;? ? ? 0 ? : ? : 1;? 0 1 * ? : 1 : 1;1 ? 1 * ? : 1 : 1;1 * 1 ? ? : 1 : 1;? ? 0 1 ? : ? : 0;? 0 * 1 ? : 0 : 0;0 ? * 1 ? : 0 : 0;0 * ? 1 ? : 0 : 0;? ? ? ? * : ? : x;endtable
endprimitive
沿敏感时序UDP
1.表中每一行最多只能有一个输入信号发生变化,(01) (10) 0 : 0 : 1,非法
2.对于所有没有指明的转换,输出默认为x
3.对于所有不改变输出状态的转换都要清晰的指明,否则就会导致输出变成x
4.如果时序UDP对每个输入的沿都敏感,那么这些沿在表中都要列出来
5.对于时序UDP,可以使用initial语句给输出状态一个初始值。
例子:简单的触发器
primitive simple_dff (q, clock, data);output reg q;input clock, data;table//clock data q q+// obtain output on rising edge of clock(01) 0 : ? : 0;(01) 1 : ? : 1; (0?) 1 : 1 : 1;(0?) 0 : 0 : 0;// ignore negative edge of clock(?0) ? : ? : -;// ignore data changes on steady clock? (??) : ? : -;endtable
endprimitive
UDP允许把沿敏感和电平敏感混合在一起使用。当输入变化时,沿敏感的变化先处理,电平敏感的变化后处理,所以当沿敏感和电平敏感的变化得出不同状态时,最后结果由电平敏感变化的结果决定。
例子:复杂JK触发器
primitive complex_jk_ff(q, clock, j, k, preset, clear);output reg q;input clock, j, k, preset, clear;table// clock jk pc state ouptut/next state? ?? 01 : ? : 1;? ?? *1 : 1 : 1;? ?? 10 : ? : 0;? ?? 1* : 0 : 0;x 00 00 : 0 : 1;x 00 11 : ? : -;x 01 11 : ? : 0;x 10 11 : ? : 1;x 11 11 : 0 : 1;x 11 11 : 1 : 0;f ?? ?? : ? : -;b *? ?? : ? : -;b ?* ?? : ? : -;endtable
endprimitive
这篇关于Verilog语法回顾--用户定义原语的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!