(6)从计数器到可控线性序列机——led实验六部曲
实验一:让一个灯亮0.25s,灭0.75s,循环
always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == 37_499_999) //灭0.75s,即计数到0.75/(20*10e-9)-1 led <= 1; else if (cnt == 49_999_999) led <= 0; //亮0.25s
实验二:亮0.25s,灭0.5s,亮0.75s,灭1s的状态循环
parameter max = 125_000_000; //2.5s为一个周期 reg [26:0] cnt; always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == max/5-1) //0.5s, led <= 1; else if (cnt == max/2-1) //0.5s 0.75s led <= 0; else if (cnt == max*9/10-1) //0.5s 0.75s 1s led <= 1; else if (cnt == max) //0.5s 0.75s 1s 0.25s led <= 0;
和实验一的思路差不多,不过这里我和视频写的不一样,对于第三个else if括号里的不太确定,也没用tb仿真
实验三:led按指定亮灭模式运行,模式未知,由用户给定,以0.25s为一个状态,8个状态为一个循环。
//2s为一个实验周期,有一个输入端口 parameter max = 100_000_000; //2s为一个周期 input [7:0] ctrl; //输入端口 reg [26:0] cnt; always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == max/8-1) //0.25s, led <= ctrl[0]; else if (cnt == max*2/8-1) // led <= ctrl[1]; else if (cnt == max*3/8-1) // led <= ctrl[2]; .......//后面懒得写了
当然,还有一种方法:
实验三:led按指定亮灭模式运行,模式未知,由用户给定,8个状态为一个循环,每个状态的时间可自定义。
input [7:0] ctrl; //输入端口
input [31:0] time; //输入时间端口
reg [26:0] cnt;
reg [2:0] counter = 0; //八个状态
//设计思路:每计满一个小状态,counter+1,然后根据counter的值去 //选择led的电平 always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == time-1) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) counter <= 0; else if (cnt == time-1) counter <= counter + 1;
always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (counter == 0) // led <= ctrl[0]; else if (counter == 1) // led <= ctrl[1]; else if (counter == 2) // led <= ctrl[2]; .......//后面懒得写了
实验四:多个led各自在不同的模式下循环闪烁
差不多就是这样的思路:
实验五:每隔10ms让led的8个状态循环执行一次
设计思路:
代码:
input [7:0] ctrl; //输入端口 reg [26:0] cnt; reg [26:0] cnt1; reg [31:0] time; reg [2:0] counter = 0; //八个状态 reg en; //计满一个小状态 always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (en) begin if (cnt == time-1) cnt <= cnt + 1; end else cnt <= cnt + 1; //计满10ms always@(posedge clk or negedge rst) if(!rst) cnt1 <= 0; else if (cnt == 500000-1) cnt1 <= 0; else cnt1 <= cnt1 + 1; //状态切换 always@(posedge clk or negedge rst) if(!rst) counter <= 0; else if(en) begin if (cnt == time-1) counter <= counter +1; end else counter <= 0; //使能控制,cnt1为0(即新的10ms开始)时拉高,8个状态完成后拉低 always@(posedge clk or negedge rst) if(!rst) en <= 0; else if (cnt1 == 0) en <= 1; else if(counter == 7) en <= 0; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (counter == 0) // led <= ctrl[0]; else if (counter == 1) // led <= ctrl[1]; else if (counter == 2) // led <= ctrl[2]; .......//后面懒得写了
注意的是,只有在en使能的情况下,计一个小状态的计数和状态切换的计数才能够计数,否则需要暂停