Verilog代码质量规范


目录

一张网图 示意用

前言

Verilog,虽然教材或者一些教程一直在强调本质上其实是在构建一个适应我们需求的电路,但是由于Verilog的并行性和并不适用于传统软件流的抽象层级,以及一些许许多多的小trick的存在,所以要想写好还是不容易的。

并行性就意味着一段功能代码,在VSCode编辑器里,无论是在上方还是下方,其功能都是一样的,但是怎么安排它,让其视觉和逻辑上变得合理,是需要我们考虑的。

其硬件描述的抽象层级就意味着它不是通过一行行功能指令去完成某个操作的,本质上是在构建每个状态所需要触发的逻辑门。

状态机是我们编写Verilog时刻要考虑的东西,通过状态机这一抽象层我们能够把硬件电路的行为通过一个个状态去触发。所以我们在编写模块的时候必须深刻理解模块要进行的操作,了解其每一个操作所占用的状态,和状态之间跳转的逻辑。

而一个模块中可能又有一个主状态机来完成操作,其他的一些辅助电路来完成统计,为了便于模块间的连接和测试,最好遵循一定的模块命名和信号命名规范。

基本语法

试图用一张网图来讲清楚
来自b站up的一张网图

命名规范

信号命名

  • 采用有意义且有效的名字,尽量采用连贯的缩写,比如:address →addr; clock→clk;
  • 长信号名用下划线“ _”分割单词;
  • 特殊信号加后缀表示其特性,如:低电平有效信号: _n;时钟信号:_clk;输入信号:_i ; 输出信号:_o
  • 寄存器打拍的信号,第一级以“ff1”结尾,后面依次“ ff2”,”_ff3”,其他类型的信号禁止使用该后缀命名;
  • 不建议使用reg作为信号结尾;
  • 不使用vdd, vss, vcc, vref开头为普通信号命名;
  • define和parameter定义的常量和参数使用全大写;
  • 所有的模块名,信号名,变量名和端口名小写,不建议使用驼峰命名法,而是**_**作为连接符

模块例化时

  1. 使用xxx_inst作为模块名,多次例化可以使用xxx_inst1,xxx_inst2等
  2. 模块连接使用端口名连接,不要使用顺序连接。
  3. 模块的参数例化也需要列写完整

编写规范

关于注释

(1) 文件头说明,包括:版权声明,作者信息说明,版本号,日期,修改记录模块功能(越详细越好,甚至可以放上时序图,状态机) 等等;

(2) 信号说明,信号基本功能描述等;

复位电平是高复位还是低复位;
disable/en, 其0或1具体代表什么含义;
时钟频率是多少?
多bit的包起来的信号,如type[1:0],或者包起来的以太网帧,可以说明每一段的含义,比如[31:16]是xxx
信号的来源模块或者去到哪个模块(from/to)便于顶层连接和维护
(3) 代码分段说明,包括代码块起点/结束描述,代码段基本功能描述等;

功能描述可以便于理解代码块功能;
起点和结束点描述可以准确定位代码的开始结束,便于阅读和理解;
好的代码分段说明,可以有利于开发的思路分析;
(4) 尽量去掉确实不需要的注释代码,过多冗余代码不利于阅读

代码块分段的模板

文件头声明:说明模块完成了什么工作,在module定义的上一行用注释说明

端口信号声明:按照交互信号的类型进行分类;不建议按照输入输出划分

参数声明: localparam本模块使用,不可传入,可以避免外部修改或者覆盖本模块的参数设置

内部信号声明:可以按照信号功能分段声明(参考端口信号声明建议)

模块的真正代码实现:逻辑块和例化一起进行,每完成了一项具体工作的逻辑块+ip核例化称为一个block logic1+instance1 +** logic2+instance2** + …

一些提示和技巧

不关闭QuestaSim就重启仿真的方法

在仿真文件夹下新建一个restore.do文件

然后把tb_top_compile , tb_top_elaborate, tb_top_simulate等文件全部添加到restore中,然后可以酌情修改,比如添加你想要的模块的.do文件,后面只需要执行restore.do就可以进行重仿真,不需要关闭再点开

有时候在Modifying Modelsim.ini的时候卡住

进工程把仿真的文件夹全部删掉,再次打开重新生成就好

有读取-计算-存储这个过程的,其中一定要用时序逻辑

特别是在状态机的某个状态中进行的计算,比如自增,如果是组合逻辑,仿真看上去是对的,但是上板不对

用到了Distributed RAM,即使是无寄存的,读取一定要有延迟

不要刻意为了节省那一拍,直接在给完地址后就立马从数据线上取出wire的值,很容易造成仿真看上去是对的,实际上上板读出来的是全0,而且从行为级仿真上放大后也可以看出,给完地址后会有很短暂的一个延迟,wire上才会有真正的数据出现

不定态’hx如果被写入了RAM中,会造成很多意想不到的错误
通过if else的else语句可以阻止不定态’hx的传播
高阻态’hz一般是没有驱动信号

从FPGA外部引入的电平信号,如果不知道其是推挽还是开漏,需要在管脚约束时检查上下拉否则会导致不定态


文章作者: Allen Hong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Allen Hong !
  目录