差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
9._呼吸灯 [2017/03/22 23:47]
zhijun
9._呼吸灯 [2019/12/23 10:46] (当前版本)
anran
行 18: 行 18:
  
 结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s 结合呼吸灯的原理,整个呼吸的周期为最亮→最暗→最亮的时间,即t的值的变化:0→T→0逐渐变化,这个时间应该为2s
 +{{ :​呼吸灯程序设计.jpg |呼吸灯程序设计}}
  
-\\   +呼吸灯设计要求呼吸周期为2s,也就是说LED灯从最亮的状态开始,第一秒时间内逐渐变暗,第二秒的时间内再逐渐变亮,依次进行。 
-1,模块化设计:在之前实验我们做了[[3. 3-8译码|3-8译码器]][[5. 时钟分频|时钟分频]]如果把结合起来,我们就能搭建一自动操作的流水LED显示框图如下: + 
-\\ +本设计需要两个计数cnt1cnt2,cnt1随系统时钟同步计数(系统时钟上升沿时cnt1自加1)范围为0~T,cnt2随cnt1的周期同步计数(cnt1等于T时,cnt2自加1)范围也是0~T,这样每次cnt1在0~T的计数时,cnt2为一固定值,相邻cnt1计数周期对应的cnt2的值逐渐增大,我们将cnt1计数0~T的时间作为脉冲周期,cnt2的值作为脉冲宽度,则占空比 = cnt2/​T,​占空比从0%到100%的时间 = cnt2*cnt1 = T^2 = 1s = 12M系统时钟,T = 3464,我们定义CNT_NUM = 3464为两个计数器计数最大值。 
-{{ ::flashled.png |}} + 
-\\   +{{ ::呼吸灯pwm原理.jpg |PWM呼吸灯原理}}
-2,循环赋值:这是一种很简洁的实现流水灯效果逻辑,就是定义一个8位的变量,在每个时钟上升沿将最低位赋值给最高位,其他位右移一位,这就实现了循环赋值。这8位输出到LED就能实现流水灯。 +
-\\   +
  
 ====Verilog代码==== ====Verilog代码====
 ------ ------
-模块化设计是用硬件描述语言进行数字电路设计的精髓,代码可重复利用。而且模块化的设计使得程序的结构也很清晰。这里我们首先看看流水灯的模块化设计。利用了之前的3-8译码器和分频器,你需要把这两个程序也拷贝到一个工程。 
 <code verilog> <code verilog>
  
行 35: 行 33:
 // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​
 // ******************************************************************** // ********************************************************************
-// File name    : flashled.v +// File name    : breath_led.v 
-// Module name  : flashled+// Module name  : breath_led
 // Author ​      : STEP // Author ​      : STEP
-// Description ​ : segment initial+// Description ​ : 
 // Web          : www.stepfpga.com // Web          : www.stepfpga.com
 //  // 
行 47: 行 45:
 // V1.0     ​|2017/​03/​02 ​  ​|Initial ver // V1.0     ​|2017/​03/​02 ​  ​|Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module Function:流水灯的模块化设+// Module Function:呼吸 
 +module breath_led(clk,​rst,​led);​ 
 +  
 + input clk;             //​系统时钟输入 
 + input rst;             //​复位输出 
 + output led;            //​led输出 
 +  
 + reg [24:0] cnt1;       //​计数器1 
 + reg [24:0] cnt2;       //​计数器2 
 + reg flag;              //​呼吸灯变亮和变暗标志位 
 +  
 + parameter ​  ​CNT_NUM = 3464; //数器的最大值 period = (3464^2)*2 = 24000000 = 2s 
 + //​产生计数器cnt1 
 + always@(posedge clk or negedge rst) begin  
 + if(!rst) begin 
 + cnt1<​=13'​d0;​ 
 + end  
 +        else if(cnt1>​=CNT_NUM-1)  
 + cnt1<​=1'​b0;​ 
 +      else  
 +                cnt1<​=cnt1+1'​b1;​  
 + end 
 +  
 + //​产生计数器cnt2 
 + always@(posedge clk or negedge rst) begin  
 + if(!rst) begin 
 + cnt2<​=13'​d0;​ 
 + flag<​=1'​b0;​ 
 + end  
 +        else if(cnt1==CNT_NUM-1) begin //​当计数器1计满时计数器2开始计数加一或减一 
 + if(!flag) begin            //​当标志位为0时计数器2递增计数,表示呼吸灯效果由暗变亮 
 + if(cnt2>​=CNT_NUM-1) ​   //​计数器2计满时,表示亮度已最大,标志位变高,之后计数器2开始递减 
 + flag<​=1'​b1;​ 
 + else 
 + cnt2<​=cnt2+1'​b1;​ 
 + end 
 + else begin 
 + if(cnt2<​=0) ​     //​当标志位为高时计数器2递减计数 
 + flag<​=1'​b0;​  ​  //​计数器2级到0,表示亮度已最小,标志位变低,之后计数器2开始递增 
 + else  
 + cnt2<​=cnt2-1'​b1;​ 
 + end  
 +  
 + end 
 + else  
 + cnt2<​=cnt2; ​               //​计数器1在计数过程中计数器2保持不变 
 + end 
 +  
 + //​比较计数器1和计数器2的值产生自动调整占空比输出的信号,输出到led产生呼吸灯效果 
 + assign led = (cnt1<​cnt2)?​1'​b0:​1'​b1;​ 
 +  
 +endmodule
  
