🎉欢迎来到FPGA专栏~产生非等占空比信号
- ☆* o(≧▽≦)o *☆嗨~我是小夏与酒🍹
- ✨博客主页:小夏与酒的博客
- 🎈该系列文章专栏:FPGA学习之旅
- 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
- 📜 欢迎大家关注! ❤️
一、效果演示
🥝等占空比信号
🥝非等占空比信号
二、等占空比信号的产生
我们通过LED的亮灭来展现等占空比信号:LED循环亮灭,亮1秒,灭1秒。
50MHz
的晶振,要实现1秒
的定时,需要计数49_999_999
次,RTL视图展示如下:
Verilog HDL代码:
/
//模块作用:led亮一秒灭一秒
//作者:CSDN-小夏与酒
module led_plus1(
input Clk,
input Rst_n,
output reg led
);
reg [25:0]cnt;
parameter cnt_max = 26'd49_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 26'd0;
else if(cnt == cnt_max)
cnt <= 26'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 1'b1;
else if(cnt == cnt_max)
led <= ~led;
else
led <= led;
end
endmodule
测试激励文件代码:
`timescale 1ns/1ns
`define clock_period 20
module led_plus1_tb;
reg Clk;
reg Rst_n;
wire led;
led_plus Uled_plus1_0(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led)
);
initial Clk = 1;
always #(`clock_period/2) Clk = ~Clk;
initial begin
Rst_n = 0;
#100 Rst_n = 1;
#(`clock_period*1000000);
$stop;
end
endmodule
三、非等占空比信号的产生
我们通过LED的亮灭来展现等占空比信号:LED循环亮灭,亮0.2秒,灭1.8秒。
实现的基本思路:当计时器从0开始计时到0.2秒的过程中,LED点亮;当计时器从0.2秒之后计时到2秒的过程中,LED熄灭;当计时器达到2秒时,计数清空。
50MHz
的晶振,要实现0.2秒
的定时,需要计数9_999_999
次;要实现2秒
的定时,需要计数99_999_999
次,RTL视图展示如下:
Verilog HDL代码:
/
//模块作用:led亮0.2秒,灭1.8秒
//作者:CSDN-小夏与酒
module led_plus2(
input Clk,
input Rst_n,
output reg led
);
reg [26:0]cnt;
parameter cnt_max = 27'd99_999_999;
parameter cnt_ON = 27'd0;
parameter cnt_OFF = 27'd9_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 27'd0;
else if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 1'b1;
else if(cnt == cnt_ON)
led <= 1'b0;
else if(cnt == cnt_OFF)
led <= ~led;
else
led <= led;
end
endmodule
测试激励文件代码:
`timescale 1ns/1ns
`define clock_period 20
module led_plus2_tb;
reg Clk;
reg Rst_n;
wire led;
led_plus Uled_plus2_0(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led)
);
initial Clk = 1;
always #(`clock_period/2) Clk = ~Clk;
initial begin
Rst_n = 0;
#100 Rst_n = 1;
#(`clock_period*1000000000);
$stop;
end
endmodule
产生非等占空比信号的思路:规定一个时间段,然后把这个时间段分成不同时间长度的小时间段,在各个小时间段里进行不同的操作。如上述代码,规定一个LED闪烁周期为2秒
,前0.2秒
点亮,后1.8秒
熄灭。而在等占空比信号的产生中,规定一个LED闪烁周期为2秒
,前1秒
点亮,后1秒
熄灭。
为了更直观地看到不同占空比信号的效果,将上述代码整理并加入到顶层文件中:
/
//模块作用:信号占空比顶层文件
//作者:CSDN-小夏与酒
module led_plus(
input Clk,
input Rst_n,
output led1,
output led2
);
led_plus1 Uled_plus1(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led1)
);
led_plus2 Uled_plus2(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led2)
);
endmodule
RTL视图:
其中,为了更好地理解本次项目的内容,led_plus1模块中也使用2秒
为一个周期,前一秒
LED亮,后一秒
LED灭,写法思路和前述代码相同:
/
//模块作用:led亮一秒灭一秒
//作者:CSDN-小夏与酒
module led_plus1(
input Clk,
input Rst_n,
output reg led
);
reg [26:0]cnt;
parameter cnt_max = 27'd99_999_999;
parameter cnt_ON = 27'd0;
parameter cnt_OFF = 27'd49_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 27'd0;
else if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 1'b1;
else if(cnt == cnt_ON)
led <= 1'b0;
else if(cnt == cnt_OFF)
led <= ~led;
else
led <= led;
end
endmodule
使用上述代码编写led_plus1模块得到的RTL视图如下:
led_plus2模块的代码没有变化:
/
//模块作用:led亮0.2秒,灭1.8秒
//作者:CSDN-小夏与酒
module led_plus2(
input Clk,
input Rst_n,
output reg led
);
reg [26:0]cnt;
parameter cnt_max = 27'd99_999_999;
parameter cnt_ON = 27'd0;
parameter cnt_OFF = 27'd9_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 27'd0;
else if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 1'b1;
else if(cnt == cnt_ON)
led <= 1'b0;
else if(cnt == cnt_OFF)
led <= ~led;
else
led <= led;
end
endmodule
实现效果:
四、小项目
把握对定时器的理解和掌握非等占空比信号的产生方法。
在这部分加入两个小项目:使用产生非等占空比信号的思路实现两种类型的流水灯。
🔸项目一
具体要求:流水灯的循环周期为2.5秒
,四个LED灯在最初时刻全部点亮,以从左到右
或者从右到左
的顺序,四个LED灯以0.5秒
为间隔依次熄灭。
实现效果:
项目代码:
📜写法一:
/
//led_prj_01
//CSDN-小夏与酒
/
module led_prj_01(
input Clk,
input Rst_n,
output reg [3:0]led
);
reg [26:0]cnt;
parameter cnt_max = 27'd124_999_999;
parameter cnt_period = 27'd24_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 27'd0;
else if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 4'b0000;
else if(cnt == 1*cnt_period)
led <= 4'b1000;
else if(cnt == 2*cnt_period)
led <= 4'b1100;
else if(cnt == 3*cnt_period)
led <= 4'b1110;
else if(cnt == 4*cnt_period)
led <= 4'b1111;
else if(cnt == 5*cnt_period)
led <= 4'b0000;
else
led <= led;
end
endmodule
对应的RTL视图:
📜写法二:
/
//led_prj_01
//CSDN-小夏与酒
/
module led_prj_01(
input Clk,
input Rst_n,
output reg [3:0]led
);
reg [26:0]cnt;
parameter cnt_max = 27'd124_999_999;
parameter cnt_period = 27'd24_999_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 27'd0;
else if(cnt == cnt_max)
cnt <= 27'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 4'b0000;
else begin
case(cnt)
1*cnt_period:led <= 4'b1000;
2*cnt_period:led <= 4'b1100;
3*cnt_period:led <= 4'b1110;
4*cnt_period:led <= 4'b1111;
5*cnt_period:led <= 4'b0000;
default:led <= led;
endcase
end
end
endmodule
对应的RTL视图:
注意:
通过上述项目可以看出,if-else语句和case语句虽然可以实现相同的功能,但是它们的RTL视图却是不一样的,即if-else
语句和case
语句在底层逻辑的实现上是存在差异的,并且case
语句的优化效果更好。
🔸项目二
具体要求:流水灯的循环周期为3秒
,四个LED灯在最初时刻全部熄灭,以从左到右
或者从右到左
的顺序,四个LED灯分别以0.25秒
、0.5秒
、0.75秒
、1秒
为间隔依次点亮,全部点亮后持续0.25秒
。
实现效果:
项目代码:
/
//led_prj_02
//CSDN-小夏与酒
/
module led_prj_02(
input Clk,
input Rst_n,
output reg [3:0]led
);
reg [27:0]cnt;
parameter cnt_max = 28'd149_999_999;
parameter cnt_period = 28'd12_499_999;
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
cnt <= 28'd0;
else if(cnt == cnt_max)
cnt <= 28'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n)
led <= 4'b1111;
else begin
case(cnt)
1*cnt_period:led <= 4'b0111;
3*cnt_period:led <= 4'b0011;
6*cnt_period:led <= 4'b0001;
10*cnt_period:led <= 4'b0000;
11*cnt_period:led <= 4'b1111;
default:led <= led;
endcase
end
end
endmodule
对应的RTL视图:
文章来源:https://www.toymoban.com/news/detail-451126.html
🧸结尾文章来源地址https://www.toymoban.com/news/detail-451126.html
- ❤️ 感谢您的支持和鼓励! 😊🙏
- 📜您可能感兴趣的内容:
- 【FPGA-Spirit_V2】基于FPGA的循迹小车-小精灵V2开发板
- 【Go黑帽子】使用Golang编写一个TCP扫描器(高级篇)
- 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
- 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制
到了这里,关于【FPGA零基础学习之旅#5】产生非等占空比信号的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!