001:FPGA入门——呼吸灯

  在一家作嵌入式公司实习已经两个月了,须要学习整理的东西不少。决定坚持写一些总结,留下一些记忆更有意义。呼吸灯这个题目刚拿到没有思路,网上的参考示例也没有找到合适的,不过最后找到一个YHXT机构(不是广告,很简单的实现了这个功能,放到博客一块儿学习。控制LED的亮度变化,就是要控制电压,让电压高低变化,是一个电压从低到高再到低的一个线性变换过程。这里用PWM控制电压最合适。产生PWM须要分别产生载波信号和调制信号,最后对二者的大小进行比较产生pwm学习

  载波用cnt1计数器生成一个锯齿波就是载波。这里计数器cnt1从0开始计数到N,计数到最大值再次从0开始计数,不断的循环计数。cnt1的最大值是N-1。根据你的时钟(系统时钟,FPGA的工做时钟,大多状况是50mhz,我这里用的是40mhz,25ns)来计数,每来一次时钟上升沿计数器加一。那么从0到N-1,所需的时间就是N*T。这个就是一个锯齿波的周期。spa

  调制信号呼吸灯是一个亮度又低到高再到低的过程,这里再用一个计数器cnt2生成一个三角波,这个三角波的周期就是呼吸灯工做一次的周期。三角波计数器从0到最大值N ,至关于对调制信号N等份,每个等份是一个载波周期。这里有一个公式   N^2 * T = 呼吸灯周期/2 。知道呼吸灯周期和时钟的状况下容易获得计数器最大值N。(这里为了方便,我设置整个led周期5s,T = 25ns,则N = 10000。)这里至关于cnt1计数到最大值,cnt2加一。当cnt2从0计数到N-1的过程就是一个上升的斜线,由N-1递减到0就是降低的斜线。在cnt2计数到最大值时设置一个标志位信号flag,flag为1,表明开始递减。blog

  大小比较经过载波和调制信号的大小比较,就能够生成一个pwm波。载波大于调制信号时,pwm = 0,载波小于调制信号时,pwm =1。input

 

 

verilog逻辑代码:博客

module hxled(clk,led1,led2);it

input clk;//系统时钟40mhzio

output led1;
output led2;//这里两个led交替呼吸table

reg [13:0]cnt1;
reg [13:0]cnt2;
reg flag;//标志位
parameter N = 10000;// 计数值最大值,一次暗亮暗的时间是5s
//cnt1
always@(posedge clk) begin
if(cnt1 == N - 1)
cnt1 <= 1'b0;
else
cnt1 <= cnt1 + 1'b1;
endtest

//cnt2
always@(posedge clk)
begin
if(cnt1 == N - 1) //cnt1计满一次 cnt2才递增或递减
begin
if(!flag)//标志位为0时 cnt2加状态
begin
if(cnt2 == N - 1)
flag <= 1'b1;//cnt2计满时 标志位拉高
else
cnt2 <= cnt2 + 1'b1;
end
else
begin
if(cnt2 == 0)
flag <= 1'b0;
else
cnt2 <= cnt2 - 1'b1;
end
end
else
cnt2 <= cnt2;
endmodule

assign led1 = (cnt1 < cnt2)?1'b1:1'b0;//大小比较
assign led2 = ~led1;//两个灯交替呼吸

endmodule

testbench文件:

`timescale 1ns/1ps
`define clock_period 25
module hxled_tb;

reg clk;
wire led1;
wire led2;

hxled u1(
.clk(clk),
.led1(led1),
.led2(led2)
);

initial clk = 1;
always# (`clock_period/2) clk = ~clk;

endmodule

  此次波形比较简单就不分析仿真波形了,板级验证经过,要注意quartus软件的操做。不一样的工做时钟能够更改一下计数器值,也能够加入复位信号。若是实验现象不明显多是计数器值设置的问题。

  再次感谢YH学堂 此次学习 了解如何用计数器产生载波信号 调制信号 如何产生PWM 以及控制呼吸灯的原理。

相关文章
相关标签/搜索