Mealy型序列检测机+按键防抖模块

Mealy型序列检测机+按键防抖模块

内容简述

输入8位序列,检测是否有“1011”序列。按btnA开始工作。按一次btnB检测一位,用currled显示该位是0/1,若检测到“1011”则将markled标为1.

按键防抖模块

我试过网上能找到的许许多多按键防抖模块,自己也写过好多,以下是我见过最清楚并且好用的一个。该按键保证每次按下不论按多久都只产生一次脉冲,凡是需要用到按键的时候都可以调用,可移植性强。下面是来源网址一个不错的FPGA学习网站

module debounce(input clk,pb_1,output pb_out);
wire slow_clk_en;
wire Q1,Q2,Q2_bar,Q0;
clock_enable u1(clk,slow_clk_en);
my_dff_en d0(clk,slow_clk_en,pb_1,Q0);

my_dff_en d1(clk,slow_clk_en,Q0,Q1);
my_dff_en d2(clk,slow_clk_en,Q1,Q2);
assign Q2_bar = ~Q2;
assign pb_out = Q1 & Q2_bar;
endmodule
//--------------------------------------------------------------------
// Slow clock enable for debouncing button 
module clock_enable(input Clk_100M,output slow_clk_en);
    reg [26:0]counter=0;
    always @(posedge Clk_100M)
    begin
       counter <= (counter>=249999)?0:counter+1;
    end
    assign slow_clk_en = (counter == 249999)?1'b1:1'b0;
endmodule
//--------------------------------------------------------------------
// D-flip-flop with clock enable signal for debouncing module 
module my_dff_en(input DFF_CLOCK, clock_enable,D, output reg Q=0);
    always @ (posedge DFF_CLOCK) begin
  if(clock_enable==1) 
           Q <= D;
    end
endmodule 

主模块

verilog语言中不能用变量名(如cnt)进行下表索引,由于不太习惯用硬件语言,刚开始程序虽能通过,但是上板的结果不正确。找了很久才找到原因。后来改用了seq<={seq[6:0],seq[7]}这种方式,用固定的下标则能正确显示结果。
在这里插入图片描述

module mealy(
    clk,
    btnA,
    btnB,
    switchs,
    currled,
    markled,
    work,
);
input clk;
input btnA,btnB;
input [7:0] switchs;
reg [1:0] y;//当前状态
reg [2:0] cnt;//计数输到了第几位
reg [7:0] seq;//存储当前序列
output reg currled;//用于输出当前位置的信息。
output reg markled;//是否检测到“1011”序列
output reg work;//是否处于工作状态
integer i;
//----------------------------------------------------
initial 
begin
    markled<=1'b0;
    work<=1'b0;
    seq<=switchs;
end
//----------------------------------------------------
//button debounce
wire signalA;
wire signalB;
debounce myBtnA(clk, btnA, signalA);
debounce myBtnB(clk, btnB, signalB);
//-----------------------------------------------------
//Sequence detection
always@(posedge signalB or posedge signalA)
begin
    if(signalA)//由于是上升沿,1为有效值,判断是否开始
        begin
            work<=~work;
            seq<=switchs;
            markled=1'b0;
            cnt<=3'b000;
            y<=2'b00;
        end 
    else if(signalB&&work)//由于是上升沿,1为有效值,判断是否读入下一位
    //对signalB的判断必须写在else中,不然有可能在A为上升沿进入aways语句时却进行了B的操作。
        begin
            seq<={seq[6:0],seq[7]};  
            currled<=seq[7];     
            if(!seq[7])
                case(y)
                    2'b00:begin y<=2'b00;markled<=1'b0; end
                    2'b01:begin y<=2'b10;markled<=1'b0; end
                    2'b10:begin y<=2'b00;markled<=1'b0; end
                    2'b11:begin y<=2'b10;markled<=1'b0; end    
                endcase
            else
                case(y)
                    2'b00:begin y<=2'b01;markled<=1'b0; end
                    2'b01:begin y<=2'b01;markled<=1'b0; end
                    2'b10:begin y<=2'b11;markled<=1'b0; end
                    2'b11:begin y<=2'b01;markled<=1'b1; end    
                endcase
            if(cnt==3'b111)work<=1'b0;//cnt用于计数,是否已输到末尾,并判断停止工作状态。
            else cnt<=cnt+1;     
        end
end
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值