FPGA系统性学习笔记连载_Day12 【呼吸灯】

2021-04-07 11:49:51 浏览数 (1)

FPGA系统性学习笔记连载_Day12 【呼吸灯】之【 Cyclone IV、Spartan-6、ZYNQ三个平台的实现及验证】

本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。

连载《叁芯智能fpga设计与研发-第12天》 【呼吸灯实验】之【intel Cyclone IV、Xilinx Spartan-6、Xilinx ZYNQ7020三个平台的实现及验证】篇

原创作者:紫枫术河 转载请联系群主授权,否则追究责任

本篇文章记录呼吸灯的原理,及在intel Cyclone IV、Xilinx Spartan-6、Xilinx ZYNQ7020三个平台的实现及验证

一、呼吸灯

顾名思义,就是模仿人的吸气和呼气,将这个过程用led的亮度逐渐变化来形象的展示。

对应要控制led的亮度变化其实就是控制led在一个周期内,高低电平的时间,控制这个时间我们称为占空比。

二、占空比

占空比:就是高电平站整个周期的时间比例,我画了个图来形象的展示

从上面的图,可以看出来,不同的占空比,高电平所占比例是不一样的

三、呼吸灯

1、参数:我们定义一个完整的呼吸过程包含:呼气(2秒)和吸气(2秒),周期为4秒。

2、呼气:我们单独考虑呼气的过程,为了让led灯要有亮灭的变化,所以必须要将2秒的时间进行拆分,为什么?

3、为什么要将2秒进行拆分?

因为如果不拆分,我们只有一个固定不变的占空比,无论占空比是多少,他始终是固定的,即led的亮度也是固定的。

4、如何拆分?

理论上:我们可以无限的细分,拆分的份数越多,led的变化就越流畅;

实际上:由于人的眼睛有视觉暂留效应,对应光的变化,人眼的分辨率是30-40ms,所以我们无限细分是无意义的。

参数取值:为了led的亮度变化比较流畅,我们取20ms的间隔将2s进行拆分,也就是每隔20ms我们给led灯一个新的亮度,

这样我们人眼就能分辨出这个亮度的变化,则 cnt * T = 2000ms,T=20ms,cnt=100,即拆分100份

5、20ms周期连续变化示意图

由步骤4得知,我们将2秒拆分为100份的20ms,也就是20ms周期的波形在时序图上看是会重复100次;

为了体现led灯亮度,每一份20ms波形的占空比都不能相同,且必须是连续增加/减小的。如下图示意

6、由步骤5得知,波形重复100次,也就是20ms的时间内,我们一共有100个状态,每一个状态就是一个占空比t * 100 = 20ms,则 t = 200us,由公式计算得知,200us的占空比为200/20*1000 0 = 1%

7、从上面的描述中,我们可以总结出,要做出呼吸灯,我们需要定义一个20ms的定时器,一个长度为100的占空比计数器

四、verilog代码实现

breath_led.v

代码语言:javascript复制
module breath_led(
    input       clk,
    input       rst_n,
     
    output  reg led
);
 
    parameter       T_20ms_cnt  = 1_000_000;//20ms计数器值
    parameter       T_200us_cnt = 10_000;   //200us计数器值
    parameter       Total_pluse = 100;  //拆分100份
 
    reg [25:0]  cnt_20ms;           //20ms周期计数器
    reg [25:0]  cnt_200us;          //占空比分辨率计数器器
     
    reg [6:0]       pluse;          //占空比,高电平时间
    reg [6:0]       pluse_cnt;          //占空比计数,用来点灯
     
    reg         flag_20ms;      //20ms周期脉冲
    reg         flag_200us;     //200us占空比分辨率脉冲
 
    //产生20ms脉冲
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)begin
            cnt_20ms <= 0;
            flag_20ms <= 1'b0;
            end
        else if(cnt_20ms == T_20ms_cnt -1)
            begin
                cnt_20ms <= 0;
                flag_20ms <= 1'b1;
            end
        else
            begin
                cnt_20ms <= cnt_20ms   1'b1;
                flag_20ms <= 1'b0;
            end
    end
 
    //根据20ms脉冲,修改占空比
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            pluse <= 0;
        else if(pluse == Total_pluse - 1)
            pluse <= 0;
        else if(flag_20ms)
            pluse <= pluse   1'b1;
        else   
            pluse <= pluse;
    end
 
    //产生200us脉冲
    always@(posedge clk,negedge rst_n)begin
    if(!rst_n)begin
        cnt_200us <= 0;
        flag_200us <= 1'b0;
        end
    else if(cnt_200us == T_200us_cnt -1)
        begin
            cnt_200us <= 0;
            flag_200us <= 1'b1;
        end
    else
        begin
            cnt_200us <= cnt_200us   1'b1;
            flag_200us <= 1'b0;
        end
    end
     
    //根据200us脉冲和占空比,点灯
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                pluse_cnt<= 0;
                led <= 0;
            end
        else if(flag_200us)
            if(pluse_cnt <= pluse)
                begin
                    led <= 1'b1;
                    pluse_cnt <= pluse_cnt   1'b1;
                end
            else
                begin
                    led <= 1'b0;
                    if(pluse_cnt == Total_pluse - 1)
                        pluse_cnt <= 0;
                    else   
                        pluse_cnt <= pluse_cnt   1'b1;
                end
        else
            led <= led;
    end
     
