这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
icore4tx_fpga_9 [2020/05/22 14:19] zgf 移除 |
icore4tx_fpga_9 [2022/04/01 11:37] (当前版本) sean |
||
---|---|---|---|
行 1: | 行 1: | ||
- | |||
| **银杏科技有限公司旗下技术文档发布平台** |||| | | **银杏科技有限公司旗下技术文档发布平台** |||| | ||
|技术支持电话|**0379-69926675-801**||| | |技术支持电话|**0379-69926675-801**||| | ||
|技术支持邮件|Gingko@vip.163.com||| | |技术支持邮件|Gingko@vip.163.com||| | ||
- | |技术论坛|http://www.eeschool.org||| | ||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
| V1.0 | 2020-05-20 | gingko | 初次建立 | | | V1.0 | 2020-05-20 | gingko | 初次建立 | | ||
- | ===== 实验八:计数器实验——呼吸灯 ===== | + | ===== 实验九:软件复位控制实验——全局复位信号 ===== |
==== 一、实验目的与意义 ==== | ==== 一、实验目的与意义 ==== | ||
- | - 掌握计数器原理及使用方法; | + | - 掌握Verilog HDL语言的使用方法。 |
- | - 掌握ISE开发软件的使用方法。 | + | - 掌握QuartusII的使用方法。 |
+ | - 掌握软件复位信号的工作原理及使用方法。 | ||
==== 二、实验设备及平台 ==== | ==== 二、实验设备及平台 ==== | ||
行 23: | 行 22: | ||
==== 三、实验原理 ==== | ==== 三、实验原理 ==== | ||
- | * 计数器是实现计数的一种最基本的加法运算。在FPGA中计数器的实质其实就是对驱动参考时钟进行计数,每当触发条件满足,计数器的寄存器参数实现自加,累加到某个状态进行清零操作。FPGA中常用计数器对系统时钟进行计数,实现时钟分频、定时器、延时、计数、控制等功能,是FPGA实现功能中常用的一种逻辑电路和时序控制方式。 | + | * 复位指的是在可编程器件、可编程控制器等电子设备中,为防止程序跑飞或者保证多个子程序同时运行,在程序中手动或者自动的方法使软硬件恢复到一个特定的工作节点的过程,而这个手动或自动控制的信号就是复位信号。手动复位可以通过按键复位实现,自动复位则是上电后产生一个脉冲信号,工程根据这脉冲信号做复位操作。 |
- | * 呼吸灯在生活中也较为常见,一般是通过控制LED的亮度渐变实现的。以本实验要实现的呼吸灯为例,要实现的效果为渐渐变亮,亮度最大后再渐渐变暗,最后熄灭,如此往复循环。LED的亮度变化是通过控制LED单位时间内亮的时间占比实现的;比如以10个时钟周期作为1个单位时间周期,当LED亮的时间持续2个时钟周期,熄灭的时间持续8个时钟周期,那么,当时钟周期较小时,每秒由成千上万个这样的单位时间构成;反馈到人的眼睛,由于视觉暂留,眼睛看不到很高频率的闪烁,而是看到LED的亮度很低。同理,当10个时钟周期里持续8个时钟周期的亮,则看起来亮度就高。 | + | * 在FPGA程序中,一个复杂的功能由多个子模块共同完成,为了保证各个子模块同时运行,在程序内部设定一个全局复位信号。其工作原理时序如图9.1所示: |
- | * 呼吸灯的呼吸效果是如何实现的呢?以本实验为例,呼吸周期为2秒,则从暗到亮的过程持续1秒,从亮到暗的过程持续1秒。在从暗到亮的过程中,假如这1秒分成1000个单位时间周期,则每个单位时间周期里LED亮的时间都要比前一个久一点。同理,从亮到暗的过程则是每个时间单位周期里LED亮的时间都要比前一个短一点。 | + | |
- | * 以本实验呼吸灯亮的这1秒过程为例来阐述。系统时钟为25MHz,机1秒钟内有25M个系统时钟周期。将1秒分成5000个单位时间周期,每个单位时间周期持续5000个系统时钟周期。 | + | |
- | * **25M/5000=5000** | + | |
- | * 那么,只需将这5000个单位时间周期内LED亮的时间从0~5000逐渐增加,这1秒LED看起来就是逐渐变亮的;同理也可以控制LED灯逐渐变暗。 | + | |
+ | {{ :icore4tx:icore4tx_fpga_9_1.png?direct |图9.1}} | ||
+ | * 如图所示,是低电平复位,既rst_n信号为低电平的时候,程序进行复位操作。其复位原理是:将复位信号作为程序控制的触发信号,在复位信号(rst_n)下降沿处对控制总线进行复位,将其赋值为复位值,有效复位信号(低电平)结束后,可根据需要对控制总线重新进行赋值。 | ||
+ | * 复位信号的作用是复位操作之后,程序中的变量或者信号处于一个稳定已知的状态,使程序按照设计功能运行。 | ||
==== 四、代码讲解 ==== | ==== 四、代码讲解 ==== | ||
- | * 原理部分讲解了呼吸灯的实现原理。下面通过代码讲解如何实现LED呼吸的效果。 | + | * 在iCore4TX核心板上并没有设计专用的按键复位电路。因此iCore4TX的复位操作均通软件复位实现。通过对原理图的理解,可以理解为复位信号就是一个在上电后不久就拉低 一段时间然后又拉高的信号;为了方便理解和观察,本例程通过复位信号控制LED灯的状态变化,直观的显示复位过程,并且将整个持续过程进行了拉长。复位信号的高低电平的跳变以及持续时间通过对系统时钟计数实现。 |
- | * 首先定义变量cnt1和cnt2;cnt1是对单位时间周期内系统时钟进行计数,cnt2是对单位时间周期(即cnt1)进行计数,那么cnt1*cnt2=25M,。然后定义变量flag,每过1秒翻转1次,则可以在flag的不同状态控制LED是渐亮还是渐灭。 | + | * ** 其代码如下:** |
- | * 具体的LED在1个单位时间周期内亮的时间持续多少个系统时钟周期,是通过cnt1和cnt2的值比较判断的。由于cnt2是逐1自加的,那么每次在cnt1从1累加到4999的过程中,cnt2是不变的,而且每次cnt1累加的过程中,cnt2总比前一个值大1;那么,在cnt1累加的过程中,小于cnt2的值的时候,控制led亮,在cnt2累加的过程中即可实现led逐渐变亮。逐渐变暗的过程同理,只需控制cnt1大于cnt2的时候led亮即可。 | + | <code verilog> |
- | ** * 代码如下:** | + | //生成复位信号的计数器,采用时序逻辑语言描述 |
+ | reg [31:0]rst_cnt = 32'd0; | ||
+ | |||
+ | always@(posedge clk_25m) | ||
+ | begin | ||
+ | if(rst_cnt==32'd250000000) | ||
+ | begin | ||
+ | rst_cnt<=32'd250000000; | ||
+ | end | ||
+ | else | ||
+ | begin | ||
+ | rst_cnt <= rst_cnt + 32'd1; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | </code> | ||
+ | * 然后根据计数器的值控制复位信号拉低复位并持续约4秒(便于观察)。 | ||
+ | <code verilog> | ||
+ | //生成复位信号,有效复位时间大约为4秒钟,实际应用中不需要持续这么久。 | ||
+ | reg rst_n = 1'd1; | ||
+ | always@(posedge clk_25m) | ||
+ | begin | ||
+ | if((rst_cnt>32'd125000000) && (rst_cnt<32'd225000010)) | ||
+ | begin | ||
+ | rst_n <= 1'd0; | ||
+ | end | ||
+ | else | ||
+ | begin | ||
+ | rst_n <= 1'd1; | ||
+ | end | ||
+ | end | ||
+ | </code> | ||
+ | |||
+ | * FPGA_LED根据复位信号,进行状态切换。上电之后,复位之前,LED置为低电平,状态为“亮”;复位时,置高电平,LED处于复位状态,为“灭”,复位结束后,LED再次置为低电平,状态为“亮”。代码如下: | ||
<code verilog> | <code verilog> | ||
- | //-------------------cnt1--------------------// | + | /*************************************************/ |
- | //对系统时钟进行计数 | + | //通过复位信号对led的输出状态进行复位 |
- | always@(posedge clk_25M or negedge rst_n) | + | //复位信号有效前将led置为低电平低电平(亮); |
- | if(!rst_n) | + | //复位后大约4秒钟led处于复位状态,置为高电平(灭); |
- | cnt1<=13'd0; | + | //复位操作结束后,再次将led置为低电平(亮)。 |
- | else if(cnt1==13'd4999) | + | reg fpga_led_r = 1'd1; |
- | cnt1<=13'd0; | + | |
- | else | + | always@(posedge clk_25m or negedge rst_n) |
- | cnt1<=cnt1+1'd1; | + | begin |
- | //------------------cnt2-------------------// | + | if(!rst_n) |
- | //对cnt1进行计数 | + | begin |
- | always@(posedge clk_25M or negedge rst_n) | + | fpga_led_r <= 1'd1; |
- | if(!rst_n) | + | end |
- | cnt2<=13'd0; | + | else |
- | else if((cnt1==13'd4999)&&(cnt2==13'd4999)) | + | begin |
- | cnt2<=13'd0; | + | fpga_led_r <= 1'd0; |
- | else if(cnt1==13'd4999) | + | end |
- | cnt2<=cnt2+1'd1; | + | end |
- | //-----------------flag--------------------// | + | assign fpga_led = fpga_led_r; |
- | //flag为1时led逐渐变亮,flag为0时逐渐变暗 | + | |
- | reg flag; | + | |
- | always@(posedge clk_25M or negedge rst_n) | + | |
- | if(!rst_n) | + | |
- | flag<=1'd0; | + | |
- | else if((cnt2==13'd0)&&(cnt1==13'd0)) | + | |
- | flag<=~flag; | + | |
- | //-----------------led--------------------// | + | |
- | //控制LED在哪个范围内亮和灭 | + | |
- | always@(posedge clk_25M or negedge rst_n) | + | |
- | if(!rst_n) | + | |
- | led_r<=1'd1; | + | |
- | else if((flag==1'd1)&&(cnt2<cnt1)) | + | |
- | led_r<=1'd0; | + | |
- | else if((flag==1'd0)&&(cnt2>cnt1)) | + | |
- | led_r<=1'd0; | + | |
- | else | + | |
- | led_r<=1'd1; | + | |
</code> | </code> | ||
==== 五、实验步骤及实验结果 ==== | ==== 五、实验步骤及实验结果 ==== | ||
- | {{ :icore4tx:icore4tx_fpga_8_1.png?direct&400 |图8.1}} | + | {{ :icore4tx:icore4tx_fpga_9_2.png?direct&400 |图9.2}} |
- | 1、将硬件正确连接,如图8.1所示。\\ | + | 1、将硬件正确连接,如图9.2所示。\\ |
2、将编写好的代码进行编译,并下载到开发板中;\\ | 2、将编写好的代码进行编译,并下载到开发板中;\\ | ||
- | 3、观察实验现象——FPGA_LED逐渐变亮然后逐渐变暗,循环进行。\\ | + | 3、观察其实验结果——程序下载后,首先开发板上FPGA_LED为亮状态,经过大约5秒钟,复位信号有效,对FPGA_LED进行复位置为灭状态,复位大约4秒钟,再次点亮FPGA_LED。\\ |
==== 六、拓展实验 ==== | ==== 六、拓展实验 ==== | ||
- | - 调整LED灯的呼吸周期。 | + | - 通过Signaltap工具采集复位信号和led控制信号,看是否与其工作原理一致。 |
- | - 通过计数器,控制led熄灭之后延迟一段时间再逐渐变亮。 | + | |