实验
- 实验目的
- 实现2s呼吸灯,前两秒亮到暗,下次暗到亮,周而复始
- 了解呼吸灯控制的原理
- 完成仿真和板级验证
- 实验原理
- 理论原理
- 利用计数器计数,实现两秒计时。计数部分包含cnt_us,cnt_ms,cnt_s
us计时标志信号(实验中计数满值为2us)
ms计时标志信号(实验中计数满值为2ms)
s计时标志信号(实验中计数满值为2s)
-
- 输出不同占空比的脉冲。cnt_ms >cnt_s时对应暗(flag=1),cnt_ms<=cnt_s时对应亮(flag=1);cnt_ms >cnt_s时对应亮(flag=0),cnt_ms<=cnt_s时对应暗(flag=0)。
- 硬件原理
- led灯供高电平点亮
Led原理图
- 系统架构设计
flag用于led显示状态切换,产生于end_cnt_s。
- 模块说明
- 模块端口信号列表
信号名 | |
clk | 时钟信号 |
rst | 复位 |
[3:0]led | Led灯 |
- 状态转移图
无
- 时序图
- 仿真波形图
flag跳转点。
us计满时,ms加一,ms计满时,s加一,s计满时flag翻转。
flag为0时,高电平占空比逐渐减小,实现重亮到暗;
flag为1时,高电平占空比逐渐增加,实现重暗到亮。
- 板级验证效果(拍照或录制视频)
verilog代码:注释部分可用,修改为流水呼吸灯
module breath_led(
input clk , rst ,
output reg [3:0]led
);
//计数器1
//parameter TIME_US =6'd50-1;//1s
//parameter TIME_MS =10'd1000-1;
//parameter TIME_S =11'd2000-1;
parameter TIME_US =7'd100-1;
parameter TIME_MS =10'd1000-1;//2=20ns*2*50*1000*1000
parameter TIME_S =11'd1000-1;
reg [6:0]cnt_us;
reg [10:0]cnt_ms,cnt_s;
//1us计时
wire add_cnt_us;//计时开始和结束的标志位
wire end_cnt_us;
always @( posedge clk or negedge rst)begin
if(!rst)
cnt_us<=1'b0;
else if(add_cnt_us)begin
if(cnt_us==TIME_US)
cnt_us<=1'b0;
else
cnt_us<=cnt_us+1'b1;
end
else
cnt_us<=cnt_us;
end
assign add_cnt_us=1;//默认开始状态
assign end_cnt_us=add_cnt_us && (cnt_us==TIME_US);//计数开始且计数值满结束标志置1
//1ms计数
wire add_cnt_ms;//计时开始和结束的标志位
wire end_cnt_ms;
always @( posedge clk or negedge rst)begin
if(!rst)
cnt_ms<=1'b0;
else if(add_cnt_ms)begin
if(cnt_ms==TIME_MS)
cnt_ms<=1'b0;
else
cnt_ms<=cnt_ms+1'b1;
end
else
cnt_ms<=cnt_ms;
end
assign add_cnt_ms=end_cnt_us;//us计时结束ms计数开始
assign end_cnt_ms=add_cnt_ms && (cnt_ms==TIME_MS);//计数开始且计数值满结束标志置1
//1s计数
wire add_cnt_s;//计时开始和结束的标志位
wire end_cnt_s;
always @( posedge clk or negedge rst)begin
if(!rst)
cnt_s<=1'b0;
else if(add_cnt_s)begin
if(cnt_s==TIME_S)
cnt_s<=1'b0;
else
cnt_s<=cnt_s+1'b1;
end
else
cnt_s<=cnt_s;
end
assign add_cnt_s=end_cnt_ms;//ms计时结束s计数开始
assign end_cnt_s=add_cnt_s && (cnt_s==TIME_S);//计数开始且计数值满结束标志置1
//呼吸控制
reg flag;
//reg [1:0]flag_2;//流水灯跳转标志位
always @( posedge clk or negedge rst)begin
if(!rst)begin
flag<=1'b0;
// flag_2<=2'b0;
end
else if(end_cnt_s)begin
flag<=~flag;
// flag_2<=flag_2+1'b1;
end
// else if(flag_2==2'd2)
// flag_2<=0;
else begin
flag<=flag;
// flag_2<=flag_2;
end
end
//流水灯四个状态
//reg [1:0]state;
//always @( posedge clk or negedge rst)begin
// if(!rst)
// state<=1'b0;
// else begin
// if(flag_2==2'b10)
// state<=state +1'b1;
// else
// state<=state;
// end
//end
//灯显示
always @( posedge clk or negedge rst)begin
if(!rst)
led<=4'b0;
else begin
// case(state)
// 2'b00:begin
led[0]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
led[1]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
led[2]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
led[3]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
// end
// 2'b01:begin
// led[1]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
// led[0]<=1'b0;
// led[2]<=1'b0;
// led[3]<=1'b0;
// end
// 2'b10:begin
// led[2]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
// led[1]<=1'b0;
// led[0]<=1'b0;
// led[3]<=1'b0;
// end
// 2'b11:begin
// led[3]<=cnt_ms>cnt_s?(flag?0:1):(flag?1:0);
// led[1]<=1'b0;
// led[2]<=1'b0;
// led[0]<=1'b0;
// end
// default:;
// endcase
// ;
end
end
endmodule
仿真部分:通过传入更小数值进行仿真,减小仿真难度。
module breath_led_tb
#(parameter TIME_US =6'd4,TIME_MS =10'd5,TIME_S =11'd5)();
reg clk,rst;
wire [3:0]led;
breath_led #(
.TIME_US (TIME_US),
.TIME_MS (TIME_MS),
.TIME_S (TIME_S )
)u_breath_led(
.clk (clk),
.rst (rst),
.led (led)
);
always #10 clk<=~clk;
initial begin
rst=0;
clk=0;
#10;
rst=1;
end
endmodule