通过按键控制蜂鸣器工作。
模块框图:
时序图:
代码:
- /*
- 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
- /*
- 蜂鸣器驱动模块,NPN三极管,beep_en == 1 鸣叫。有源电磁式。
- 1, 初始状态鸣叫,按键每按下一次,蜂鸣器状态翻转。
- 2. 初始状态蜂鸣器工作,响100ms , 不响100ms, 响100ms, 不响300ms.按键每按下一次,蜂鸣器工作状态翻转。
- */
- module beep (
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire key_flag ,
-
- output reg beep_en
- );
- // // output reg beep_en
- // always @(posedge sys_clk or negedge sys_rst_n) begin
- // if(~sys_rst_n)
- // beep_en <= 1'b1 ;
- // else if(key_flag)
- // beep_en <= ~beep_en ;
- // end
- // parameter
- parameter MAX_CNT_100MS = 5_000_000 ,
- MAX_CNT_300MS = 15_000_000 ;
- localparam RING = 3'b001 ,
- NO_RING_MOD1 = 3'b010 ,
- NO_RING_MOD2 = 3'b100 ;
- // reg signal define
- reg beep_work ;
- reg [23:0] cnt_core ;
- reg [2:0] state_c ;
- reg [2:0] state_n ;
- reg mod1_flag ;
- // wire signal define
- wire RINGtoNO_RING_MOD1 ;
- wire RINGtoNO_RING_MOD2 ;
- wire NO_RING_MOD1toRING ;
- wire NO_RING_MOD2toRING ;
- wire no_ring_done ;
- /*****************************************************/
- // reg beep_work ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- beep_work <= 1'b1 ;
- else if(key_flag)
- beep_work <= ~beep_work ;
- else
- beep_work <= beep_work ;
- end
- // reg [2:0] state_c ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- state_c <= RING ;
- else
- state_c <= state_n ;
- end
- // reg [2:0] state_n ;
- always @(*) begin
- if(beep_work) begin
- case(state_c)
- RING : if(RINGtoNO_RING_MOD1)
- state_n = NO_RING_MOD1 ;
- else if(RINGtoNO_RING_MOD2)
- state_n = NO_RING_MOD2 ;
- else
- state_n = RING ;
- NO_RING_MOD1: if(NO_RING_MOD1toRING)
- state_n = RING ;
- else
- state_n = NO_RING_MOD1 ;
- NO_RING_MOD2: if(NO_RING_MOD2toRING)
- state_n = RING ;
- else
- state_n = NO_RING_MOD2 ;
- default : state_n = RING ;
- endcase
- end
- else
- state_n = RING ;
- end
- assign RINGtoNO_RING_MOD1 = (state_c == RING) && (no_ring_done && (mod1_flag)) ;
- assign RINGtoNO_RING_MOD2 = (state_c == RING) && (no_ring_done && (!mod1_flag)) ;
- assign NO_RING_MOD1toRING = (state_c == NO_RING_MOD1) && (no_ring_done) ;
- assign NO_RING_MOD2toRING = (state_c == NO_RING_MOD2) && (no_ring_done) ;
- // reg [23:0] cnt_core ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- cnt_core <= 24'd0 ;
- else
- if(beep_work) begin
- case (state_c)
- RING : if(no_ring_done)
- cnt_core <= 24'd0 ;
- else
- cnt_core <= cnt_core + 1'b1 ;
- NO_RING_MOD1: if(no_ring_done)
- cnt_core <= 24'd0 ;
- else
- cnt_core <= cnt_core + 1'b1 ;
- NO_RING_MOD2: if(no_ring_done)
- cnt_core <= 24'd0 ;
- else
- cnt_core <= cnt_core + 1'b1 ;
- default : cnt_core <= 24'd0 ;
- endcase
- end
- else
- cnt_core <= 24'd0 ;
- end
- // reg mod1_flag ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- mod1_flag <= 1'b1 ;
- else if(beep_work) begin
- if((state_c != RING) && (no_ring_done))
- mod1_flag <= ~mod1_flag ;
- else
- mod1_flag <= mod1_flag ;
- end
- else
- mod1_flag <= 1'b1 ;
- end
- // wire no_ring_done;
- assign no_ring_done = (((state_c != NO_RING_MOD2)&&(cnt_core == MAX_CNT_100MS - 1))||((state_c == NO_RING_MOD2)&&(cnt_core == MAX_CNT_300MS - 1))) ? 1'b1 : 1'b0 ;
- // output reg beep_en
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- beep_en <= 1'b1 ;
- else if(beep_work) begin
- if(state_c == RING)
- beep_en <= 1'b1 ;
- else
- beep_en <= 1'b0 ;
- end
- else
- beep_en <= 1'b0 ;
- end
-
- endmodule
- module top(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire key_in ,
-
- output wire beep
- );
- // 例化间连线
- wire key_flag ;
- key_filter key_filter_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .key_in ( key_in ) ,
-
- .key_flag ( key_flag )
- );
-
- beep beep_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .key_flag ( key_flag ) ,
-
- .beep_en ( beep )
- );
-
- endmodule
- `timescale 1ns/1ns
- module test_top();
- reg sys_clk ;
- reg sys_rst_n ;
- reg key_in ;
-
- wire beep ;
-
- top top_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .key_in ( key_in ) ,
-
- .beep ( beep )
- );
-
- parameter CYCLE = 20 ;
- defparam top_inst.key_filter_inst.MAX_CNT_10MS = 50 ;
- defparam top_inst.beep_inst.MAX_CNT_100MS = 500 ;
- defparam top_inst.beep_inst.MAX_CNT_300MS = 1500 ;
-
- initial begin
- sys_clk = 1'b1 ;
- sys_rst_n <= 1'b0 ;
- key_in <= 1'b1 ;
- #( CYCLE * 10 ) ;
- sys_rst_n <= 1'b1 ;
- #( CYCLE * 10 ) ;
-
- #( CYCLE * 3000 ) ;
- #( CYCLE * 500 ) ; // 检测蜂鸣器状态机是否正常工作。
-
- key_in <= 1'b0 ;
- #( CYCLE * 50 * 3 ); // 按下足够长的时间,第一次按键按下。
- key_in <= 1'b1 ;
- #( CYCLE * 3000 ) ;
- #( CYCLE * 500 ) ; // 检测蜂鸣器状态机是否正常工作。
-
- key_in <= 1'b0 ;
- #( CYCLE * 50 * 3 ); // 按下足够长的时间,第二次按键按下。
- key_in <= 1'b1 ;
- #( CYCLE * 3000 ) ;
- #( CYCLE * 500 ) ; // 检测蜂鸣器状态机是否正常工作。
-
- $stop ;
- end
-
- always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
-
-
- endmodule
仿真: