FPGA的设计艺术(14)使用函数和任务提升逻辑的可重用性(fpga的设计方法)
1077
2022-05-29
文章目录
前言
Verilog中的编写注意事项
大小写敏感
Verilog中的关键字
范围定义的正确使用
不要省略begin与end
注释中斜杠的方向
编译指令中的前导符号
混用阻塞和非阻塞赋值的危害
仿真雷区
阻塞赋值顺序
敏感量表缺失
仿真死循环
少用生僻语句
前言
Verilog中的编写注意事项
大小写敏感
Verilog是一种case sensitive的语言,即敏感大小写。例如以下几个变量是不一样的:
reg abc;
reg Abc;
reg aBc;
reg ABC;
在verilog中,它们分别代表4个不同的寄存器类型,不能搞混。如过定义了一个寄存器类型变量a,但是使用的时候写成A,编译器会报错,表示没有找到A的定义。
Verilog中的关键字
Verilog中的命名也不能与关键字相同, 所以在书写代码的时候也要避免使用了关键字作为标识符。以下列举了Verilog中的一些关键字供大家参考,可以看出Verilog中的关键字都是小写的,由于Verilog是大小写敏感的,所以只要标识符不完全和关键字一样即可。
always and assign attribute begin buf bufif0 bufif1 case casex casez cmos deassign default defparam disable edge else end endattribute endcase endfunction endmodule endprimitive endspecify endtable endtask event for force forever fork function highz0 highz1 if ifnone initial inout input integer join medium module large macromodule nand negedge nmos nor not notif0 notif1 or output parameter pmos posedge primitive pull0 pull1 pulldown pullup rcmos real realtime reg release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared signed small specify specparam strength strong0 strong1 supply0 supply1 table task time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg unsigned vectored wait wand weak0 weak1 while wire wor xnor xor
1
2
3
4
5
6
7
8
9
10
不过也恰恰由于Verilog是大小写敏感的,所以在使用关键字时切忌要保持全部小写,例如,如下的使用都是错误的:
REG a; // wrong, should be “reg”
Wire b; // wrong, should be “wire”
aSSign b = 1’b1; // wrong, should be “assign”
范围定义的正确使用
在Verilog中,声明端口或者变量时,往往都需要配合语法来说明位宽信息,例如:
wire [15:0] x;
不过下述定义也是正确的,
wire [0:15] y;
即范围可以从大到小,也可以从小到大。但是像上述这样的定义往往会让人犯迷糊,从而导致使用的时候出现很多问题。为了能够正确使用,减少出问题的机率,我们列举出范围参数的详细语法:
[MSB:LSB]
从范围参数的详细语法我们可以看出,范围参数的左边界是对应MSB的,右边界是对应LSB的。所以,如果一个二进制数c按照从左至右,从MSB到LSB排列,为
c15、c14、c13……、c2、c1、c0;
那么如果做如下操作:
assign x = c;
assign y = c;
则x[15] = c15, x[0] = c0; y[0] = c[15], y[15] = c0;
记住这一对应关系即可自如应对范围定义不统一的问题,不过建议大家还是使用从大到小的范围定义法,因为这和二进制数的排列是一致的,方便理解和编程,并且在初始化数组时,有时候只有按照这种方法定义的数组才能初始化成功。
除此以外,在早期版本的Verilog语言中,范围参数中不允许出现变量,当需要根据变量来选择范围的时候,只能通过单个索引的方式来完成,例如:
a = b[i:i-3]; //wrong 需要改成 a[3] = b[i]; a[2] = b[i-1]; a[1] = b[i-2]; a[0] = b[i-3];
1
2
3
4
5
6
不过在Verilog2001版本以后,Verilog支持了在范围中使用变量,并且还引入了新的语法如下:
[
1
2
例如:
1
wire [7:0] b; wire [3:0] a = b[6 -: 4]; //equal to a= b[6:3]; integer i; reg [3:0] c; c <= b[i -: 4]; //must in always
1
2
3
4
5
不要省略begin与end
在Verilog中,很多语句都可以包含一些子语句,例如always程序库、if条件、for循环等等。一般情况下,如果某个分支中子语句的数量仅有一条的时候,可以省略begin-end语法。例如:
always@*
if(sel == 1’b1)
a = b;
else
a = c;
不过,为了保证代码的一致性和可读性,更为了减少出错的可能,建议大家不要省略begin-end语法。这样虽然代码看起来略微长一些,但是无论是从修改还是从阅读来说都会给我们带来极大便利。例如上例改写如下:
always@*
begin
if(sel == 1’b1)
begin
a = b;
end
else
begin
a = c;
end
end
顺便提一下,唯一不能省略begin-end语法的是循环生成语句。
注释中斜杠的方向
Verilog的注释符号有两种:
“//”和“/* … */”
请注意斜杠的方向为键盘中和“?”共用一个键位的斜杠符号,而不是反斜杠“\”。
编译指令中的前导符号
使用编译指令时,都需要在前面加一个前导符号“”,并且在引用宏定义中参数的时候也需要加这个符号来表明。注意,该符号不是单引号“’”,而是位于键盘左上角和“~”符号共用一个键位的“”符号。
混用阻塞和非阻塞赋值的危害
如果在一个always程序块中,混用阻塞与非阻塞赋值,轻则会造成组合逻辑和时序逻辑混杂在一起的结果,给人带来很大的混乱;重则直接影响仿真或编译的正确性。
如果给一个变量混用混用阻塞与非阻塞赋值,那么结果更是不可预测,估计这个时候你自己都不知道你是希望它被综合工具翻译成连线还是寄存器,此时只有期待老天保佑了!
仿真雷区
阻塞赋值顺序
从阻塞赋值的意义我们就可以得知,如果代码书写的顺序改变,那么程序的功能就可能会有变化。这尤其对仿真器影响最大,因为仿真器是完全按照Verilog语法来理解程序的。
例如:
always@(a, b)
begin
t = a & b;
c = ~ t;
end
若写成这样仿真就会出现问题,即每次a或b改变时,c得到的是上一次a、b的与非结果:
always@(a, b)
begin
c = ~ t;
t = a & b;
end
若要保证仿真行为正确,可以在敏感量表中添加本来不是输入变量的变量t。但是带来的负面影响就是always必须执行两次才能得到正确的结果。
always@(a, b)
begin
t = a & b;
c = ~ t;
end
敏感量表缺失
敏感量表的缺失问题一般指的都是组合逻辑always,因为时序逻辑的敏感量表比较固定,一般不会出问题。如果敏感量表缺失,那么其实从语法上来看是会引入锁存的,但是目前的编译器一般都会帮助客户补全敏感量表从而避免锁存的出现,而仿真器没有该功能,所以如果敏感量表缺失,是会影响到仿真结果的。例如:
always@(a)
begin
t = a & b;
c = ~ t;
end
此时,若b改变,c不会改变,因为仿真器认为该程序块不敏感b的事件。
仿真死循环
组合逻辑如果表述的不好,很容易造成仿真死循环,例如,类似如下的代码都是有问题的:
always@*
a = not a;
或
assign b = m + b;
以上反馈如果出现在时序逻辑中,不会有任何问题,因为时序逻辑中的赋值要到下一个周期才会生效。但是如果用在组合逻辑中,由于赋值马上生效,一旦生效后的值与之前的值不同,又会激发下一次赋值,如此往复而无穷尽,所以仿真器会卡在这一时刻无法走下去。
当然了,并不是说一定不能存在反馈,而是不能存在负反馈,例如SR锁存器就可以利用正反馈来实现稳定的电路变化。虽然实际中有存在负反馈的数字组合逻辑电路,但是它得到的结果对数字逻辑来说是没有意义的,因此在编程时请注意避免。
少用生僻语句
正如我们在本篇开头所说,语言在不断发展,仿真器也在不断发展,那么肯定是越常用的语法,越规范的语句,仿真器支持的越好,那些比较生僻的语句,即是仿真器支持,编译器还不一定支持,所以,建议大家多多使用常用的语法结构进行编程,请放心,这完全不会影响你去实现一个非常非常复杂的设计,反而这才是最好的做法。
FPGA
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。