前段时间思路一直很混乱,总是觉得自己跟着视频学但是没达到自己想要的效果(就是能拿到一个问题,自己分析出需求,明白涉及到的接口有哪些,再是程序逻辑),所以跑去图书馆找了好几本书,翻到了一本适合自己的(代码比较全面,不像有的书籍只写模块,还有些细节东西不写出来),呼吸灯是前天学习完毕的,今天自己将课后训练写完并发现了新的问题。这次明白了时序图的重要性以及采用仿真来看波形进行调试的思路
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// 他的基础思路是将2s拆为1000个2ms,再将2ms拆成1000个2us,在每一个2ms中逐渐增多2us
//亮灯时间,三个计数器要并列放在一起看才行,不可孤立每一个cnt想问题
// Create Date: 2024/03/03 17:09:52
// Design Name:
// Module Name: breath_led
//写着一部分代码我是从微观去思考问题,没有站在更高的角度想问题,所以导致一直没理解
//led亮的条件语句
//////////////////////////////////////////////////////////////////////////////////
module breath_led(
Clk,
Rst,
Led
);
input Clk;
input Rst;
output reg Led;
reg[6:0] cnt_2us;
reg[9:0] cnt_2ms;
reg[9:0] cnt_2s;
reg [1:0] half_cnt_4s;
//3个cnt是同时进行计数的
parameter Max_us = 100-1;//99
parameter Max_ms = 1000-1;//999
parameter Max_s = 1000-1;//999
//cnt_2us,他的基本单位是时钟周期20ns,所以时钟周期满99就是一个2us
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
cnt_2us <= 0;
end
else if (cnt_2us == Max_us)
cnt_2us <= 0;
else
cnt_2us <= cnt_2us + 1'b1;
end
//cnt_2ms,他的基本单位是2us,所以当cnt_2us满99就说明有一个2us,所以要求2ms就是1000个2us
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
cnt_2ms <= 0;
end
else if ((cnt_2ms == Max_ms) && (cnt_2us == Max_us))
cnt_2ms <= 0;
else if ((cnt_2us == Max_us) && (cnt_2ms < Max_ms))
cnt_2ms <= cnt_2ms + 1'b1;
end
//cnt_2s,他的基本单位是2ms,由上可知cnt_2us满99就说明有一个2us,cnt_2ms满99就说明有一个2ms,所以要1000
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
cnt_2s <= 0;
end
else if ((cnt_2us == Max_us) && (cnt_2ms == Max_ms) && (cnt_2s == Max_s))begin
cnt_2s <= 0;
end
else if ((cnt_2us == Max_us) && (cnt_2ms == Max_ms) && (cnt_2s < Max_s))
cnt_2s <= cnt_2s + 1'b1;
end
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
half_cnt_4s <= 0;
end
else if (half_cnt_4s == 2)
half_cnt_4s <= 0;
else if ((cnt_2us == Max_us) && (cnt_2ms == Max_ms) && (cnt_2s == Max_s))
half_cnt_4s <= half_cnt_4s + 1;
end
/*
//Led 由暗到亮
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
Led <= 0;
end
else if (cnt_2s > cnt_2ms)//**************这一步最关键,一定要配套时序图
Led <= 1;
else
Led <= 0;
end
*/
/*
//先暗后亮再逐渐熄灭(这里是错误的,上板实验显示一直亮灯并且没有呼吸变化),用于记录对比
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
Led <= 0;
end
else if (half_cnt_4s >= 0 && half_cnt_4s < 1) begin//**************这一步最关键,一定要配套时序图
if (cnt_2s > cnt_2ms)begin
Led <= 1;
end
end
else if (half_cnt_4s >= 1 && half_cnt_4s < 2)begin
if ((cnt_2s + cnt_2ms) < 1000)begin
Led <= 1;
end
end
else
Led <= 0;
end
*/
//先暗后亮再逐渐熄灭,进行的修改,是将两个else if里的语句提取出来用于并列才解决问题,以后也许就是一直采用这种方法了,这里面由全亮到全暗的过程还是要对比时序图,找规 //律,既然由全暗到全亮,是逐渐提高亮的2us所占有的比例而且是从前向后逐渐增多,那么从全亮到全暗就是逆过来,从后向前逐渐减少,一开始想着直接取反,但是发现逻辑错误,因为这
//样是从前向后逐渐减少比例,后面对比时序图规律发现距离中位数两侧等距的数字的和不变才想到这一步,经过上板实验验证成功,还有一点就是进行仿真一定要仔细对比,同时有些参数可
//以修改小一些节约时间,我写这么大的数字也花了好几分钟才达到half_cnt_4s大于0的场景(注意half_cnt_4s是离散量不是连续量)
always@(posedge Clk or negedge Rst)begin
if (Rst == 0)begin
Led <= 0;
end
else if (half_cnt_4s >= 0 && half_cnt_4s < 1 && cnt_2s > cnt_2ms)
Led <= 1;
else if (half_cnt_4s >= 1 && half_cnt_4s < 2 && (cnt_2s + cnt_2ms) < 1000)
Led <= 1;
else
Led <= 0;
end
endmodule
仿真文件
module breath_led_tb();
reg Clk;
reg Rst;
wire Led;//要对赋值的变量设置为reg,要检测信号(输出)就是wire,而且要先声明变量才能进行例化
breath_led breath_led(
.Clk(Clk),
.Rst(Rst),
.Led(Led)
);//例化
//先初始化
initial begin
Clk <= 0;
Rst <= 0;
#201;
Rst <= 1;
end
//再设置时钟
always #10 Clk = ~Clk;
endmodule