设计思路:
三个按键控制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) beginif(~sys_rst_n) key_in_r1 <= 1'b1 ;elsekey_in_r1 <= key_in ;end // reg key_in_r2 ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) key_in_r2 <= 1'b1 ;elsekey_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) beginif(~sys_rst_n) state_c <= IDLE ;elsestate_c <= state_n ;end// reg [3:0] state_n ;always @(*) begincase(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 ;elsestate_n = FILTER_BACK ;default : state_n = IDLE ;endcaseendassign 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) beginif(~sys_rst_n) cnt_core <= 19'd0 ;elsecase (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 ;endcaseend// wire filter_doneassign filter_done = (cnt_core == MAX_CNT_10MS - 1) ;// output reg key_flagalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) key_flag <= 1'b0 ;else if(FILTER_UPtoSAMPLING)key_flag <= ~key_in_r2 ;else key_flag <= 1'b0 ;endendmodule
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 definereg [24:0] cnt_500ms ;reg [ 1:0] cnt_state ;// wire signal definewire 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) beginif(~sys_rst_n) cnt_500ms <= 25'd0 ;else if(add_cnt_500ms) beginif(end_cnt_500ms)cnt_500ms <= 25'd0 ;else cnt_500ms <= cnt_500ms + 1'b1 ;endelse cnt_500ms <= 25'd0 ;end// reg [ 1:0] cnt_state ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_state <= 2'd0 ;else if(add_cnt_state) beginif(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) beginif(~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 ;endcaseend
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 definereg [24:0] cnt_500ms ;// wire signal definewire add_cnt_500ms ;wire end_cnt_500ms ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/// reg [24:0] cnt_500ms ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_500ms <= 25'd0 ;else if(add_cnt_500ms) beginif(end_cnt_500ms)cnt_500ms <= 25'd0 ;else cnt_500ms <= cnt_500ms + 1'b1 ;endelse 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) beginif(~sys_rst_n) led_out <= 4'b0000 ;else if(end_cnt_500ms)led_out <= ~led_out ;else led_out <= led_out ;endendmodule
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 definereg [24:0] cnt_500ms ;reg [ 2:0] cnt_state ; // wire signal definewire 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) beginif(~sys_rst_n) cnt_500ms <= 25'd0 ;else if(add_cnt_500ms) beginif(end_cnt_500ms)cnt_500ms <= 25'd0 ;else cnt_500ms <= cnt_500ms + 1'b1 ;endelse cnt_500ms <= 25'd0 ;end// reg [ 1:0] cnt_state ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) cnt_state <= 2'd0 ;else if(add_cnt_state) beginif(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) beginif(~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 ;endcaseend
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 definereg [3:0] state_c ;reg [3:0] state_n ;// wire signalwire 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) beginif(~sys_rst_n) state_c <= IDLE ;elsestate_c <= state_n ;end// reg state_n ;always @(*) begincase(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 ;endcaseendassign 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_outalways @(posedge sys_clk or negedge sys_rst_n) beginif(~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 ;endcaseendendmodule
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 wirewire 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 beginsys_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 ;endalways #( CYCLE / 2 ) sys_clk = ~sys_clk ;endmodule