文章目录

  • 前言
  • Verilog中的编写注意事项
    • 大小写敏感
    • Verilog中的关键字
    • 范围定义的正确使用
    • 不要省略begin与end
    • 注释中斜杠的方向
    • 编译指令中的前导符号
    • 混用阻塞和非阻塞赋值的危害
  • 仿真雷区
    • 阻塞赋值顺序
    • 敏感量表缺失
    • 仿真死循环
    • 少用生僻语句

前言

同VHDL一样,Verilog编写已有一些注意事项,但是比较少,下面摘自《FPGA之道》一起看下作者如何总结。

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

不过也恰恰由于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];

不过在Verilog2001版本以后,Verilog支持了在范围中使用变量,并且还引入了新的语法如下:

[<base_index> +: bit_width]  //由低位到高位
[<base_index> -: bit_width]  //由高位到低位
例如:
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

不要省略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之道(37)Verilog中的编写注意事项相关推荐

  1. FPGA之道(31)VHDL编写注意事项

    文章目录 前言 VHDL编写注意事项 大小写不敏感 VHDL中的关键字 多余的符号 纠结的downto 与to 数组范围混用 逻辑向量范围混用 范围中的变量 仿真雷区 进程敏感量表缺失 进程间语句顺序 ...

  2. (64)FPGA面试题-在Verilog中,$display语句可以使用哪些不同的选项?

    1.1 FPGA面试题-在Verilog中,$display语句可以使用哪些不同的选项? 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-在Verilog ...

  3. 【FPGA学习】Quartus II中Testbench编写

    在编写FPGA的程序时,常常要在ModelSim软件上进行仿真,来验证功能 而要进行仿真,就要先编写Testbench 我们可以使用QuartusII总动生成一个Testbench的模板 选择Proc ...

  4. Verilog中可综合及不可综合语句概述

    Verilog中可综合及不可综合语句概述 2017-06-02 23:51 379人阅读 评论(0) 收藏 举报  分类: FPGA(4)  Verilog中可综合及不可综合语句概述 Verilog硬 ...

  5. FPGA之道(35)Verilog中的并行与串行语句

    文章目录 前言 Verilog的并行语句 Verilog连续赋值语句 普通连续赋值语句 条件连续赋值语句 Verilog程序块语句 沿事件 纯组合always 纯时序always 具有同步复位的alw ...

  6. FPGA之道(36)Verilog中的编译指令

    文章目录 前言 Verilog中的编译指令 define指令 timescale指令 inlcude指令 前言 本文摘自<FPGA之道>,一起来了解下Verilog中的编译指令. Veri ...

  7. FPGA之道(84)功能仿真之Verilog Test Fixture

    文章目录 前言 Verilog Test Fixture "Hello world"之Verilog Test Fixture 待仿真设计 仿真示例 示例详解 仿真结果 继承描述语 ...

  8. FPGA之道(67)代码中的约束信息(四)状态机的相关约束

    文章目录 前言 状态机的相关约束 fsm_extract fsm_style fsm_encoding enum_encoding safe_implementation safe_recovery_ ...

  9. FPGA之道(66)代码中的约束信息(三)存储器以及寄存器的相关约束

    文章目录 前言 存储器的相关约束 ram_extract ram_style rom_extract rom_style 寄存器的相关约束 前言 这是这个话题的第三篇,最重要的前言是本文节选自:< ...

最新文章

  1. 软件体系架构阅读笔记一
  2. python之IO操作
  3. mysql恢复root密码
  4. zookeeper 安装及集群
  5. css3 背景属性与边框属性的新增 200303
  6. leetcode - 111. 二叉树的最小深度
  7. css3动画 --- Transition
  8. 第3章 系统设计和架构设计【扩胸运动,有容乃大】
  9. 低秩恢复算法(图像去噪)
  10. 甲骨文裁员是在为云业务转型太慢埋单吗?
  11. mysql数据库误删除后的数据恢复操作说明
  12. 2020科目一考试口诀_2020驾考技巧科目一考试口诀答题法
  13. SHOWWINDOW最小化不好用
  14. 计算机网络连接限制,网络受限制或无连接怎么办?电脑网络连接受限制或无连接问题...
  15. 男士必须收藏:男士健身方案
  16. 【模型压缩】蒸馏神经网络(Distill the Knowledge in a Neural Network)
  17. 苹果CMS V10自动采集脚本开始执行 版本:v1.0
  18. Unity使用反射探头实现地面的镜面反射
  19. (Verilog)单周期CPU设计
  20. matplotlib 怎么画核密度

热门文章

  1. 构建高性能的ASP.NET应用(五)-如何开始寻找性能瓶颈
  2. AndroidManifest.xml配置文件详解
  3. 用pcl读ply文件_PCL之轨迹绘制(二)
  4. mysql cluster 安装_MYSQL Cluster安装攻略
  5. qt vs 不出来dos窗口_VS嵌入QT后,建立QT工程后printf和cout无效,无法产生控制台应用程序窗口,需设置工程属性...
  6. 职校电子计算机专业高考分数线,2015年重庆高考分数线公布:一本文572理573
  7. linux将mysql的错误连接数_Mysql学习笔记(十二) 并发参数调节
  8. 大连评职称英语计算机,假如 职称英语和中级职称的工商管理、经济基础都考过了,辞职了还有地方给评中级经济师吗?大连的...
  9. linux 内核位置无关,Linux内核启动阶段虚实地址映射
  10. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)