(1)Verilog代码:
module ex_breath_led(clk,reset_n,led_out);
input clk;
input reset_n;
output [3:0]led_out;
reg [5:0]cnt_1us;
reg [9:0]cnt_1ms;
reg [10:0]cnt_2ms;
reg [11:0]cnt_4ms;
reg [12:0]cnt_8ms;
reg [9:0]cnt_1s;
reg overturn;
parameter MCNT_1us = 6'd49;
parameter MCNT_1ms = 10'd999;
parameter MCNT_2ms = 11'd1999;
parameter MCNT_4ms = 12'd3999;
parameter MCNT_8ms = 13'd7999;
parameter MCNT_1s = 10'd999;
//1us计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1us <= 6'd0;
else if(cnt_1us == MCNT_1us)
cnt_1us <= 6'd0;
else
cnt_1us <= cnt_1us + 6'd1;
//1ms计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1ms <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_1ms <= 10'd0;
else if(cnt_1us == MCNT_1us)
cnt_1ms <= cnt_1ms + 10'd1;
else
cnt_1ms <= cnt_1ms;
//2、4、8ms计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_2ms <= 11'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_2ms == MCNT_2ms))
cnt_2ms <= 11'd0;
else if(cnt_1us == MCNT_1us)
cnt_2ms <= cnt_2ms + 11'd1;
else
cnt_2ms <= cnt_2ms;
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_4ms <= 12'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_4ms == MCNT_4ms))
cnt_4ms <= 12'd0;
else if(cnt_1us == MCNT_1us)
cnt_4ms <= cnt_4ms + 12'd1;
else
cnt_4ms <= cnt_4ms;
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_8ms <= 13'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_8ms == MCNT_8ms))
cnt_8ms <= 13'd0;
else if(cnt_1us == MCNT_1us)
cnt_8ms <= cnt_8ms + 13'd1;
else
cnt_8ms <= cnt_8ms;
//1s计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1s <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
cnt_1s <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_1s <= cnt_1s + 10'd1;
else
cnt_1s <= cnt_1s;
//翻转逻辑overturn信号
always@(posedge clk or negedge reset_n)
if(!reset_n)
overturn <= 1'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
overturn <= ~overturn;
else
overturn <= overturn;
//led_out主程序设计
assign led_out[0] = (((overturn == 1'd0)&&(cnt_1ms <= cnt_1s))||((overturn == 1'd1)&&(cnt_1ms <= MCNT_1s - cnt_1s)));
assign led_out[1] = (((overturn == 1'd0)&&((cnt_2ms>>1) <= cnt_1s))||((overturn == 1'd1)&&((cnt_2ms>>1) <= MCNT_1s - cnt_1s)));
assign led_out[2] = (((overturn == 1'd0)&&((cnt_4ms>>2) <= cnt_1s))||((overturn == 1'd1)&&((cnt_4ms>>2) <= MCNT_1s - cnt_1s)));
assign led_out[3] = (((overturn == 1'd0)&&((cnt_8ms>>3) <= cnt_1s))||((overturn == 1'd1)&&((cnt_8ms>>3) <= MCNT_1s - cnt_1s)));
endmodule
(2)仿真文件代码:
`timescale 1ns / 1ps
module ex_breath_led_tb;
reg clk;
reg reset_n;
wire [3:0]led_out;
ex_breath_led ex_breath_led_inst(
.clk(clk),
.reset_n(reset_n),
.led_out(led_out)
);
defparam ex_breath_led_inst.MCNT_1us = 4;
defparam ex_breath_led_inst.MCNT_1ms = 99;
defparam ex_breath_led_inst.MCNT_2ms = 199;
defparam ex_breath_led_inst.MCNT_4ms = 399;
defparam ex_breath_led_inst.MCNT_8ms = 799;
defparam ex_breath_led_inst.MCNT_1s = 99;
initial clk = 1'd1;
always #10 clk = ~clk;
initial begin
reset_n <= 1'd0;
#15;
reset_n <= 1'd1;
#5_000_000;
$stop;
end
endmodule
(3)仿真波形:
(4)引脚绑定:
(5)上版验证后,发现该Verilog代码是错的,在肉眼看来,四个灯是在同频呼吸,因此修改代码为:
module ex_breath_led(clk,reset_n,led_out);
input clk;
input reset_n;
output [3:0]led_out;
reg [5:0]cnt_1us;
reg [9:0]cnt_1ms;
reg [9:0]cnt_1s;
reg [10:0]cnt_2s;
reg [11:0]cnt_4s;
reg [12:0]cnt_8s;
reg [3:0]overturn;
parameter MCNT_1us = 6'd49;
parameter MCNT_1ms = 10'd999;
parameter MCNT_1s = 10'd999;
parameter MCNT_2s = 11'd1999;
parameter MCNT_4s = 12'd3999;
parameter MCNT_8s = 13'd7999;
//1us计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1us <= 6'd0;
else if(cnt_1us == MCNT_1us)
cnt_1us <= 6'd0;
else
cnt_1us <= cnt_1us + 6'd1;
//1ms计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1ms <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_1ms <= 10'd0;
else if(cnt_1us == MCNT_1us)
cnt_1ms <= cnt_1ms + 10'd1;
else
cnt_1ms <= cnt_1ms;
//1s计数器模块
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_1s <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
cnt_1s <= 10'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_1s <= cnt_1s + 10'd1;
else
cnt_1s <= cnt_1s;
//2、4、8秒计数器模块设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_2s <= 11'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_2s == MCNT_2s))
cnt_2s <= 11'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_2s <= cnt_2s + 11'd1;
else
cnt_2s <= cnt_2s;
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_4s <= 12'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_4s == MCNT_4s))
cnt_4s <= 12'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_4s <= cnt_4s + 12'd1;
else
cnt_4s <= cnt_4s;
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt_8s <= 13'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_8s == MCNT_8s))
cnt_8s <= 13'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms))
cnt_8s <= cnt_8s + 13'd1;
else
cnt_8s <= cnt_8s;
//翻转逻辑overturn信号
always@(posedge clk or negedge reset_n)
if(!reset_n)
overturn <= 4'd0;
else if((cnt_1us == MCNT_1us)&&(cnt_1ms == MCNT_1ms)&&(cnt_1s == MCNT_1s))
overturn <= overturn + 4'd1;
else
overturn <= overturn;
//led_out主程序设计
assign led_out[0] = (((overturn[0] == 1'd0)&&(cnt_1ms <= cnt_1s))||((overturn[0] == 1'd1)&&(cnt_1ms <= MCNT_1s - cnt_1s)));
assign led_out[1] = (((overturn[1] == 1'd0)&&(cnt_1ms <= (cnt_2s >> 1)))||((overturn[1] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_2s >> 1))));
assign led_out[2] = (((overturn[2] == 1'd0)&&(cnt_1ms <= (cnt_4s >> 2)))||((overturn[2] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_4s >> 2))));
assign led_out[3] = (((overturn[3] == 1'd0)&&(cnt_1ms <= (cnt_8s >> 3)))||((overturn[3] == 1'd1)&&(cnt_1ms <= MCNT_1s - (cnt_8s >> 3))));
endmodule
`timescale 1ns / 1ps
module ex_breath_led_tb;
reg clk;
reg reset_n;
wire [3:0]led_out;
ex_breath_led ex_breath_led_inst(
.clk(clk),
.reset_n(reset_n),
.led_out(led_out)
);
defparam ex_breath_led_inst.MCNT_1us = 4;
defparam ex_breath_led_inst.MCNT_1ms = 9;
defparam ex_breath_led_inst.MCNT_1s = 9;
defparam ex_breath_led_inst.MCNT_2s = 19;
defparam ex_breath_led_inst.MCNT_4s = 39;
defparam ex_breath_led_inst.MCNT_8s = 79;
initial clk = 1'd1;
always #10 clk = ~clk;
initial begin
reset_n <= 1'd0;
#15;
reset_n <= 1'd1;
#500_000;
$stop;
end
endmodule
仿真波形:
PS:实验现象正确,实现了预定目标,但我觉得可以以0.25s、0.5s、1s、2s的频率去呼吸,8s太长了,效果不佳。