by 杜伟韬 中国传媒大学
用途
本设计“FPGA数字计时器”,是一个Verilog和FPGA的初学者的示范设计,用于向学生展示
- 如何将设计目标分割为小型电路模块
- 如何使用Verilog实现小型电路模块
- 如何从简单的电路开始逐步实现目标设计。
使用DE0开发板的FPGA 定时器
|
目标
- 使用Terasic公司出品的DE0开发板,设计并实现一个计时器。
- 精度为1/100秒,范围0~99.99秒
- 4个LED数码管显示
- 使用2个按键控制计时的启动、暂停、清零。
设计过程
对于刚刚熟悉Verilog的同学而言,你应当掌握以下电路模块的设计方法
- 设计诸如3-8译码器的组合逻辑电路
- 设计计数器之类的时序逻辑电路
- 设计简单的状态机
- 设计移位寄存器
- 查看Verilog 电路编译之后的RTL View
- 编译电路之后进行 波形仿真
本实验的完成过程分成四步走,这样每一步的跨度不大,比较容易上手 # 阶段1
本阶段的目标是验证实验电路板的信号连接和下载,这是设计开始的必要环节。 阶段目标
- 让FPGA上的数码管每隔1秒钟全部点亮或熄灭,
- 应该看到4个“8”在闪烁
- 验证了FPGA的管脚和数码管的连接是好的
- 本阶段使用原理图的完成设计
- 请自行阅读 DE0 用户手册(见参考资料),了解电路板上FPGA的信号连接
插入说明—调试技能-波形仿真
- 2个秒脉冲之间的时钟周期很长,用波形仿真观察不方便,怎么办?
- 修改你的电路参数(计数器的溢出值),让2次溢出之间的时钟周期个数变短
- 这样利于波形仿真观察结果
- 记得下载电路之前要改成实际值
电路结构
如下图所示:
阶段1、电路结构
|
设计思路
- 使用一个计数器,每秒钟溢出一次然后从0重新计数
- 每次计数器溢出,把一个D触发器的结果取反
- 把D触发器的输出连接到4个LED的所有段上
- 计数器的溢出信号是单时钟周期有效
- 每个时钟周期使用计数器溢出信号和D触发器的Q值生成它的D值
插入说明—调试技能-观察RTL图
- 确认D触发器:编译工具会优化你的组合逻辑(就是卡诺图的圈圈)但是不会擅自增删D触发器
- 明确你代码中那些reg变量会成为D触发器
- 在Quartus-Tools-NetList Viewer-RTL Viewer里面找你的D触发器在不在
关键信号时序
如下图所示:
阶段1、电路时序
|
阶段2
阶段目标
本阶段设计目标的功能和阶段1一样,但是实现方法有所不同,包括
- 全部的电路功能使用Verilog代码实现
- 使用“Assignments — Import Assignments”的管脚指派方法
- 设计文本化的好处是利于修改和重用,缺点是不直观
- 文本的好处是,基于代码的设计更容易使用计算机工具维护(比如版本控制器),以及更容易重用代码
- 本阶段的设计资料请自行参考设计代码
阶段3
阶段目标
本阶段的设计目标为设计一个可以从0.01秒计数到99.99秒的计时器电路。
电路结构
电路的结构如下图所示
阶段3、电路结构
|
设计思路
- 复位按键使用拨码开关,不需要去抖
- 脉冲生成模块:带工作使能的计数器
- 对输入时钟信号计数,生成四种尺度的时间脉冲信号
- 所有的时间脉冲信号都是单周期高电平有效的
- 该模块内部为4个计数器,并且有一条串联的计数器溢出进位链
- 小时间尺度计数器的进位信号被后级大时间尺度计数器作为计数使能信号
- 脉冲计数模块:带工作使能的计数器
- 对输入的高电平脉冲0~9回绕计数
- 模块内部是一个计数器
- 输入的高电平信号作为计数器的计数使能
- 计数器的计数值0~9作为模块的输出
- BCD译码模块:3-8译码器的变体
- 该模块是一个纯粹的组合逻辑
- 该模块把0~9的数字译码成为LED的段显示码
- 该模块使用CASE语句实现
插入说明—设计方法-时钟设计
- 尽量不要采用多个时钟,最好只有一个
- 单一时钟有利于EDA工具进行“代码-电路”的转换
- 多个时钟容易出现数据传输时同步出错的问题
- 用使能信号控制电路的动作
- 例如:带有使能的D触发器,使能为1时 D向Q传递数据,否则Q保持不变
插入说明—调试技能-观察中间节点信号波形
- 有时编译工具会把电路的中间节点信息优化掉,让你无法从波形仿真上观察信号
- 解决办法:把要观察的信号引出到最顶层的模块,当作输出信号
- 不需要为这种观察信号分配管脚
- 注意:本阶段的参考代码要把“复位”的拨码开关置为“复位无效”状态电路才会运行
关键信号时序
关键的信号时序如下图所示:
阶段3、电路时序
|
阶段4
阶段目标
本阶段在阶段3的基础上,添加以下功能:
- 上电的自动复位,上电后自动生成复位信号,把所有模块复位
- 添加一个暂停/继续的功能按钮,需要去抖
- 添加一个计数清零后暂停的功能按钮,需要去抖
电路结构
本阶段的电路结构如下所示
阶段4、电路结构
|
设计思路
本阶段需要对上阶段的电路添加和修改以下功能
给脉冲生成模块添加运行/暂停信号
- 该信号状态为运行时,正常生成计时脉冲
- 该信号状态为暂停时,内部电路进入保持状态,不生成计时脉冲
- 本模块不生成计时脉冲,则后级各个脉冲计数器会进入计数保持状态
- 该信号实际上是各个计数器的工作使能信号
给脉冲生成模块和各个LED的计数模块添加清零信号
插入说明—调试技能-观察新的信号
插入说明—设计方法-状态机设计
- 仔细考虑有哪些状态
- 仔细考虑状态之间的跳转逻辑
- 复杂的状态机要用表格或状态转移图来设计状态跳转关系
- 合理分解状态,尽量让输出逻辑仅和状态值有关,而和输入无关,这样不容易出错
- 代码风格尽量用三段式
插入说明—调试技能-状态机分析
- 写的规范的状态机代码可以被编译工具识别出来
- 在RTL Viewer 里面可以看到黄颜色的方框 , 如下图所示
阶段4状态机顶层视图
|
- 还可以观察工具解析出的状态转移关系 ,如下图,这样可以检验你的状态转换逻辑是否写对。
阶段4状态机的状态转移视图
|
添加上电复位模块
- 必要性:所有的模块都要有复位信号,电路上电后经过复位进入确定状态
- 设计依据:Altera FPGA的D触发器上电后的初始值是0
- 实现方法 * 使用一个计数器,计数到最大值后保持不动 * 达到最大计数值之前输出复位有效,之后输出复位无效
- 注意事项:由于FPGA的上电加载需要时间,所以计数器的溢出时间要在0.1秒的数量级
参考代码
参考设计代码 阶段1-4, 点击下载
实验作业
作业要求
根据本教程提供的参考代码请设计满足以下功能的计时电路
- 最小显示精度为1秒,60进制,从0计时到59分59秒
- 使用拨码开关和按键,能够设置时间的功能,建议形式如下 * 采用4个拨码开关,任何一个开关拨到上方时,对应的数码管开始闪烁 * 闪烁的数码管应当仍能正常更新计时的显示值 * 采用“增加”和“减少”2个按键 * 每按下“增加”按键一次,闪烁的数码的显示值加1,并且以0-60回绕 * 每按下“减少”按键一次,闪烁的数码的显示值减1,并且以0-60回绕
- 不准使用多个时钟,所有D触发器用同一个时钟工作
插入说明—调试技能-提高观察效率
- 如何知道你的电路能够正确的计时到59分59秒?
- 难道要等1个小时才能知道么?
- 参考阶段1中的方法
参考资料
以下资料来自网络,版权归原作者所有,感谢原作者的工作
网络资料_Quartus 使用入门, * 请注意:不要盲目对着这个文档操作 * 你的FPGA型号、EPCS配置芯片型号和下载器接口类型和这个文档是不同的! * 以上参数请根据DE0的手册自行修改 * 点击下载
- 网络资料_Quartus 指派管脚, * 建议使用“Assignments — Import Assignments”的方法 * 使用带有列操作模式编辑器编辑管脚约束文件 * 点击下载
使用JTAG模式下下载EPCS器件的方法 , 点击下载
DE0用户手册 英文版, 请习惯看英文手册,对考四六级有帮助 ,点击下载 点击下载