什么是模块化设计

FPGA/IC设计中根据模块层次的不同有两种基本的设计方法:

  • 自下而上方法对设计进行逐次划分的过程是从基本单元出发的,设计树最末枝上的单元是已经设计好的基本单元,或者其他项目开发好的单元或者IP。该方法先对底层的功能块进行分析,然后使用这些模块来搭建规模更大的功能块,如此继续直至顶层模块。
  • 自上而下的设计是从系统级开始,把系统分为基本单元,然后再把每个单元划分为下一层次的基本单元,继续划分知道满足设计要求为止。该方法先定义顶层功能块,进而分析需要哪些构成顶层模块的必要子模块;然后进一步对各个子模块进行分解。

设计中这两种方法往往是混用的。设计师首先根据功能定义好顶层模块,然后依据一定的标准来划分各个子模块。同时对子模块进行优化设计,并使用这些子模块来搭建上层模块。两者的工作按相反的方向独立进行,直至在某一中间点会合。

在设计系统时,首先根据系统功能需求进行分析,然后将复杂的系统分解为多个子模块,这些子模块还可以再继续分解为更下一级的子模块,直到满足设计要求。模块化设计可以提高代码的可读性,令设计思路更清晰,便于大型设计的分工合作和独立测试,且有助于设计文件的维护和复用。

一个模块化设计实例

假如现在需要你设计一个数字电路,它的功能是:开发板数码的管默认显示数字0,每按下一次按键key,则数码管显示的数字+1(显示10进制数字)。

首先需要的肯定是一个数码管显示模块,它可以根据输入的数据,来显示对应的数字。然后需要一个能检测到按键被按下的模块,它每检测到按键按下一次,都要输出一个使能信号。最后是数据累加1模块,每有一次按键模块使能信号(表示按了一次按键)传过来,它都要使数据累加1。

因为开发板上的按键是机械按键,按下和松开的瞬间都会存在一定的机械抖动,为了正确的检测到按键被按下,还需要设计一个按键消抖模块,而用下降沿检测即可检测按键是否被按下。由于数码管需要显示的数字为10进制,所以数据累加模块产生的数据还需要进行BCD转化,这意味着要再设计一个2进制转BCD模块。

这样一个系统的逐层分解就完成了。看到这你可能会很不解,就这么一个简单的模块还需要搞这么麻烦,直接写到一个模块不就完事了吗?虽然理论上任何设计都可以在同一个模块中完成,但是如果将不同功能、不同层次、不同类型的电路混淆在同一个模块中,却不是一种好的系统设计方法,对于比较复杂的设计,将会导致整个设计杂乱无章,不利于设计的阅读与维护,也会给综合和实现过程带来许多麻烦。

同时,像按键消抖模块,下降沿检测模块和BCD模块可能都是初学者在学习过程中已经设计过了的模块,那么是将这些模块直接拿过来例化方便还是重新写一遍RTL方便?

模块划分的方法

模块划分的方法和基本原则是:

1、子模块功能相对独立,模块内部联系尽量紧密,而模块间的连接尽量简单。子模块的合理划分非常重要,应该综合考虑子模块的功能、结构、时序、复杂度等多方面的因素。

2、层次不要太深,一般为3~5层即可。在综合时综合工具为了获得更好的综合效果,会默认将RTL代码的层次打平(Flatten)。为了在综合后仿真和实现后仿真中较方便地找出一些中间信号,比如子模块之间的接口信号等,可 以在综合工具中设置保留结构层次,以便于查找和观察仿真信号。

3、顶层模块最好只包含对所有子模块的组织和调用,而不要完成复杂的逻辑功能。比如只写输入/输出管脚声明、模块的调用与实例化、全局时钟资源、全局置位/复位、三态Buffer和一些简单的组合逻辑。

4、子模块之间也可以有接口,但是最好不要建立子模块间跨层次的接口。例如上图中模块 A1到模块 B1之间不要直接连接,两者需要交换的信号可以通过模块 A、模块 B的接口传递。这样可以增加设计的可读性和可维护性。

下面是一些划分模块的优化设计方法:

1、对每个同步时序设计的子模块的输出使用寄存器。这种模块划分符合时序约束的习惯,便于利用约束属性进行时序约束,可以达到更好的时序优化效果,

2、将相关的逻辑或者可以复用的逻辑划分在同一模块内。这样可以在最大程度上复用资源,减少设计所消耗的面积。同时更利于综合工具优化某个具体功能的时序关键路径。

3、将不同优化目标的模块分开。目前很多综合与实现工具都支持物理区域位置约束,以模块为单元进行物理区域约束,就可以让综合工具仅需考虑单一的优化目标,从而使优化时序或面积就更有效。

4、可以将时序约束较松的逻辑归到同一模块。有些逻辑的时序非常宽松,不需要较高的时序约束。将这些模块归类,并指定宽松约束,则可以让综合器尽量节省面积资源和优化布局布线。

5、将存储逻辑(RAM、ROM、和 FIFO等)独立划分成模块。这样做的好处是便于利用综合约束属性显化指定这些存储单元的结构和所使用的资源类型,也便于综合器合理推断出这些逻辑所使用的固定硬件资源。

总结

模块化设计的优点:

  • 代码具有更好的可读性,更容易理解设计的功能和数据之间的流动,更容易debug
  • 代码具有更好的可复用性,能减少多次设计之间的重复工作,避免重复造轮子,提高工作效率
  • 不同模块的时钟域相对独立,使跨时钟域设计之间的边界更清晰

模块化设计是设计复杂数字系统的重要方法,对复杂设计的分工、测试以及代码的阅读、维护和复用都有好处。模块划分非常重要,其关系到能否最大程度上发挥项目成员协同设计的能力,更重要的是它直接决定着设计的综合、 实现的耗时与效率。

复用都有好处。模块划分非常重要,其关系到能否最大程度上发挥项目成员协同设计的能力,更重要的是它直接决定着设计的综合、 实现的耗时与效率。


  • 您有任何问题,都可以在评论区和我交流

  • 本文由 孤独的单刀 原创,首发于CSDN平台,博客主页:wuzhikai.blog.csdn.net

  • 您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞、评论和收藏