-module flashled (clk,​rst,​led);​ 
  
- input clk,​rst;​  +</​code>​
- output [7:0] led; +
  
- 
-        reg   [2:0] cnt ;                               //​定义了一个3位的计数器,输出可以作为3-8译码器的输入 
-        ​ 
-        wire clk1h; ​                                    //​定义一个中间变量,表示分频得到的时钟,用作计数器的触发 ​       ​ 
- 
-        //​例化module decode38,相当于调用 
-        decode38 u1 (                                    
- .sw(cnt), ​                      //​例化的输入端口连接到cnt,输出端口连接到led  ​ 
- .led(led) 
- ); 
-  
-        //​例化分频器模块,产生一个1Hz时钟信号  
-        divide #​(.WIDTH(32),​.N(12000000)) u2 (         //​传递参数 
- .clk(clk),​ 
- .rst_n(rst), ​                  //​例化的端口信号都连接到定义好的信号 
- .clkout(clk1h) 
- );                              
-  
-        //​1Hz时钟上升沿触发计数器,循环计数  
-        always @(posedge clk1h or negedge rst) 
-      if (!rst) 
- cnt <= 0; 
-      else 
- cnt <= cnt +1; 
-  
-        endmodule 
-        ​ 
- </​code>​ 
-\\ 
-\\ 
- 
-模块化设计结构清晰,verilog语言是很灵活的。对于流水灯还有一种很简洁的实现方法。 
- 
-<code verilog> 
- 
-// ******************************************************************** 
-// >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ 
-// ******************************************************************** 
-// File name    : flashled.v 
-// Module name  : flashled 
-// Author ​      : STEP 
-// Description ​ : segment initial 
-// Web          : www.stepfpga.com 
-//  
-// -------------------------------------------------------------------- 
-// Code Revision History :  
-// -------------------------------------------------------------------- 
-// Version: |Mod. Date:   ​|Changes Made: 
-// V1.0     ​|2017/​03/​02 ​  ​|Initial ver 
-// -------------------------------------------------------------------- 
-// Module Function:​流水灯的模块化设计 
- 
-module flashled (clk,​rst,​led);​ 
- 
- input clk,​rst;​  
- output [7:0] led;  
-        ​ 
-        wire clk1h; ​                                    //​定义一个中间变量,表示分频得到的时钟,用作计数器的触发 ​       ​ 
- 
-        //​例化分频器模块,产生一个1Hz时钟信号  
-        divide #​(.WIDTH(32),​.N(12000000)) u2 (         //​传递参数 
- .clk(clk),​ 
- .rst_n(rst), ​                  //​例化的端口信号都连接到定义好的信号 
- .clkout(clk1h) 
- );                              
-  
-        //​1Hz时钟上升沿触发循环赋值  
-        always@(posedge clk1h or negedge rst) 
- begin 
- if(!rst) 
- led <= 8'​b11111110; ​           // <​=为非阻塞赋值 
- else ​ 
- led <= {led[0],​led[7:​1]}; ​     //​当时钟上升沿来一次,执行一次赋值,赋值内容是led[0]与led[7:​1]重新拼接成8位赋给led,相当于循环右移 
- end  
-        ​ 
- </​code>  ​ 
-\\  ​ 
 ====引脚分配==== ====引脚分配====
 ------ ------
-按照面表格定义输入输出信号 +引脚分配如 
-\\ + 
-^信号 ​           ^引脚            ​^信号 ​             ^引脚 ​   ^    +名称 ​| clk| rst| led| 
-|clk   |C1              |led[3] ​   |M11     ^ +FPGA管脚 ​C1    ​| ​L14     | N13       |
-|rst   |L14              ​|led[4]    ​|P11     ^ +
-|led[0] ​  ​|N13 ​             |led[5] ​   |N10    ​^ +
-|led[1] ​  ​|M12 ​            ​|led[6] ​   |N9     ​+
-|led[2] ​  |P12             ​|led[7] ​   |p9     ^  +
-\\ +
-\\+
  
-配置好以后编译下载程序。可以调整例化分频器时传递的参数来调整流水灯的速度。 
-\\ 
  
 ====小结==== ====小结====
 ------ ------
-掌握了verilog里面例化module的用法,采模块化设计程序。模块化设计是非常重要FPGA设计思想。在下一节我们会学习按键另外用法[[7按键消抖|按键消抖]]。 +脉宽调制是一种值得广大工程师在许多应用设计中使用的有效技术,你也可以根据本节介绍的流水灯程序,实现RGB三色灯呼吸。在下一节我们会学习状态机使[[10交通灯|交通灯的设计]]。
- +
- +