约束
1、建议给信号名添加有意义的前缀或后缀,命名符合常用命名规范(_clk 或clk_表
示时钟,n表示低电平有效,z表示三态信号,en表示使能控制,rst 表示复位)。
2、由parameter定义的常量要求全部字母大写,自己定义的参数、类型用大写标识。
3、在module内不应该存在没有驱动源的信号,更不能在模块端口存在没有驱动的输出信号,避免在compile时产生warning。
4、不允许出现定义的parameter/wire/reg没有使用。
5、变量在if-else或case语句中所有变量在所有分支中都赋值。如果用到case语句,写上default项。
6、不推荐嵌套使用5级以上if…else if…结构。
7、一致的信号命名风格
简洁,清晰,有效是基本的信号命名规则,详见命名规范。
全称 |
缩写 |
中文含义 |
acknowledge |
ack |
应答 |
adress |
addr(ad) |
地址 |
arbiter |
arb |
仲裁 |
check |
chk |
校验,如CRC校验 |
clock |
clk |
时钟 |
config |
cfg |
Configuration,装置 |
control |
ctrl |
控制 |
count |
cnt |
计数 |
data in |
din(di) |
数据输入 |
data out |
dout(do) |
数据输出 |
decode |
de |
译码 |
decrease |
dec |
减一 |
delay |
dly |
|
disable |
dis |
不使能 |
error |
err |
错误(指示) |
enable |
en |
使能 |
frame |
frm |
帧 |
generate |
gen |
生成,如CRC生成 |
grant |
gnt |
申请通过 |
increase |
inc |
加一 |
input |
in(i) |
|
length |
len |
(帧、包)长 |
nmport |
nm |
网管相关 |
output |
out(o) |
|
packet不推荐packet |
pkt |
与帧相同 |
priority |
pri |
优先级 |
pointer |
ptr |
指针 |
rd enable |
ren |
读使能 |
read |
rd |
读(操作) |
ready |
rdy |
应答信号或准备好 |
receive |
rx |
(帧数据)接收 |
request |
req |
(服务、仲裁)请求 |
reset |
rst |
|
segment |
seg |
|
source |
scr |
源(端口) |
ststistics |
stat |
统计 |
timer |
tmr |
定时器 |
switcher |
sf |
Switch fabric |
temporary |
tmp |
临时 |
transmit |
tx |
发送(帧数据)相关 |
Valid |
vld(v) |
有效、校验正确 |
wr enable |
wen |
写使能 |
write |
wr |
写操作 |
a. 端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写
b. 使用简称、缩略词(加上列表)
c. 基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,如tx_data_val;命名长度一般限制在20个字符以内。
d. 低电平有效信号,加后缀”_n”,如 rst_n
e. 无条件寄存的寄存信号在原信号上加ff1、ff2… 如原信号 data_in, 寄存一拍data_in_ff1,寄存两拍data_in_ff2
f. 不能用 ”reg”,作为最后的后缀名,因为综合工具会给寄存器自动加上_reg, 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。
8、括号的使用
如果一个表达式的分组情况不是很明显时,加上括号有助于理解。
例如下面的代码加上括号就清晰很多。
if (&a==1’b1&&!flag==1’b1 || b==1’b1) //
改为:
if ((&a==1’b1&&(!flag==1’b1)||( b==1’b1)) //
9、适当的使用空格
一般表达式在运算符的两侧要各留出一个空格,但定义比较长的表达式,去掉预先级高的运算符前的空格,使其与运算对象紧连在一起,可以更清晰的显示表达式结构。
还是上面的例子:
if ((&a==1’b1)&&(!flag==1’b1 ) ||( b==1’b1)) //
改为:
if ((&a == 1’b1)&&(!flag == 1’b1) ||( b == 1’b1)) //
”<=”, ”==”前后都要加空格。
赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配。如:
reg [4:0] signal_a;
错误: 1 signal_a <= 5;
2 if(signal_a == 5)
3 signal_a <= signal_b[3:0]+4;
正确: 1 signal_a <= 5’d5
2 if(signal_a == 5’d5)
3 signal_a <= {1’b0, signal_b[3:0]+5’d4
因为工具默认是32位宽,如果不注明位宽,工具检查会报warning,而且这样增加了设计的严谨性。
11、条件的完整性
If else搭配使用,对于缺省的条件要写”else;”;
If elsed 条件判别式要全面,比如if(a == 1’b0);
Case中的缺省条件要写”default”。
12、”IF ELSE”结构VS”CASE”结构
IF ELSE结构综合的结构可能是与或非门构成的,也可能是一组多路选择器,而case结构综合结果一般会是多路选择器,但对于可以优化的case综合工具会综合出更简单的结构。
所有对于可以写出平行结构的条件,优先写成case结构,例如地址译码等,条件之间有重复和嵌套的情况则是写成if else结构。
13、推荐不要在一个always块里给多个变量赋值。如果将一组条件相同的变量写在一个always块中更有利于可读性的提高和功能的实现时候,可有例外情况,但请尽量多加注释,以增加可读性,并注意在组合always块中不要出现LATCH(不如对状态机的组合always块及它对条件相似的多个变量赋值);
14、always的注释:要在每一个always块之前加一段注释,增加可读性和便于调试。
15、考虑到综合工具不是万能的 因此 我们在编写代码时 要采取恰当的风格 以提高电路
性能 对FPGA设计 Xilinx为例 而言 其所要求的代码风格:
1.) 资源共享的应用限制在同一个module里 这样 综合工具才能最大限度地发挥其资源共
享综合作用。
2.)尽可能将Critical path上所有相关逻辑放在同一个module里.。这样,综合工具能够发挥其最佳综合效果。
3.)Critical path所在的module与其它module分别综合,对critial path采用速度优先的综合策略 。对其它module采用面积优先的综合策略。
4.)尽可能Register所有的Output。做到这一点,对加约束比较方便;同时一条路径上的组合逻辑不可能分散在各个module里 这对综合非常有利 可以比较方便地达到面积 速度双赢的目的。
5.)一个module的size不能太大,具体大小,由各综合工具而定
6.) 一个module尽量只有一个时钟,或者整个设计只有一个时钟