一、实验内容
1.等占空比信号发生:计数器计时1ms,使LED灯每隔1ms状态翻转一次,实现LED灯闪烁,产生周期为2ms、占空比50%的方波信号;
2.非等占空比信号发生:计时器计时1.8ms,LED灯亮1ms,灭0.8ms,产生周期为1.8ms、非等占空比的方波信号;
3.序列型脉冲信号产生:生成1011010011的序列脉冲信号,每个脉冲信号时间为1us;
二、计数器最大值计算
当Rst_n复位信号被拉低时,计数值清零;复位信号被拉高时,计数器从0开始计数,在每个Clk时钟上升沿到来时自增1。
以50Mhz的系统时钟为例,时钟周期为20ns,即两个Clk时钟上升沿间隔为20ns,因此计数器每20ns计数一次。要实现1ms计时,则需要计数1ms/20ns=50000次,由于计数器从0开始计数,故1ms计时的计数器最大值为50000-1=49999。得出计数器最大值的计算公式:
计数器最大值
=
计数时间
/
系统时钟周期
−
1
计数器最大值=计数时间/系统时钟周期-1
计数器最大值=计数时间/系统时钟周期−1
三、等占空比信号发生
1.单一信号发生
使LED灯每隔1ms状态翻转一次,产生周期为2ms的方波信号,代码如下:
module cntled(
input Clk, //系统时钟
input Rst_n, //系统复位
output reg led //LED端口
);
reg [15:0] cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 0;
else if(cnt == 49999)//(49999+1)*20=1000000ns=1ms
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
led <= 0;
else if(cnt == 49999)
led <= ~led;
endmodule
仿真文件:
`timescale 1ns/1ns
module cntled_tb();
reg Clk,Rst_n;
wire led;
cntled cntled(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led)
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Rst_n = 0;
#200;
Rst_n = 1;
#10000000;
$stop;
end
endmodule
仿真结果:
2.多个信号发生
三个LED灯,使其分别按1ms、500us、250us的速率翻转。
根据上述内容,计算出三个计数器的最大值分别为49999、24999、12499,为了实现多次调用模块,在代码中添加cnt_max,通过更改cnt_max改变计数器的计数时间,cnt_max可以设置为模块端口,也可以设置为全局常量,在此提供三种方法。
//cnt_max设置为模块端口
input [15:0] cnt_max;
//cnt_max设置为全局常量
parameter cnt_max = 49999;
在对计数器模块例化时,对cnt_max赋值,以改变计数器的计数时间,模块cntled1将cnt_max设置为端口,模块cntled2将cnt_max设置为全局常量,例化代码如下:
//方法1: 直接添加为模块端口
cntled1 test0(
.Clk(Clk),
.Rst_n(Rst_n),
.cnt_max(49_999),
.led(led1)
);
//方法2: 添加常量,在例化时对常量赋值
cntled2
#(
.cnt_max(24_999)
)
test1(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led2)
);
//方法3: 添加常量,在例化后对常量赋值
cntled2 test2(
.Clk(Clk),
.Rst_n(Rst_n),
.led(led3)
);
defparam test2.cnt_max = 12_499;
仿真结果:
四、非等占空比信号发生
LED灯亮1ms,灭0.8ms,产生周期为1.8ms、非等占空比的方波信号,代码如下:
module cntled3(Clk,Rst_n,led);
input Clk,Rst_n;
output reg led;
reg [16:0] cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 0;
else if(cnt == 89_999) //1.8ms
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
led <= 0;
else if(cnt < 50_000) //1ms
led <= 0;
else //0.8ms
led <= 1;
endmodule
仿真结果:
五、序列型脉冲信号产生
生成1011010011的序列脉冲信号,每个脉冲信号时间为1us。
共10个脉冲信号,故设置计数时间为10us,用序列机判断cnt的计数值,每计50个数时更改信号的输出值,即在cnt为0、49、99、149、199、249、299、349、399、449时更改信号的输出值;cnt为其它数值时,输出信号保持不变。代码如下:文章来源:https://www.toymoban.com/news/detail-835854.html
module cntled4(Clk,Rst_n,led);
input Clk,Rst_n;
output reg led;
reg [16:0] cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 0;
else if(cnt == 499)//10us
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
led <= 0;
else
case(cnt)
0:led <= 1;
49:led <= 0;
99:led <= 1;
199:led <= 0;
249:led <= 1;
299:led <= 0;
399:led <= 1;
default:led <= led;
endcase
endmodule
仿真结果:文章来源地址https://www.toymoban.com/news/detail-835854.html
到了这里,关于FPGA学习笔记:Verilog利用计数器发生信号的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!