设计思路:
三个按键控制led输出。
三个按键经过滤波(消抖),产生三个按键标志信号。
三个led数据的产生模块(流水,跑马,闪烁模块),分别产生led信号。
这六路信号(三路按键信号,三路led信号),接入state_led_ctrl模块,进行led_out的控制。
状态机:
模块框图:
代码:
/*
1位按键消抖
*/
module key_filter (
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg key_flag
);
// 参数定义
parameter MAX_CNT_10MS = 500_000 ;
localparam IDLE = 4'b0001 ,
FILTER_UP = 4'b0010 ,
SAMPLING = 4'b0100 ,
FILTER_BACK = 4'b1000 ;
// reg signal define
reg key_in_r1 ;
reg key_in_r2 ;
reg [18:0] cnt_core ;
reg [3:0] state_c ;
reg [3:0] state_n ;
// wire signal define
wire nege ;
wire pose ;
wire IDLEtoFILTER_UP ;
wire FILTER_UPtoIDLE ;
wire FILTER_UPtoSAMPLING ;
wire SAMPLINGtoFILTER_BACK ;
wire FILTER_BACKtoIDLE ;
wire filter_done ;
/******************************************************************/
// reg key_in_r1 ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
key_in_r1 <= 1'b1 ;
else
key_in_r1 <= key_in ;
end
// reg key_in_r2 ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
key_in_r2 <= 1'b1 ;
else
key_in_r2 <= key_in_r1 ;
end
// wire nege ;
assign nege = ~key_in_r1 && key_in_r2 ;
// wire pose ;
assign pose = key_in_r1 && ~key_in_r2 ;
// reg [3:0] state_c ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
state_c <= IDLE ;
else
state_c <= state_n ;
end
// reg [3:0] state_n ;
always @(*) begin
case(state_c)
IDLE : if(IDLEtoFILTER_UP)
state_n = FILTER_UP ;
else
state_n = IDLE ;
FILTER_UP : if(FILTER_UPtoIDLE)
state_n = IDLE ;
else if(FILTER_UPtoSAMPLING)
state_n = SAMPLING ;
else
state_n = FILTER_UP ;
SAMPLING : if(SAMPLINGtoFILTER_BACK)
state_n = FILTER_BACK ;
else
state_n = SAMPLING ;
FILTER_BACK:if(FILTER_BACKtoIDLE)
state_n = IDLE ;
else
state_n = FILTER_BACK ;
default : state_n = IDLE ;
endcase
end
assign IDLEtoFILTER_UP = (state_c == IDLE) && (nege) ;
assign FILTER_UPtoIDLE = (state_c == FILTER_UP) && (pose) ;
assign FILTER_UPtoSAMPLING = (state_c == FILTER_UP) && (filter_done) ;
assign SAMPLINGtoFILTER_BACK = (state_c == SAMPLING) && (pose) ;
assign FILTER_BACKtoIDLE = (state_c == FILTER_BACK)&& (filter_done) ;
// reg [18:0] cnt_core ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_core <= 19'd0 ;
else
case (state_c)
IDLE :cnt_core <= 19'd0 ;
FILTER_UP :if(filter_done)
cnt_core <= 19'd0 ;
else
cnt_core <= cnt_core + 1'b1 ;
SAMPLING :cnt_core <= 19'd0 ;
FILTER_BACK:if(filter_done)
cnt_core <= 19'd0 ;
else
cnt_core <= cnt_core + 1'b1 ;
default : cnt_core <= 19'd0 ;
endcase
end
// wire filter_done
assign filter_done = (cnt_core == MAX_CNT_10MS - 1) ;
// output reg key_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
key_flag <= 1'b0 ;
else if(FILTER_UPtoSAMPLING)
key_flag <= ~key_in_r2 ;
else
key_flag <= 1'b0 ;
end
endmodule
module led_paoma (
input wire sys_clk ,
input wire sys_rst_n ,
output reg [3:0] led_out
);
parameter MAX_CNT_500MS = 25_000_000 ;
// reg signal define
reg [24:0] cnt_500ms ;
reg [ 1:0] cnt_state ;
// wire signal define
wire add_cnt_500ms ;
wire end_cnt_500ms ;
wire add_cnt_state ;
wire end_cnt_state ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
// reg [24:0] cnt_500ms ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_500ms <= 25'd0 ;
else if(add_cnt_500ms) begin
if(end_cnt_500ms)
cnt_500ms <= 25'd0 ;
else
cnt_500ms <= cnt_500ms + 1'b1 ;
end
else
cnt_500ms <= 25'd0 ;
end
// reg [ 1:0] cnt_state ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_state <= 2'd0 ;
else if(add_cnt_state) begin
if(end_cnt_state)
cnt_state <= 2'd0 ;
else
cnt_state <= cnt_state + 1'b1 ;
end
else
cnt_state <= cnt_state ;
end
// // wire signal define
// wire add_cnt_500ms ;
assign add_cnt_500ms = 1'b1 ;
// wire end_cnt_500ms ;
assign end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;
// wire add_cnt_state ;
assign add_cnt_state = end_cnt_500ms ;
// wire end_cnt_state ;
assign end_cnt_state = ((add_cnt_state && (cnt_state == 2'b11 )) ) ;
// output reg [3:0] led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_out <= 4'b0000 ;
else
case (cnt_state)
2'b00 : led_out <= 4'b0001 ;
2'b01 : led_out <= 4'b0010 ;
2'b10 : led_out <= 4'b0100 ;
2'b11 : led_out <= 4'b1000 ;
default: led_out <= 4'b0000 ;
endcase
end
endmodule
module shanshuo (
input wire sys_clk ,
input wire sys_rst_n ,
output reg [3:0] led_out
);
parameter MAX_CNT_500MS = 25_000_000 ;
// reg signal define
reg [24:0] cnt_500ms ;
// wire signal define
wire add_cnt_500ms ;
wire end_cnt_500ms ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
// reg [24:0] cnt_500ms ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_500ms <= 25'd0 ;
else if(add_cnt_500ms) begin
if(end_cnt_500ms)
cnt_500ms <= 25'd0 ;
else
cnt_500ms <= cnt_500ms + 1'b1 ;
end
else
cnt_500ms <= 25'd0 ;
end
// // wire signal define
// wire add_cnt_500ms ;
assign add_cnt_500ms = 1'b1 ;
// wire end_cnt_500ms ;
assign end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;
// output reg [3:0] led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_out <= 4'b0000 ;
else if(end_cnt_500ms)
led_out <= ~led_out ;
else
led_out <= led_out ;
end
endmodule
module led_water (
input wire sys_clk ,
input wire sys_rst_n ,
output reg [3:0] led_out
);
parameter MAX_CNT_500MS = 25_000_000 ;
// reg signal define
reg [24:0] cnt_500ms ;
reg [ 2:0] cnt_state ;
// wire signal define
wire add_cnt_500ms ;
wire end_cnt_500ms ;
wire add_cnt_state ;
wire end_cnt_state ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
// reg [24:0] cnt_500ms ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_500ms <= 25'd0 ;
else if(add_cnt_500ms) begin
if(end_cnt_500ms)
cnt_500ms <= 25'd0 ;
else
cnt_500ms <= cnt_500ms + 1'b1 ;
end
else
cnt_500ms <= 25'd0 ;
end
// reg [ 1:0] cnt_state ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_state <= 2'd0 ;
else if(add_cnt_state) begin
if(end_cnt_state)
cnt_state <= 2'd0 ;
else
cnt_state <= cnt_state + 1'b1 ;
end
else
cnt_state <= cnt_state ;
end
// // wire signal define
// wire add_cnt_500ms ;
assign add_cnt_500ms = 1'b1 ;
// wire end_cnt_500ms ;
assign end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;
// wire add_cnt_state ;
assign add_cnt_state = end_cnt_500ms ;// && led_flag
// wire end_cnt_state ;
assign end_cnt_state = ((add_cnt_state && (cnt_state == 3'b101 )) ) ;
// output reg [3:0] led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_out <= 4'b0000 ;
else
case (cnt_state)
3'b000 : led_out <= 4'b0001 ;
3'b001 : led_out <= 4'b0010 ;
3'b010 : led_out <= 4'b0100 ;
3'b011 : led_out <= 4'b1000 ;
3'b100 : led_out <= 4'b0100 ;
3'b101 : led_out <= 4'b0010 ;
default: led_out <= 4'b0000 ;
endcase
end
endmodule
module state_led_ctrl (
input wire sys_clk ,
input wire sys_rst_n ,
input wire water_flag ,
input wire paoma_flag ,
input wire shanshuo_flag ,
input wire [3:0] led_water ,
input wire [3:0] led_paoma ,
input wire [3:0] led_shanshuo ,
output reg [3:0] led_out
);
localparam IDLE = 4'b0001 ,
WATER = 4'b0010 ,
PAOMA = 4'b0100 ,
SHANSHUO = 4'b1000 ;
// reg signal define
reg [3:0] state_c ;
reg [3:0] state_n ;
// wire signal
wire IDLEtoWATER ;
wire IDLEtoPAOMA ;
wire IDLEtoSHANSHUO ;
wire WATERtoPAOMA ;
wire WATERtoSHANSHUO ;
wire PAOMAtoWATER ;
wire PAOMAtoSHANSHUO ;
wire SHANSHUOtoPAOMA ;
wire SHANSHUOtoWATER ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
// // reg signal define
// reg state_c ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
state_c <= IDLE ;
else
state_c <= state_n ;
end
// reg state_n ;
always @(*) begin
case(state_c)
IDLE : if(IDLEtoWATER)
state_n = WATER ;
else if(IDLEtoPAOMA)
state_n = PAOMA ;
else if(IDLEtoSHANSHUO)
state_n = SHANSHUO ;
else
state_n = IDLE ;
WATER : if(WATERtoPAOMA)
state_n = PAOMA ;
else if(WATERtoSHANSHUO)
state_n = SHANSHUO ;
else
state_n = WATER ;
PAOMA : if(PAOMAtoWATER)
state_n = WATER ;
else if(PAOMAtoSHANSHUO)
state_n = SHANSHUO ;
else
state_n = PAOMA ;
SHANSHUO : if(SHANSHUOtoPAOMA)
state_n = PAOMA ;
else if(SHANSHUOtoWATER)
state_n = WATER ;
else
state_n = SHANSHUO ;
default : state_n = IDLE ;
endcase
end
assign IDLEtoWATER = (state_c == IDLE ) && (water_flag ) ;
assign IDLEtoPAOMA = (state_c == IDLE ) && (paoma_flag ) ;
assign IDLEtoSHANSHUO = (state_c == IDLE ) && (shanshuo_flag) ;
assign WATERtoPAOMA = (state_c == WATER ) && (paoma_flag ) ;
assign WATERtoSHANSHUO = (state_c == WATER ) && (shanshuo_flag) ;
assign PAOMAtoWATER = (state_c == PAOMA ) && (water_flag ) ;
assign PAOMAtoSHANSHUO = (state_c == PAOMA ) && (shanshuo_flag) ;
assign SHANSHUOtoPAOMA = (state_c == SHANSHUO ) && (paoma_flag ) ;
assign SHANSHUOtoWATER = (state_c == SHANSHUO ) && (water_flag ) ;
// led_out
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
led_out <= 4'hf ;
else
case (state_c)
IDLE : led_out <= 4'hf ;
WATER : led_out <= led_water ;
PAOMA : led_out <= led_paoma ;
SHANSHUO: led_out <= led_shanshuo ;
default: led_out <= 4'hf ;
endcase
end
endmodule
module top (
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_water ,
input wire key_paoma ,
input wire key_shanshuo ,
output wire [3:0] led_out
);
// inst wire
wire water_flag ;
wire paoma_flag ;
wire shanshuo_flag ;
wire [3:0] led_water ;
wire [3:0] led_paoma ;
wire [3:0] led_shanshuo ;
// inst
key_filter key_filter_inst_water(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_in ( key_water ) ,
.key_flag ( water_flag )
);
key_filter key_filter_inst_paoma(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_in ( key_paoma ) ,
.key_flag ( paoma_flag )
);
key_filter key_filter_inst_shanshuo(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_in ( key_shanshuo ) ,
.key_flag ( shanshuo_flag )
);
led_water led_water_isnt (
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.led_out ( led_water )
);
led_paoma led_paoma_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.led_out ( led_paoma )
);
shanshuo shanshuo_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.led_out ( led_shanshuo )
);
state_led_ctrl state_led_ctrl_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.water_flag ( water_flag ) ,
.paoma_flag ( paoma_flag ) ,
.shanshuo_flag ( shanshuo_flag ) ,
.led_water ( led_water ) ,
.led_paoma ( led_paoma ) ,
.led_shanshuo ( led_shanshuo ) ,
.led_out ( led_out )
);
endmodule
仿真:
`timescale 1ns/1ns
module test_top ();
reg sys_clk ;
reg sys_rst_n ;
reg key_water ;
reg key_paoma ;
reg key_shanshuo ;
wire [3:0] led_out ;
top top_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.key_water ( key_water ) ,
.key_paoma ( key_paoma ) ,
.key_shanshuo ( key_shanshuo ) ,
.led_out ( led_out )
);
defparam top_inst.key_filter_inst_water.MAX_CNT_10MS = 50 ;
defparam top_inst.key_filter_inst_paoma.MAX_CNT_10MS = 50 ;
defparam top_inst.key_filter_inst_shanshuo.MAX_CNT_10MS = 50 ;
defparam top_inst.led_water_isnt.MAX_CNT_500MS = 50 ;
defparam top_inst.led_paoma_inst.MAX_CNT_500MS = 50 ;
defparam top_inst.shanshuo_inst.MAX_CNT_500MS = 50 ;
parameter CYCLE = 20 ;
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b1 ;
key_water <= 1'b1 ;
key_paoma <= 1'b1 ;
key_shanshuo<= 1'b1 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b0 ;
#( 200 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 10 ) ;
key_water <= 1'b0 ;
#( CYCLE * 100 ) ;
key_water <= 1'b1 ;
#( CYCLE * 1000 ) ;
key_paoma <= 1'b0 ;
#( CYCLE * 100 ) ;
key_paoma <= 1'b1 ;
#( CYCLE * 1000 ) ;
key_shanshuo <= 1'b0;
#( CYCLE * 100 ) ;
key_shanshuo <= 1'b1;
#( CYCLE * 1000 ) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule