FPGA设计思想之“逻辑复制”

举报
李锐博恩 发表于 2021/07/15 03:43:18 2021/07/15
【摘要】 1、逻辑复制是一种通过增加面积来改善时序条件的优化手段,它最主要的应用时调整信号的扇出。如果某个信号需要驱动的后级逻辑信号较多,也就是其扇出非常大,那么为了增加这个信号的驱动能力,就必须插入很多级的Buffer,这样就在一定程度上增加了这个信号的路径延迟。 这种情况下就可以复制生成这个信号的逻辑,用多路同频同相的信号驱动后续电路,使平均到每路的扇出变低,这样不需要插入Buf...

1、逻辑复制是一种通过增加面积来改善时序条件的优化手段,它最主要的应用时调整信号的扇出。如果某个信号需要驱动的后级逻辑信号较多,也就是其扇出非常大,那么为了增加这个信号的驱动能力,就必须插入很多级的Buffer,这样就在一定程度上增加了这个信号的路径延迟。

这种情况下就可以复制生成这个信号的逻辑,用多路同频同相的信号驱动后续电路,使平均到每路的扇出变低,这样不需要插入Buffer就能满足驱动能力增加的要求,从而节省路径延迟。

 

举一个例子:这个例子来自于特权同学《深入浅出玩转FPGA》

例一:未进行逻辑复制时:


  
  1. module logic_copy(
  2. input a,b,c,d,
  3. input sel,
  4. output dout
  5. );
  6. assign dout = sel?(a + b):(c + d);
  7. endmodule

对应的RTL原理图为:

可见,占用了两个加法器和一个二选一的多路选择器;

 


例二:逻辑复制后:


  
  1. module logic_copy(
  2. input a,b,c,d,
  3. input sel,
  4. output dout
  5. );
  6. wire ab,cd;
  7. assign ab = sel ? a : c;
  8. assign cd = sel ? b : d;
  9. assign dout = ab + cd;
  10. endmodule

 

 

 

可见,占用了两个选择器和一个加法器;

2、FPGA中需要做很多重复工作

下面内容来自于:FPGA中逻辑复制

在某些FPGA设计中,需要很多重复设计的时候,这时候逻辑复制也就有用了。

例如:在某个特殊应用场合需要设计方向可以任意改变的240位宽的三态IO管脚。我们先看看常用的一个位宽的三态管脚怎么设计。


  
  1. module inout_interface(
  2. dat_in,
  3. io_out,
  4. io_dir,
  5. dat_out
  6. );
  7. input dat_in;
  8. input io_dir;
  9. output dat_out;
  10. inout io_out;
  11. assign io_out = io_dir ? dat_in : 1'bz;
  12. assign dat_out = io_out;
  13. endmodule

 

如上述程序所示为单个双向IO口的典型设计代码,中间由IO输入方向控制数据和高阻之间的切换,难题出现了,怎么设计240位宽的双向IO口呢?难道如下列程序所示:


  
  1. module inout_interface(
  2. dat_in,
  3. io_out,
  4. io_dir,
  5. dat_out
  6. );
  7. input [239 : 0] dat_in;
  8. input [239 : 0] io_dir;
  9. output [239 : 0] dat_out;
  10. inout [239 : 0] io_out;
  11. assign io_out = io_dir ? dat_in : 240'bz;
  12. assign dat_out = io_out;
  13. endmodule

 

显然这样是不行的,因为当io_dir为240位的时候只有当全为0的时候此式才为假,其余时候都为真,显然达不到想要的每个IO都是双向口的设计。

修改代码如下:

 


  
  1. module inout_interface(
  2. dat_in,
  3. io_out,
  4. io_dir,
  5. dat_out
  6. );
  7. input [239 : 0] dat_in;
  8. input [239 : 0] io_dir;
  9. output [239 : 0] dat_out;
  10. inout [239 : 0] io_out;
  11. assign io_out[0] = io_dir[0] ? dat_in[0] : 1'bz;
  12. assign dat_out[0] = io_out[0];
  13. assign io_out[1] = io_dir[1] ? dat_in[1] : 1'bz;
  14. assign dat_out[1] = io_out[1];
  15. assign io_out[2] = io_dir[2] ? dat_in[2] : 1'bz;
  16. assign dat_out[2] = io_out[2];
  17. .
  18. . // 此处略去1万行
  19. .
  20. assign io_out[239] = io_dir[239] ? dat_in[239] : 1'bz;
  21. assign dat_out[239] = io_out[239];
  22. endmodule

 

  显然这种办法能实现240位宽的独立方向控制IO,但是估计写代码要累死人,有没得更好的办法呢?

  当然有,在verilog2001中有个逻辑复制语法——generate,可以对verilog模块进行无限复制。有了这个模块我们即可轻松通过逻辑复制来达到我们的要求了。

 


  
  1. // 单个双向IO实现模块
  2. module pin_inout(
  3. indat,
  4. indir,
  5. outdat,
  6. outdatin
  7. );
  8. input indat;
  9. input indir;
  10. inout outdat;
  11. output outdatin;
  12. assign outdat = indir ? indat : 1'bz;
  13. assign outdatin = outdat;
  14. endmodule
  15. module inout_interface(
  16. dat_in,
  17. io_out,
  18. io_dir,
  19. dat_out
  20. );
  21. input [239 : 0] dat_in;
  22. input [239 : 0] io_dir;
  23. output [239 : 0] dat_out;
  24. inout [239 : 0] io_out;
  25. // 逻辑复制240次
  26. genvar i;
  27. generate
  28. for(i = 0; i < 240; i = i + 1)
  29. begin : pin_loop
  30. pin_inout pin_inout_inst(
  31. .indat ( dat_in[i] ),
  32. .indir ( io_dir[i] ),
  33. .outdat ( io_out[i] ),
  34. .outdatin ( dat_out[i] )
  35. );
  36. end
  37. endgenerate
  38. endmodule

由上面代码可看出,巧妙利用verilog语法能减少自身工作量。

在FPGA设计中有些情况的逻辑复制不需要我们做,但是有些情况的逻辑复制不得不手工完成,因此,熟练掌握verilog语法是设计出好的模型、减少工作量的前提。


最后有关inout端口的处理,给出一篇链接,仅供参考!

verilog 中inout管脚的处理

 

 

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/88702418

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。