数字IC中Verilog编码注意事项
一、禁用多驱动
一个wire型变量(具体到每个bit),只能在一个assign语句赋值
一个reg型变量(具体到每个bit),只能在一个always语句赋值
综合工具不能识别互斥条件
在一个always块内,一次触发,对同一个信号最多只赋一次值
比如:不要用多个if
always@(posedge clk or negedge rstn)begin
if(!rstn)begin
b<='d0;
end
else begin
if(c)begin
b<=a0;
end
if(d)begin
b<=a1;
end
end
end
这种写法是可以综合的,但是不便于理解和后期维护。如果c和d两个条件同时满足,综合时会采用d这个结果(最后面的一个条件)。
应该按照如下写法:
always@(posedge clk or negedge rstn)begin
if(!rstn)begin
b<='d0;
end
else begin
if(c)begin
b<=a0;
end
else if(d)begin
b<=a1;
end
end
end
二、异步复位电平要统一
异步复位的触发条件必须与always block块的判断条件一致
cell library里面无法找到negedge触发的复位信号同时用高电平检测的物理器件。所以这样虽然语法上是可以的,但是是无法综合的。所以不能这样写。
异步复位的触发条件必须出现在always block的第一个if()条件判断中
DFF里有一个clk端口,一个rstn端口。底层器件会自己去匹配信号(哪个是clk,哪个是rstn)。如果复位信号不是第一个if判断条件,底层器件就无法正确匹配clk和rstn。综合的时候就会报错。所以这样写虽然语法是允许的,但是是不可综合的。
在数字电路中,经常采用低电平有效的异步复位。优势:复位的时候不需要clk稳定,可以在DFF power up时,供电从0到VCC的上升过程中,一直保持复位状态。
三、只需要时序逻辑复位,组合逻辑不需要复位
当所有的寄存器都复位后,组合逻辑的输出一定是确定值。所以没有必要对组合逻辑再进行复位。
四、DATA类的DFF可以不复位
控制类的DFF需要复位。数据类的DFF可以不复位。
即使DFF在Power on的时候是随机值,也不会导致function出现bug,那么就可以不复位。
减少不必要的复位,可以减少rstn线的loading,减少rstn走线消耗的面积
五、避免不必要的MUX
有些信号在无效的时候(尤其是data),没有必要用一个mux把它force到固定值。就让他自动生成锁存器保持原来的值就行。
多写一个else会增加设计的面积,没有必要。
六、禁止使用initial block
需要初始值时,一律使用reset。
initial是不可综合的!
FPGA中,SRAM可以用initial block赋初值。因为FPGA中bit下载的过程中会解决这个不可综合问题,但是在ASIC中,是不允许这样的。
七、reg变量不能在定义的时候赋初始值
FPGA中,DFF可以在定义的时候赋初值。但是在ASIC中,reg型变量,不能在定义的时候赋初始值。这样是不可综合的。
八、两个异步复位输入
既有异步复位(reset到0),又有异步置位(reset到1)
always @(posedge clk or negedge rstn or negedge setn) begin
if (!rstn) begin
a<=1'b0;
end
else if (!setn) begin
a<=1'b1;
end
else begin
a<=b;
end
end
always @(posedge clk or negedge rstn or negedge setn) begin
if (!setn) begin
c<=1'b1;
end
else if (!rstn) begin
c<=1'b0;
end
else begin
c<=b;
end
end
如果底层cell library有set/reset两个输入端的异步复位寄存器(不管优先级是否匹配),就可以综合。否则不能综合。
九、异步复位值为变量
可以综合,但是一般没有必要。(需要底层cell library有set/reset两个输入端的异步复位寄存器。
非必要不使用!
十、准确定义数据位宽
数学运算,需要准确定义数据位宽,这样综合面积才小。
设计者应该是知道运算结果的可能取值范围的。综合工具推断的话,只能按照计算不溢出的最小bit数来优化,可能不是最优结果。
十一、generate的for写上block标识
generate的for写上block标识,这样才能标记该for loop的hierarchy信息
不加,语法没有问题。DC综合会有warning提示。加了,在gate level网表找对应的DFF更方便。
例如:
generate
genvar y,x;
for (y = 0; y <= 15; y = y + 1)
begin:gen_diff_out
for(x=0;x<=15;x=x+1)begin:gen_diff_in
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
diff[y][x]<='d0;
end
else if (cal_en) begin
diff[y][x]<={1'b0,din_array[y][x]}-{1'b0,ref_array[y][x]};
end
end
end
end
endgenerate
十二、组合逻辑always不要自触发
在一个组合逻辑的always块里,可以对多个变量赋值;但是不要让这个always块的输出同时也是这个always块的敏感变量