|
炼狱传奇-层次化设计之战
本节我们通过驱动流水灯的不同方式来体现 Fpga 中的一个重要思想—层次
化设计。
首先介绍一下我所使用开发板的硬件资源,50MHZ 时钟输入、4 个低电平点
亮的流水灯。 然后通过两种不同驱动方式的对比使读者更加深层次的了解层次化
设计
下图提供了一段流水灯代码,请问能够实现流水现象吗?
与上述代码所对应的波形图如下
FPGA 的时钟是 50M,周期 20ns,上述代码每隔 20ns,流水灯的状态发生改
变,即每个灯亮的状态是 20ns,时间非常短,人的肉眼观察不到灯亮的状态。
由于周期特别短导致无法观察到灯亮,因此只要通过计数器将周期延长一定
的时间,就可以看到“流水”现象。以下代码通过设计一个计数器 count 将周期
延长到两秒,代码如下
代码经过编译以后得到 RTL 图如下
下面提供相对应的仿真代码, 通过参数传递的方式将 led_fsm1 中的 NUM 赋
值为 50,代替 NUM=28'd100000000,提高仿真效率
具体解释如下,在 led_fsm1 中 NUM 达到 28'd100000000-1(NUM-1)时,才会
产生时钟的跳转,但是在波形仿真中仿真时间长,效率低,通过参数传递将 50
传给 NUM,这样在仿真中,NUM-1=49 时,时钟发生翻转,提高仿真效率,参数传
递时,将参数定义为 parameter 类型,并且在文件中凡是能够用到参数的地方,
尽量要用参数表示,比如用到 28'd100000000-1,可以用 NUM-1 代替,否则会导
致参数传递失败。具体参考给出的波形文件
仿真结果如下
从 上 面 的 波 形 看 出 当 count==50-1 , led_out 发 生 改 变 , 而 不 是
count==28'd100000000-1 ,由此可知参数传递成功
那么,请问一下,在一个模块里面既要写 count 分频模块,又要写 led_out
的输出,有没有简单的思路呢?
下面我们介绍一种更简单的思考方式,层次化设计
所谓层次设计就是将一个整体项目划分成多个模块, 就像电脑由键盘、 鼠标、
显示器构成一样。分好模块以后,我们就必须要一个顶层文件,将多个模块连接
起来。
下面依然用一个 50MHz 的晶振点亮一个流水灯进行层次化设计为例进行讲
解。
首先考虑流水灯由哪几个模块构成。如果用 50MHz 驱动流水灯的话,50MHz
频率过快,会导致点亮流水灯的效果看不到,所以我们需要一个分频模块,将时
钟频率降低。为了实现流水灯则需要一个逻辑控制模块,最后将这两个模块在顶
层中进行连接
系统框图如下:
接下来,设计具体电路描述代码,实现各模块功能,首先,新建工程如下
然后建立起顶层文件
建立时钟分频模块 led_freq 在这里不建议调用锁相环(PLL) ,锁相环分频
是有限制的,我试了一下如果用锁相环来点灯的话,时钟太快还是看不到流水的
现象,所以需要独立编写一个 led_freq 模块
在写完分频模块以后,就要写如何让流水灯实现,以下是流水灯控制模块的代码,在控
制模块 (led_ctrl) 中 注意信号 clk, 此时钟不是 50M 时钟, 是经过分频模块分频以后的时钟,
这点是如何实现的呢?可以看后面提供的 RTL 图,看模块的连接关系,和顶层模块讲解
下面先提供一个 led_ctrl 控制的仿真代码,用来测试单独的流水灯控制模
块,具体代码如下
led_ctrl 模块仿真波形如下
有以上波形可以看出,复位结束以后,流水灯的驱动端口 led_out 和状态机
的状态寄存器 state 在时钟上升沿的驱动下有效配合,实现了数据的滚动赋值,
可以正确实现流水灯设计。
下面编辑顶层模块, 顶层模块的主要功能是将分频模块和流水灯控制模块连
接起来,我们要求在顶层中只做端口连线,不做任何逻辑。顶层具体代码如下:
进行全编译,结果如下:
编译通过,我们可以首先查看一下 RTL 级视图,点击 Tools->Netlist Viewers->RTL Viewer
查看结果如下
由上图可以说明,最终综合出来的电路和我们所设想的是完全一致的。
通过对比以上两种方法, 可以很明显的发现层次化设计的 RTL 视图能够清晰的反映出模
块之间的连接关系,在设计中可以独立的对每个模块进行设计,降低设计的复杂度,尤其是
大规模的设计,也便于代码的调试,将一个复杂的系统转换为对每个独立模块的调试,所以
层次化设计是一项非常重要的设计技巧
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?我要注册
x
|