Verilog代码设计风格

1.信号命名规则

信号命名规则在团队开发中占据着重要地位,统一、有序的命名能大幅减少设计人员之间的冗余工作,还可便于团队成员代码的查错和验证。比较著名的信号命名规则当推Microsoft 公司的“匈牙利”法,该命名规则的主要思想是“在变量和函数名中加入前缀以增进人们对程序的理解”。例如所有的字符变量均以ch 为前缀,若是常数变量则追加前缀c。

信号命名的整体要求为:命名字符具有一定的意义,直白易懂,且项目命名规则唯一。对于HDL 设计,设计人员还需要注意以下命名规则。

(1)系统级信号的命名

系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号。系统信号以字符串sys 或syn 开头;时钟信号以clk 开头,并在后面添加相应的频率值;复位号一般以rst 或reset 开头;置位信号为st 或set 开头。典型的信号命名方式如下所示:

wire [7:0] sys_dout, sys_din;
wire clk_32p768MHz;
wire reset;
wire st_counter;

(2)低电平有效的信号命名

低电平有效的信号后一律加下划线和字母n。如:

wire SysRst_n;
wire FifoFull_n;

(3)经过锁存器锁存后的信号

经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。如:

信号CpuRamRd 信号,经锁存后应命名为CpuRamRd_r。

低电平有效的信号经过锁存器锁存后,其命名应在_n 后加r。如:

CpuRamRd_n 信号,经锁存后应命名为CpuRamRd_nr

多级锁存的信号,可多加r 以标明。如:

CpuRamRd 信号,经两级触发器锁存后,应命名为CpuRamRd_rr。

2.模块命名规则

HDL 语言的模块类似于C 语言中的函数,可采用C 语言函数的大多数规则。模块的命

名应该尽量用英文表达出其完成的功能。遵循动宾结构的命名法则,函数名中动词在前,并

在命名前加入函数的前缀,函数名的长度一般不少于2 个字母。HDL 模块的命名还需要考

虑以下情况:

(1)模块的命名规则

在系统设计阶段应该为每个模块进行命名。命名的方法是,将模块英文名称的各个单词

首字母组合起来,形成3 到5 个字符的缩写。若模块的英文名只有一个单词,可取该单词的

前3 个字母。各模块的命名以3 个字母为宜。例如:

Arithmatic Logical Unit 模块,命名为ALU。

Data Memory Interface 模块,命名为DMI。

Decoder 模块,命名为DEC。

(2)模块之间接口信号的命名

所有变量命名分为两个部分:第一部分表明数据方向,其中数据发出方在前,数据接收方在后;第二部分为数据名称。两部分之间用下划线隔离开。第一部分全部大写,第二部分所有具有明确意义的英文名全部拼写或缩写的第一个字母大写,其余部分小写。举例:

wire CPUMMU_WrReq;

下划线左边是第一部分,代表数据方向是从CPU 模块发向存储器管理单元模块(MMU)。下划线右边Wr 为Write 的缩写,Req 是Request 的缩写。两个缩写的第一个字母都大写,便于理解。整个变量连起来的意思就是CPU 发送给MMU 的写请求信号。模块上下层次间信号的命名也遵循本规定。若某个信号从一个模块传递到多个模块,其命名应视信号的主要路径而定。

(3)模块内部信号

模块内部的信号由几个单词连接而成,缩写要求能基本表明本单词的含义;单词除常用的缩写方法外(如:Clock->Clk,Write->Wr,Read->Rd 等),一律取该单词的前几个字母(如:Frequency->Freq,Variable->Var 等);每个缩写单词的第一个字母大写;若遇两个大写字母相邻,中间添加一个下划线(如DivN_Cntr);举例:

SdramWrEn_n;

FlashAddrLatchEn;

3.代码格式规范

(1)分节书写格式

各节之间加1 到多行空格。如每个always,initial 语句都是一节。每节基本上完成一个特定的功能,即用于描述某几个信号的产生。在每节之前有几行注释对该节代码加以描述,至少列出本节中所描述信号的含义。

行首不要使用空格来对齐,而是用Tab 键,Tab 键的宽度设为4 个字符宽度。行尾不要有多余的空格。

(2)注释的规范

使用//进行的注释行以分号结束;使用/* */进行的注释,/*和*/各占用一行,并且顶头;

例如:

// Edge detector used to synchronize the input signal;

对于函数,应该从“功能”,“参数”,“返回值”、“主要思路”、“调用方法”、“日期”六

个方面用如下格式注释:

// 程序说明开始

// ================================================================//

// 功能: 完成两个输入数的相加。

// 参数: strByDelete,strToDelete

// 输入参数

// 输出参数

// 主要思路:本算法主要采用2 级流水线完成相加

// 日期:起始日期,如:2008/8/21.9:40--2008/8/23.21:45

// 版本:

// 程序编写人员:

// 程序调试记录:

// ================================================================//

// 模块说明结束

此外,在注释说明中,需要注意以下细节:

� 在注释中应该详细说明模块的主要实现思路,特别要注明自己的一些想法,如果有必要则应该写明对想法产生的来由。

� 在注释中详细注明函数的适用方法,对于输入参数的要求以及输出数据的格式。

