要求:
1:light亮两次灭两次。
2:第一次亮0.1s,灭0.5s,亮0.2s,灭1s。
3:让4个LED循环亮。
4:key1开始,key2结束。
想法:
1:因为有开始键,所以我们要按键消抖,所以第一步开始写按键。
2:因为要下板子,所以我们要分频,分成10HZ的分频。所以第二步分频。
3:因为亮灭,所以我们可以写一个状态机,设成6个状态。分别为IDLE,L01,
B05,L02,B10,stop。当key1为1时,我们就进入L01,在L01亮了0.1s时,进入到B05,依次往下,最后若果当key2为1时,则进入到stop。
4:还要有一个led选择器,因为一个led灯总共完成一次的周期为1.6s,所以每到一个1.6s,我们用一个计数器加一,然后用计数器控制led灯。
代码:
源码:
module led_s(
input clk,
input rst,
input key1,
input key2,
output reg led1,
output reg led2,
output reg led3,
output reg led4
);
parameter IDLE=6'b000001;
parameter L01=6'b000010;
parameter B05=6'b000100;
parameter L02=6'b001000;
parameter B10=6'b010000;
parameter AM=6'b100000;
reg [5:0]c_state,n_state;
//key1的按键消抖
reg key1_o;
wire pos,neg;
always@(posedge clk or negedge rst)
begin
if(~rst)
key1_o<=1;
else
key1_o<=key1;
end
assign pos=key1&(~key1_o);
assign neg=(~key1)&key1_o;
reg k;
always@(posedge clk)
begin
if(~rst)
k<=0;
else if(pos==1||neg==1)
k<=1;
else
k<=0;
end
reg [3:0]cnt;
always@(posedge clk)
begin
if(~rst)
cnt<=0;
else if(k)
cnt<=0;
else
cnt<=cnt+1'b1;
end
reg key1_out;
always@(posedge clk or negedge rst)
begin
if(~rst)
key1_o<=1;
else if(cnt==2)
key1_out<=key1;
end
//key2的按键消抖
reg key2_o;
wire pos1,neg1;
always@(posedge clk or negedge rst)
begin
if(~rst)
key2_o<=1;
else
key2_o<=key2;
end
assign pos1=key2&(~key2_o);
assign neg1=(~key2)&key2_o;
reg k1;
always@(posedge clk)
begin
if(~rst)
k1<=0;
else if(pos==1||neg==1)
k1<=1;
else
k1<=0;
end
reg [3:0]cnt1;
always@(posedge clk)
begin
if(~rst)
cnt1<=0;
else if(k1)
cnt1<=0;
else
cnt1<=cnt+1'b1;
end
reg key2_out;
always@(posedge clk or negedge rst)
begin
if(~rst)
key2_o<=1;
else if(cnt==2)
key2_out<=key2;
end*/
//时间参数
parameter M1=25'd5_000_000;
//时间计数器
reg [24:0]count;
reg [4:0]count1;
always@(posedge clk)
begin
if(~rst)
count<=0;
else if(c_state==IDLE)
count<=0;
else if(count==M1-1'b1)
count<=0;
else
count<=count+1;
end
always@(posedge clk)
begin
if(~rst)
count1<=0;
else if(c_state==IDLE)
count1<=0;
else if(count==M1-1)
begin
if(count1==16)
count1<=0;
else
count1<=count1+1;
end
end
//led选择器
reg [1:0]cnt2;
always@(posedge clk)
begin
if(~rst)
cnt2<=0;
else if(count1==16 && count==M1-1)
cnt2<=cnt2+1;
end
reg led;
always@(posedge clk)
begin
if(~rst)
led1<=0;
else if(cnt2==0)
led1<=led;
else
led1<=0;
end
always@(posedge clk)
begin
if(~rst)
led2<=0;
else if(cnt2==1)
led2<=led;
else
led2<=0;
end
always@(posedge clk)
begin
if(~rst)
led3<=0;
else if(cnt2==2)
led3<=led;
else
led3<=0;
end
always@(posedge clk)
begin
if(~rst)
led4<=0;
else if(cnt2==3)
led4<=led;
else
led4<=0;
end
//三段式状态机
always@(posedge clk)
begin
if(~rst)
c_state<=IDLE;
else
c_state<=n_state;
end
always@(*)
begin
n_state=IDLE;
case(c_state)
IDLE: if(key1==0) n_state=L01; else n_state=IDLE;
L01: if(count1==0 && count==M1-1) n_state=B05; else n_state=L01;
B05: if(count1==5 && count==M1-1) n_state=L02; else n_state=B05;
L02: if(count1==6 && count==M1-1) n_state=B10; else n_state=L02;
B10: if(count1==16 && count==M1-1) n_state=AM; else n_state=B10;
AM: if(key2==0) n_state=IDLE; else n_state=L01;
default: n_state=IDLE;
endcase
end
always@(posedge clk)
begin
if(~rst)
led<=0;
else
case(n_state)
IDLE:led<=0;
L01:led<=1;
B05:led<=0;
L02:led<=1;
B10:led<=0;
AM:led<=0;
default:;
endcase
end
endmodule
激励:
`timescale 1ns/1ns
module led_s_tb();
reg clk;
reg rst;
reg key1;
reg key2;
initial
begin
rst=0;
#100 rst=1;
#10000 $stop;
end
initial
begin
clk=0;
end
always #10 clk<=~clk;
initial
begin
key1=0;
#100 key1=1;
#1000 key1=1;
end
initial
begin
key2=0;
#200 key2=0;
#2000 key2=1;
end
led_s led_s_out(
.clk(clk),
.rst(rst),
.key1(key1),
.key2(key2),
.led1(),
.led2(),
.led3(),
.led4()
);
endmodule