通过按键控制蜂鸣器工作。
模块框图:
时序图:
代码:
/*
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
仿真: