1.前言
之前在做一家IC公司面试题时,有一道题,是需要统计一个可变位宽数据中1的个数,看到题目后最开始想法是像写C语言一样写一个for循环累加,之后纠结了半天,感觉电路应该是并行的,如果使用for循环累加,是不是会不可实现,不可布局布线,于是纠结了半天。今天将写的for循环在vivado中综合实现,发现实际上是可以,在这里和大家分享一下。
2.verilog实现
题目:
输入:i_err_din[ PARA_NUM-1 : 0]
输出:o_dout_add = i_err_din[0]+i_err_din[1]+......+i_err_din[PARA_NUM-1]
verilog代码
module error_com
#(
parameter PARA_NUM = 8 ,
parameter PARA_NUM_WIDTH = $clog2(PARA_NUM)
)
(
input [ PARA_NUM - 1 : 0 ] i_err_din ,
output reg [ PARA_NUM_WIDTH : 0 ] o_dout_add
);
integer i;
always @( *) begin
o_dout_add = 0 ;
for(i=0;i<PARA_NUM ; i=i+1)begin
o_dout_add = o_dout_add + i_err_din[i];
end
end
endmodule
仿真代码
`timescale 1ns / 1ps
module error_com_tb ;
localparam PARA_NUM = 8 ;
localparam PARA_NUM_WIDTH = $clog2(PARA_NUM) ;
localparam PARA_MAX = 2**PARA_NUM ;
integer i;
reg [ PARA_NUM - 1 : 0 ] i_err_din ;
wire [ PARA_NUM_WIDTH : 0 ] o_dout_add ;
error_com
#(
.PARA_NUM (PARA_NUM )
)
error_com_u0(
.i_err_din (i_err_din ) ,
.o_dout_add (o_dout_add )
);
initial begin
for(i=0;i<PARA_MAX;i=i+1)begin
i_err_din = i ;
#100;
end
#100;
$stop;
end
endmodule
仿真结果
3.分析
首先仿真结果和预期结果是一致的,说明这段代码是可以综合的。同时我注意到vivado综合时会由如下警报:
在XILINX官网上搜索这个警报原因:This warning indicates that the design is not large enough to benefit from parallel synthesis. As a result, the parallel flow will not be run.
大致意思就是此段代码无法很好的综合成并行电路,无法使用综合工具的并行流。会被综合成串行流。vivado综合出来的原理图如下:
同时我也尝试在DC里面综合,结果和vivado综合结果一致,原理图如下:
说明现在的综合工具已经足够强大,组合逻辑中的写的for循环综合成串行电路,正如上图所示,写的for循环,综合成了一系列串行的加法器 。
注意
注意这里一定要使用阻塞赋值,否则综合是有问题的。当使用非阻塞赋值综合出来的电路如下: