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等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!