module top ( input wire sys_clk, input wire sys_rst_n , input wire one, input wire half, output wire [03:00] led ); wire one_out_w; wire half_out_w; wire po_cola; wire po_money; key_filter key_filter_insert( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .one (one) , .half ( half ) , .one_out ( one_out_w ) , .half_out (half_out_w) ); complex_fsm complex_fsm_insert ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .money_one ( one_out_w ) , .money_half ( half_out_w) , .po_cola ( po_cola ) , .po_money ( po_money ) , .led (led) ); endmodule
module key_filter #( parameter MAX_CNT_20MS = 20'd100_0000 )( input wire sys_clk, input wire sys_rst_n , input wire one, input wire half, output reg one_out , output reg half_out ); /****************************************************** **** * What are the elements of a counter? * 1 Conditions for starting counting. When to start counting? * 2 Conditions for counting to zero When to end counting * 3 Bit width of counting register *Key points: * How to generate these two conditions is the key. ************************************************* **/ // wire define wire [01:00] key; wire nege; wire pose; wire add_cnt_20ms; wire end_cnt_20ms; //regdefine reg [19:00] cnt_20ms; reg [01:00] key_r1; reg [01:00] key_r2; reg add_cnt_flag; // key assign key = {one, half}; // key_r1 always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin key_r1 <= 1'b1; end else begin key_r1 <= key ; end end // key_r2 always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin key_r2 <= 1'b1; end else begin key_r2 <= key_r1; end end // nege pose assign nege = | ( ~key_r1 & amp; key_r2 ) ; // Both require bitwise operations assign pose = | ( key_r1 & amp; ~key_r2 ) ; // add_cnt_flag always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin add_cnt_flag <= 1'b0; end else begin if(nege) begin add_cnt_flag <= 1'b1; end else begin if( pose || end_cnt_20ms ) begin add_cnt_flag <= 1'b0; end else begin add_cnt_flag <= add_cnt_flag; end end end end // cnt_20ms add_cnt_20ms end_cnt_20ms always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin cnt_20ms <= 20'd0; end else begin if(add_cnt_20ms) begin if(end_cnt_20ms) begin cnt_20ms <= 20'd0; end else begin cnt_20ms <= cnt_20ms + 20'd1; end end else begin cnt_20ms <= 20'd0; end end end assign add_cnt_20ms = add_cnt_flag; assign end_cnt_20ms = add_cnt_20ms & amp; & amp; cnt_20ms == ( MAX_CNT_20MS - 1'b1 ) ; // one_out always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin one_out <= 1'b0; end else begin if(end_cnt_20ms) begin one_out <= ~key_r2[1]; end else begin one_out <= 1'b0; end end end // half_out always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin half_out <= 1'b0; end else begin if(end_cnt_20ms) begin half_out <= ~key_r2[0]; end else begin half_out <= 1'b0; end end end endmodule // `timescale 1ns/1ns // // // Author : EmbedFire // // Create Date : 2019/03/15 // // Module Name : key_filter // // Project Name : key_filter // // Target Devices: Altera EP4CE10F17C8N // // Tool Versions: Quartus 13.0 // // Description: Button debounce module // // // // Revision : V1.0 // // Additional Comments: // // // // Experimental platform: Wildfire_Zhengtu Pro_FPGA development board // // Company: http://www.embedfire.com // // Forum: http://www.firebbs.cn // // Taobao: https://fire-stm32.taobao.com // // module key_filter // #( // parameter CNT_MAX = 20'd999_999 //Maximum value of counter count // ) //( // input wire sys_clk, // system clock 50Mhz // input wire sys_rst_n , //global reset // input wire key_in, //key input signal //output reg key_flag //When key_flag is 1, it means that the key is detected after debounce. // //When key_flag is 0, it means that no key has been detected. // ); // //********************************************** ************************// // //****************** Parameter and Internal Signal *******************// // //********************************************** ************************// // //reg define // reg [19:0] cnt_20ms; //Counter // //********************************************** ************************// // //**************************** Main Code *************** *************// // //********************************************** ************************// // //cnt_20ms: If the rising edge of the clock detects that the value of the external key input is low, the counter starts counting. // always@(posedge sys_clk or negedge sys_rst_n) // if(sys_rst_n == 1'b0) // cnt_20ms <= 20'b0; // else if(key_in == 1'b1) // cnt_20ms <= 20'b0; // else if(cnt_20ms == CNT_MAX & amp; & amp; key_in == 1'b0) // cnt_20ms <= cnt_20ms; //else // cnt_20ms <= cnt_20ms + 1'b1; // //key_flag: The key valid flag is generated when the count reaches 20ms. // //And key_flag is pulled high at 999_999 and maintained at a high level for one clock // always@(posedge sys_clk or negedge sys_rst_n) // if(sys_rst_n == 1'b0) // key_flag <= 1'b0; // else if(cnt_20ms == CNT_MAX - 1'b1) // key_flag <= 1'b1; //else // key_flag <= 1'b0; // endmodule
module complex_fsm #( parameter CNT_1US = 6'd50 , CNT_1K = 10'd1000 )( input wire sys_clk, input wire sys_rst_n , input wire money_one, input wire money_half, output reg po_cola , output reg po_money , output reg [03:00] led ); // define wire signal wire [01:00] money; wire clear; //define reg signal reg [06:00] state ; regctrl; reg [03:00] water_led; // counter reg [05:00] cnt_1us; wire add_cnt_1us; wire end_cnt_1us; reg [09:00] cnt_1ms; wire add_cnt_1ms; wire end_cnt_1ms; reg [09:00] cnt_1s; wire add_cnt_1s; wire end_cnt_1s; reg [03:00] cnt_10s; wire add_cnt_10s; wire end_cnt_10s; //define localparam localparam IDLE = 7'b0000001 , HALF = 7'b0000010 , ONE = 7'b0000100 , ONE_HALF = 7'b0001000 , TWO = 7'b0010000 , WATER_R = 7'b0100000 , WATER_C = 7'b1000000; // money // assign money = ( money_half ) ? 2'b01 : ( money_one ) ? 2'b10 : 2'b00 ; assign money = {money_one,money_half}; // counter // cnt_1us always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin cnt_1us <= 0 ; end else begin if(clear) begin cnt_1us <= 0 ; end else begin if(add_cnt_1us) begin // The state machine starts counting in the non-IDLE state if(end_cnt_1us) begin // The state machine needs to be cleared and counted again after the state transition and after it is full. cnt_1us <= 0 ; end else begin cnt_1us <= cnt_1us + 1'b1; end end else begin cnt_1us <= 0; // The count value of the state machine returns to zero in the IDLE state end end end end assign clear = (state != IDLE & amp; & amp; state != WATER_R & amp; & amp; state != WATER_C & amp; & amp; money != 2'b00) ; assign add_cnt_1us = state != IDLE ; assign end_cnt_1us = add_cnt_1us & amp; & amp; cnt_1us == ( CNT_1US - 1'b1 ); //|| (state == WATER_R & amp; & amp; end_cnt_10s) || (state == WATER_C & amp; & amp; end_cnt_10s) Since it will be reset to zero when entering IDLE, there is no need to write these two sentences. // cnt_1ms always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin cnt_1ms <= 0 ; end else begin if(clear) begin cnt_1ms <= 0 ; end else begin if(add_cnt_1ms) begin if(end_cnt_1ms) begin cnt_1ms <= 0 ; end else begin cnt_1ms <= cnt_1ms + 1'b1; end end else begin cnt_1ms <= cnt_1ms; // Obviously it cannot be reset to zero here and needs to be maintained. end end end end assign add_cnt_1ms = end_cnt_1us; // cascade assign end_cnt_1ms = add_cnt_1ms & amp; & amp; cnt_1ms == ( CNT_1K - 1'b1 ) ; // cnt_1s always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin cnt_1s <= 0 ; end else begin if(clear) begin cnt_1s <= 0 ; end else begin if(add_cnt_1s) begin if(end_cnt_1s) begin cnt_1s <= 0 ; end else begin cnt_1s <= cnt_1s + 1'b1; end end else begin cnt_1s <= cnt_1s ; end end end end assign add_cnt_1s = end_cnt_1ms; assign end_cnt_1s = add_cnt_1s & amp; & amp; cnt_1s == ( CNT_1K - 1'b1 ) ; // cnt_10s always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin cnt_10s <= 0 ; end else begin if(clear) begin cnt_10s <= 0 ; end else begin if(add_cnt_10s) begin if(end_cnt_10s) begin cnt_10s <= 0 ; end else begin cnt_10s <= cnt_10s + 1'b1; end end else begin cnt_10s <= cnt_10s ; end end end end assign add_cnt_10s = end_cnt_1s; assign end_cnt_10s = add_cnt_10s & amp; & amp; cnt_10s == ( 4'd10 - 4'b1 ) ; // state always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin state <= IDLE ; end else begin case(state) IDLE: begin if(money == 2'b01) begin state <= HALF ; end else begin if(money == 2'b10) begin state <= ONE ; end else begin state <= IDLE ; end end end HALF: begin if(end_cnt_10s) begin state <= IDLE ; end else begin if(money == 2'b01) begin state <= ONE ; end else begin if(money == 2'b10) begin state <= ONE_HALF; end else begin state <= HALF ; end end end end ONE: begin if(end_cnt_10s) begin state <= IDLE ; end else begin if(money == 2'b01) begin state <= ONE_HALF; end else begin if(money == 2'b10) begin state <= TWO ; end else begin state <= ONE ; end end end end ONE_HALF : begin if(end_cnt_10s) begin state <= IDLE ; end else begin if(money == 2'b01) begin state <= TWO ; end else begin if(money == 2'b10) begin state <= WATER_R; // Exactly 2.5 yuan to enter the right flow state end else begin state <= ONE_HALF; end end end end TWO: begin if(end_cnt_10s) begin state <= IDLE ; end else begin if(money == 2'b01) begin state <= WATER_R; // Exactly 2.5 yuan to enter the right flow state end else begin if(money == 2'b10) begin state <= WATER_C ; end else begin state <= TWO ; end end end end WATER_R : begin if(end_cnt_10s) begin state <= IDLE ; end else begin state <= WATER_R ; end end WATER_C : begin if(end_cnt_10s) begin state <= IDLE ; end else begin state <= WATER_C ; end end default : state <= IDLE ; endcase end end //ctrl always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin ctrl <= 1'b1; end else begin if(water_led == 4'b1110) begin ctrl <= 1'b0; end else begin if(water_led == 4'b0111) begin ctrl <= 1'b1; end else begin ctrl <= ctrl ; end end end end // water_led always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin water_led <= 4'b0111; end else begin case (state) WATER_R : begin if(end_cnt_1s) begin water_led <= { led[0], led[03:01] }; end else begin water_led <= water_led; end end WATER_C : begin if(end_cnt_1s) begin if( ctrl & amp; & amp; end_cnt_1s ) begin // An enable or control signal is needed here, and end_cnt_1s needs to be connected to maintain the LED 1110 state for 1s water_led <= { led[0], led[03:01] }; end else begin water_led <= { led[02:00], led[3] }; end end else begin water_led <= water_led; end end default: water_led <= 4'b0111; // Unchanged when not in use to save power consumption. endcase end end // led always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin led <= 4'b1010; end else begin case (state) IDLE: begin led <= 4'b1111; end HALF: begin led <= 4'b1110; end ONE: begin led <= 4'b1100; end ONE_HALF : begin led <= 4'b1000; end TWO: begin led <= 4'b0000; end WATER_R : begin led <= water_led ; end WATER_C : begin led <= water_led ; end default: led <= 4'b0101; endcase end end // po_cola always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin po_cola <= 0 ; end else begin if( (state == ONE_HALF & amp; & amp; money == 2'b10) || (state == TWO & amp; & amp; money != 2'b00) ) begin po_cola <= 1'b1; end else begin po_cola <= 0 ; end end end // po_money always @(posedge sys_clk or negedge sys_rst_n) begin if(~sys_rst_n) begin po_money <= 0 ; end else begin if(state == TWO & amp; & amp; money == 2'b10) begin po_money <= 1; end else begin po_money <= 0 ; end end end endmodule