FPGA设计思想之“逻辑复制”
1、逻辑复制是一种通过增加面积来改善时序条件的优化手段,它最主要的应用时调整信号的扇出。如果某个信号需要驱动的后级逻辑信号较多,也就是其扇出非常大,那么为了增加这个信号的驱动能力,就必须插入很多级的Buffer,这样就在一定程度上增加了这个信号的路径延迟。
这种情况下就可以复制生成这个信号的逻辑,用多路同频同相的信号驱动后续电路,使平均到每路的扇出变低,这样不需要插入Buffer就能满足驱动能力增加的要求,从而节省路径延迟。
举一个例子:这个例子来自于特权同学《深入浅出玩转FPGA》
例一:未进行逻辑复制时:
-
module logic_copy(
-
input a,b,c,d,
-
input sel,
-
output dout
-
);
-
-
assign dout = sel?(a + b):(c + d);
-
-
-
endmodule
对应的RTL原理图为:
可见,占用了两个加法器和一个二选一的多路选择器;
例二:逻辑复制后:
-
module logic_copy(
-
input a,b,c,d,
-
input sel,
-
output dout
-
);
-
wire ab,cd;
-
assign ab = sel ? a : c;
-
assign cd = sel ? b : d;
-
assign dout = ab + cd;
-
-
-
endmodule
可见,占用了两个选择器和一个加法器;
2、FPGA中需要做很多重复工作
下面内容来自于:FPGA中逻辑复制
在某些FPGA设计中,需要很多重复设计的时候,这时候逻辑复制也就有用了。
例如:在某个特殊应用场合需要设计方向可以任意改变的240位宽的三态IO管脚。我们先看看常用的一个位宽的三态管脚怎么设计。
-
module inout_interface(
-
dat_in,
-
io_out,
-
io_dir,
-
dat_out
-
);
-
input dat_in;
-
input io_dir;
-
output dat_out;
-
inout io_out;
-
-
assign io_out = io_dir ? dat_in : 1'bz;
-
assign dat_out = io_out;
-
-
endmodule
如上述程序所示为单个双向IO口的典型设计代码,中间由IO输入方向控制数据和高阻之间的切换,难题出现了,怎么设计240位宽的双向IO口呢?难道如下列程序所示:
-
module inout_interface(
-
dat_in,
-
io_out,
-
io_dir,
-
dat_out
-
);
-
input [239 : 0] dat_in;
-
input [239 : 0] io_dir;
-
output [239 : 0] dat_out;
-
inout [239 : 0] io_out;
-
-
assign io_out = io_dir ? dat_in : 240'bz;
-
assign dat_out = io_out;
-
-
endmodule
显然这样是不行的,因为当io_dir为240位的时候只有当全为0的时候此式才为假,其余时候都为真,显然达不到想要的每个IO都是双向口的设计。
修改代码如下:
-
module inout_interface(
-
-
dat_in,
-
-
io_out,
-
-
io_dir,
-
-
dat_out
-
-
);
-
-
input [239 : 0] dat_in;
-
-
input [239 : 0] io_dir;
-
-
output [239 : 0] dat_out;
-
-
inout [239 : 0] io_out;
-
-
-
-
assign io_out[0] = io_dir[0] ? dat_in[0] : 1'bz;
-
-
assign dat_out[0] = io_out[0];
-
-
-
-
assign io_out[1] = io_dir[1] ? dat_in[1] : 1'bz;
-
-
assign dat_out[1] = io_out[1];
-
-
-
-
assign io_out[2] = io_dir[2] ? dat_in[2] : 1'bz;
-
-
assign dat_out[2] = io_out[2];
-
-
-
-
.
-
-
. // 此处略去1万行
-
-
.
-
-
-
-
assign io_out[239] = io_dir[239] ? dat_in[239] : 1'bz;
-
-
assign dat_out[239] = io_out[239];
-
-
-
-
endmodule
显然这种办法能实现240位宽的独立方向控制IO,但是估计写代码要累死人,有没得更好的办法呢?
当然有,在verilog2001中有个逻辑复制语法——generate,可以对verilog模块进行无限复制。有了这个模块我们即可轻松通过逻辑复制来达到我们的要求了。
-
// 单个双向IO实现模块
-
-
module pin_inout(
-
-
indat,
-
-
indir,
-
-
outdat,
-
-
outdatin
-
-
);
-
-
-
-
input indat;
-
-
input indir;
-
-
inout outdat;
-
-
output outdatin;
-
-
-
-
assign outdat = indir ? indat : 1'bz;
-
-
assign outdatin = outdat;
-
-
-
-
endmodule
-
-
-
-
module inout_interface(
-
-
dat_in,
-
-
io_out,
-
-
io_dir,
-
-
dat_out
-
-
);
-
-
input [239 : 0] dat_in;
-
-
input [239 : 0] io_dir;
-
-
output [239 : 0] dat_out;
-
-
inout [239 : 0] io_out;
-
-
-
-
// 逻辑复制240次
-
-
genvar i;
-
-
generate
-
-
for(i = 0; i < 240; i = i + 1)
-
-
begin : pin_loop
-
-
pin_inout pin_inout_inst(
-
-
.indat ( dat_in[i] ),
-
-
.indir ( io_dir[i] ),
-
-
.outdat ( io_out[i] ),
-
-
.outdatin ( dat_out[i] )
-
-
);
-
-
end
-
-
endgenerate
-
-
-
-
endmodule
由上面代码可看出,巧妙利用verilog语法能减少自身工作量。
在FPGA设计中有些情况的逻辑复制不需要我们做,但是有些情况的逻辑复制不得不手工完成,因此,熟练掌握verilog语法是设计出好的模型、减少工作量的前提。
最后有关inout端口的处理,给出一篇链接,仅供参考!
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/88702418
- 点赞
- 收藏
- 关注作者
评论(0)