endmodule

五、仿真脚本

breath_led_tb.v

代码语言:javascript复制
`timescale 1ns/1ps
 
module breath_led_tb;
    reg     clk;
    reg     rst_n;
     
    wire        led;
 
    breath_led  breath_led_isnt(
        .clk        (clk),
        .rst_n  (rst_n),
         
        .led        (led)
    ); 
     
    initial begin
        clk = 0;
        rst_n = 0;
        #20;
        rst_n =1;
        #500000;
        $stop;
    end
     
    always #10 clk = ~clk;
     
endmodule  

六、仿真结果

从仿真波形,看我们的设计实现了想要的结果

七、硬件验证(Intel Cycle IV FPGA平台验证)

我用的是叁芯智能的开发板(intel Cycle IV:EP4CE6E22C8)

0、时钟clk = PIN23 rest=PIN24

1、LED灯原理图

LED0:PIN_73

LED1:PIN_74

LED2:PIN_75

LED3:PIN_76

2、打开Pin Planner引脚分配工具,具体方法,参考我之前的博客

3、硬件测试效果,因为手机的分辨率较高,出来的效果没有肉眼观测好

00:11

Day12 呼吸灯B01

FPGA技术江湖的视频

八、硬件验证(Xilinx Spartan-6 FPGA 平台验证)

我用的是叁芯智能的开发板(Xilinx Spartan-6:XC6SLX9)

0、时钟、复位脚

RESET:PIN_23

CLK:PIN22

1、LED灯原理图

LED0:PIN_74

LED1:PIN_75

LED2:PIN_78

LED3:PIN_79

2、打开引脚分配工具,具体方法,参考我之前的博客

3、硬件测试效果

00:12

Day12 呼吸灯 B02

FPGA技术江湖的视频

九、Xilinx ZYNQ7020 FPGA 平台验证

我用的是广州创龙的开发板(Xilinx ZYNQ7020:xc7z020clg400-2)

0)、CLK =K17/Y7,Rst = G15(按键模拟复位键),不能用L16(这是复位FPGA下载的)

创龙是25M晶振,通过一个芯片时钟为200Mhz,同时给了FPGA的4个clk时钟块

1)、LED灯原理图

LED0:B5 这个引脚是连接到PS端,FPGA没法用,这个脚我们必须指定一个(扩展GPIO),否则vavido编译报错

LED1:F16

LED2:M14

LED3:M15

这个led灯是低电平点亮,所以我们要将代码改成低点亮led,高熄灭led灯

代码语言:javascript复制
always@(posedge clk,negedge rst_n)begin
    if(!rst_n)
        begin
            pluse_cnt<= 0;
            led <= 0;
        end
    else if(flag_200us)
        if(pluse_cnt <= pluse)
            begin
                led <= 1'b0;
                pluse_cnt <= pluse_cnt   1'b1;
            end
        else
            begin
                led <= 1'b1;
                if(pluse_cnt == Total_pluse - 1)
                    pluse_cnt <= 0;
                else   
                    pluse_cnt <= pluse_cnt   1'b1;
            end
    else
        led <= led;
end

2)、打开引脚分配工具,具体方法,参考我之前的博客

3)、修改时间参数,因为zynq晶振25Mhz,进时钟芯片变为200MHz,所以需要修改代码的参数

代码语言:javascript复制
parameter       T_20ms_cnt  = 4_000_000;//20ms计数器值
parameter       T_200us_cnt = 40_000;   //200us计数器值
parameter       Total_pluse = 100;  //拆分100份

4)、经过下板发现没有想象,这是因为xilinx7系列的时钟不能直接使用,困扰我2天

创龙的开发板PL时钟,是由一个25MHz和一个时钟芯片CDCM61002进行倍频率,最后输出2路差分时钟;

给FPGA的MRCC和SRCC时钟专用引脚,在xilinx7系列里,时钟都必须要用IBUF和BUFG这样才能使用;

<1>、第一种方法,我调用了一个PLL IP核,实现了将外部时钟引入内部逻辑

<2>、使用硬件原语描述

<3>、对于上面2个方法有个要求,差分信号只能描述P端,N端是软件自动匹配的,不能配置N端,否则布线失败

4、硬件效果

00:09

Day12 呼吸灯 Z7020

【QQ交流群】

群号:173560979,进群暗语:FPGA技术江湖粉丝。

多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。

【微信交流群】

现微信交流群已建立09群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!

0 人点赞