约束
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)) //
”<=”, ”==”前后都要加空格。
10、赋值要指明比特宽度
赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配。如:
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尽量只有一个时钟,或者整个设计只有一个时钟