目录
一、FPGA的晶振与定时器
二、定时器(led闪烁、蜂鸣器频率控制)
1、时钟上升沿、复位下降沿触发
2、复位,计数器清零
3、计数满1s时,计数器清零
4-1、led闪烁(每秒)
4-2、蜂鸣器响(每毫秒)
代码
三、蜂鸣器报警(多响)
1、初始化
2、计数
3、蜂鸣器控制
代码
FPGA的晶振是50MHz,50MHz = 50_000_000Hz = 1/50_000_000s = 20ns
即每次时钟(clk)上升沿(posedge)每50Mhz(20ns)到来一次。
always@(posedge clk)
基于这个原理,就可以愉快地做定时的操作了。
首先要知道:2^26 = 67_108_864 > 50_000_000,所以可以设置二进制长度2^26。(即宽26)
reg [25:0] cnt
这里涉及到的蜂鸣器,和单片机的又不太一样,我自己尝试了一下直接给电平,它是响不了的,想让它响好像只能给控制频率,让它响。
注:人耳能听到的频率是90hz到15khz,所以你的驱动源频率须在此范围之内才能听到。
//led灯定时(1s)
always@ (posedge clk, negedge rst_n)
//按下复位键
if (!rst_n)
cnt <= 1'b0;
//计数满1s
else if(cnt != 26'd49_999_999) //定时到1hz(即1s)
cnt <= cnt + 1'b1;
//led闪烁:1s计数满
else
begin
led <= ~led;
cnt <= 1'b0;
end
//蜂鸣器定频率
always@ (posedge clk)
begin
//计数满
if(!(cnt % 26'd49_999)) //定时到1khz(即1ms)
beep <= ~beep;
end
//定时(led灯闪烁、蜂鸣器频率控制)
//FPGA晶振是50MHz(即20ns)
module my_and(clk, rst_n, beep, led);
input clk, rst_n;
output reg beep;
output reg led;
reg [25:0] cnt;
//led灯定时(1s)
always@ (posedge clk, negedge rst_n)
begin
//按下复位键
if (!rst_n)
cnt <= 1'b0;
//计数满1s
else if(cnt != 26'd49_999_999) //定时到1hz(即1s)
cnt <= cnt + 1'b1;
//led闪烁:1s计数满
else
begin
led <= ~led;
cnt <= 1'b0;
end
end
//蜂鸣器按频率响
always@ (posedge clk)
begin
//计数满
if(!(cnt % 26'd49_999)) //定时到1khz(即1ms)
beep <= ~beep;
end
endmodule
这里实验效果是:响4声、停一会。
实验原理:蜂鸣器响是通过根据频率控制的,如果想让它断断续续地鸣叫,可以给它限值频带,频带范围内控制它响,不在频带范围内就不让它响。
这里由于需要响四声,停一下,我设置通频带范围:
1、27'd0~27'd6_250_000;
2、d12_500_000~27'd18_750_000;
3、27'd25_000_000~27'd31_250_000;
4、27'd37_500_000~27'd43_750_000;
周期:100MHz(2s)
//蜂鸣器报警(频带控制)
module my_and(clk, rst_n, beep);
input clk, rst_n;
output reg beep;
reg [28:0] cnt;
initial
begin
cnt <= 1'b0;
beep <= 1'b0;
end
周期2s(28'd99_999_999从0开始算的,即100MHz)
//计数
always@(posedge clk, negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 1'b0;
end
else if(cnt != 28'd99_999_999) //2s
cnt <= cnt + 1'b1;
else
cnt <= 1'b0; //清空
end
设置了四个频带,在频带范围就响,不在就不响。
//蜂鸣器控制
always@(posedge clk)
begin
//第一个频带(第一声)
if(cnt < 27'd6_250_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第二个频带(第二声)
else if(cnt > 27'd12_500_000 && cnt < 27'd18_750_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第三个频带(第三声)
else if(cnt > 27'd25_000_000 && cnt < 27'd31_250_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第四个频带(第四声)
else if(cnt > 27'd37_500_000 && cnt < 27'd43_750_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
end
//蜂鸣器报警(频带控制)
module my_and(clk, rst_n, beep);
input clk, rst_n;
output reg beep;
reg [28:0] cnt;
initial
begin
cnt <= 1'b0;
beep <= 1'b0;
end
//计数
always@(posedge clk, negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 1'b0;
end
else if(cnt != 28'd99_999_999) //2s
cnt <= cnt + 1'b1;
else
cnt <= 1'b0; //清空
end
//蜂鸣器控制
always@(posedge clk)
begin
//第一个频带(第一声)
if(cnt < 27'd6_250_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第二个频带(第二声)
else if(cnt > 27'd12_500_000 && cnt < 27'd18_750_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第三个频带(第三声)
else if(cnt > 27'd25_000_000 && cnt < 27'd31_250_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
//第四个频带(第四声)
else if(cnt > 27'd37_500_000 && cnt < 27'd43_750_000)
begin
if(cnt%27'd49_999==0)
beep <= ~beep;
end
end
endmodule