� 在注释中要强调调用时的危险方面,可能出错的地方。

� 对日期的注释要求记录从开始编写模块到模块测试结束之间的日期。

� 对模块注释开始到模块命名之间应该有一组用来标识的特殊字符串。如果算法比较复杂,或算法中的变量定义与位置有关,则要求对变量的定义进行图解。对难以理解的算法能图解尽量图解。

(3)空格的使用

不同变量,以及变量与符号、变量与括号之间都应当保留一个空格。Verilog HDL 语言关键字与其它任何字符串之间都应当保留一个空格。如:

always @ ( ...... )

使用大括号和小括号时,前括号的后边和后括号的前边应当留有一个空格。逻辑运算符、算术运算符、比较运算符等运算符的两侧各留一个空格,与变量分隔开来;单操作数运算符例外,直接位于操作数前,不使用空格。使用//进行的注释,在//后应当有一个空格;注释行的末尾不要有多余的空格。例:

assign SramAddrBus = { AddrBus[31:24], AddrBus[7:0] };

assign DivCntr[3:0] = DivCntr[3:0] + 4'b0001;

assign Result = ~Operand;

(4)begin…end 的书写规范

同一个层次的所有语句左端对齐;initial、always 等语句块的begin 关键词跟在本行的末尾,相应的end 关键词与initial、always 对齐,并且在end 后面添加注释标明结束;这样做的好处是避免因begin 独占一行而造成行数太多;如:

always @ ( posedge SysClk or negedge SysRst ) begin
if( !SysRst ) DataOut <= 4'b0000;
else if( LdEn ) begin
DataOut <= DataIn;
End
else
DataOut <= DataOut + 4'b0001;
end //end always 模块

不同层次之间的语句使用Tab 键进行缩进,每加深一层缩进一个Tab;在endmodule,endtask,endcase 等标记一个代码块结束的关键词后面要加上一行注释说明这个代码块的名称。

4.模块调用规范

如3.2.2 节所述,在Verilog 中,有两种模块调用的方法,一种是位置映射法,严格按照模块定义的端口顺序来连接,不用注明原模块定义时规定的端口名,其语法为:

被调用模块名 用户自定义调用名

(连接端口1 信号名, 连接端口2 信号名, 连接端口3 信号名,…);

另一种为信号映射法,即利用“.”符号,表明原模块定义时的端口名,其语法为:

被调用模块名 用户自定义调用名

(.端口1 信号名(连接端口1 信号名),

.端口2 信号名(连接端口2 信号名),

.端口3 信号名(连接端口3 信号名),…);

显然,信号映射法同时将信号名和被引用端口名列出来,不必严格遵守端口顺序,不仅降低了代码易错性,还提高了程序的可读性和可移植性。因此,在良好的代码中,严禁使用位置调用法,全部采用信号映射法。

原文发布于微信公众号 - 瓜大三哥(xiguazai_tortoise)

原文发表时间:2016-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android先生

Java多线程-带你认识Java内存模型,内存分区,从原理剖析Volatile关键字

地址:https://juejin.im/post/59f8231a5188252946503294

983
来自专栏owent

我们的Lua类绑定机制

最近一个人搞后台,框架底层+逻辑功能茫茫多,扛得比较辛苦,一直没抽出空来写点东西。

2651
来自专栏用户画像

浅析JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模...

842
来自专栏tkokof 的技术,小趣及杂念

HGE系列之六 管中窥豹(资源管理)

记的上次浮光掠影的讲了一些HGE中的基础类别,不知大家了解了多少,仔细看过的朋友肯定知道当时在讲述一个类别的构造函数时我打了个马虎,直接略过了,原因说的好像是...

781
来自专栏平凡文摘

JDK 10 的 109 项新特性

1002
来自专栏Golang语言社区

(译)Go 语言的内存、指针详解

这是一篇面向即将学习 go 语言并且对指针理念或者 go 的指针类型不是很了解的程序员的内容 什么是指针? 简单解释,指针就是指向另一段地址的值,课本上是这么解...

46414
来自专栏阮一峰的网络日志

asm.js 和 Emscripten 入门教程

Web 技术突飞猛进,但是有一个领域一直无法突破 ---- 游戏。 游戏的性能要求非常高,一些大型游戏连 PC 跑起来都很吃力,更不要提在浏览器的沙盒模型里跑了...

3065
来自专栏极客编程

测试利器Mocha

mocha 是一个功能丰富的javascript测试框架,可以运行在nodejs和浏览器环境,使异步测试变得简单有趣。mocha 串联运行测试,允许灵活和精确地...

1042
来自专栏Java学习网

java开发中代码级别的优化方法总结,有效提高程序性能

负载测试和应用程序监控对于确定应用程序的一些关键性能瓶颈非常有用。但同时,我们需要遵循良好的编码习惯,以避免在对应用程序进行监控的时候出现过多的性能问题。

1272
来自专栏nnngu

百度搜索 “Java面试题” 前200页(面试必看)

本文中的题目来源于网上的一篇文章《百度搜索 “Java面试题” 前200页》,但该文章里面只有题目,没有答案。因此,我整理了一些答案发布于本文。本文整理答案的原...

78311

扫码关注云+社区

领取腾讯云代金券