FPGA进阶教程四--有限状态机的Verilog实现(已完结)

版权说明:未经许可,不得转载

一.目的

1.掌握复杂时序逻辑电路的设计方法

2.了解FPGA中有限状态机的工作原理和实现过程

3.学习用Verilog描述有限状态机的方法。

二.工具

1.Digilent Anvyl开发板

2.安装ISE Design Suite软件的PC机一台

3.USB数据线一根

三.简单上手实验

1.用Verilog HDL设计并实现一个10101串行序列检查器(可重叠)。

2.设计一个密码锁,检测密码为:30221。要求:以4个按钮作为输入,分别表示输入的数据0、1、2、3;当检测到有效的密码输入时,LED0被点亮。

四.实验原理

注:因为这两个实验设计到的代码量相对较多,为了方便后期修改和查看我把实验源码分为了几个部分,最后使用一个顶层文件进行调用处理。

这里给出开发板相关引脚信息和这两个实验的设计思路。

引脚信息:


串行序列检测器设计如下:


密码锁设计如下:

五.实验步骤及结果分析

实验1

设计过程:

1.先对开发板的100Mhz时钟进行分频

2.然后对分频后的时钟进行处理,并获得一个稳定的时钟脉冲

3.画出实验的有限状态机(画的不好看,有强迫症的请不要介意

FPGA进阶教程四--有限状态机的Verilog实现(已完结)

):


根据设计过程,便可写出如下源代码:

时钟分频.v

module clk_div(

    input mclk,

    input clr,

    output clk190

    );



reg [24:0] q;



always@(posedge mclk or posedge clr)

begin

if(clr==1)

q <= 0;

else 

q <= q + 1'b1;

end



assign clk190=q[17];



endmodule

时钟脉冲.v:

module clk_pause(

    input inp,

    input cclk,

    input clr,

    output outp

    );

reg delay1;

reg delay2;

reg delay3;



always@(posedge cclk or posedge clr)

begin

if(clr==1)

begin

delay1 <= 0;

delay2 <= 0;

delay3 <= 0;

end

else

begin

delay1 <= inp;

delay2 <= delay1;

delay3 <= delay2;

end

end



assign outp = delay1&delay2&~delay3;



endmodule

有限状态机.v:

module pg2(

    input wire clk,

input wire clr,

input wire din,

output reg dout

    );

reg [2:0] pre_state,next_state;

parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100,S5=3'b101;

always@(posedge clk or posedge clr)

begin

if(clr==1)

pre_state <= S0;

else

pre_state <= next_state;

end



always@(*)

begin

case(pre_state)

S0:if(din==1)

next_state <= S1;

else

next_state <= S0;

S1:if(din==0)

next_state <= S2;

else

next_state <= S1;

S2:if(din==1)

next_state <= S3;

else

next_state <= S0;

S3:if(din==0)

next_state <= S4;

else

next_state <= S1;

S4:if(din==1)

next_state <= S5;

else

next_state <= S0;

S5:if(din==1)

next_state <= S1;

else

next_state <= S4;

default:next_state <= S0;

endcase

end



always@(*)

begin

if(pre_state==S5)

dout <= 1;

else

dout <= 0;

end



endmodule

顶层文件.v:

module clk_top(

    input mclk,

    input [2:0] btn,

    output led

    );



wire clr,clk190,clkp,btn01;

assign clr=btn[2];

assign btn01 = btn[0]|btn[1];

clk_div U1(.mclk(mclk),

.clr(clr),

.clk190(clk190)



);

clk_pause U2(.inp(btn01),

.cclk(clk190),

.clr(clr),

.outp(clkp)

);

pg2 U3(.clk(clkp),

.clr(clr),

.din(btn[1]),

.dout(led)



);



endmodule

.ucf文件:

NET mclk LOC=D11;

NET led LOC=W3;

NET btn<0> LOC=A3;

NET btn<1> LOC=AB9;

NET btn<2> LOC=E6;

实验结果截图如下:

当输入10101序列(可重叠)后,LED灯亮

实验2

设计过程和上一题一样,唯一不同的就是该实验的有限状态机,如下:


根据设计过程,可写出如下源代码:

时钟分频.v:

module clk_div(

    input mclk,

    input clr,

    output clk190

    );



reg [24:0] q;


always@(posedge mclk or posedge clr)

begin

if(clr==1)

q <= 0;

else 

q <= q + 1'b1;

end


assign clk190=q[17];



endmodule

时钟脉冲.v:

module clk_pause(

    input inp,

    input cclk,

    input clr,

    output outp

    );

reg delay1;

reg delay2;

reg delay3;



always@(posedge cclk or posedge clr)

begin

if(clr==1)

begin

delay1 <= 0;

delay2 <= 0;

delay3 <= 0;

end

else

begin

delay1 <= inp;

delay2 <= delay1;

delay3 <= delay2;

end

end



assign outp = delay1&delay2&~delay3;



endmodule

有限状态机.v:

module pg2(

    input wire clk,

input wire clr,

input wire [3:0] din,

output reg dout

    );

reg [2:0] pre_state,next_state;

parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100,S5=3'b101;

always@(posedge clk or posedge clr)

begin

if(clr==1)

pre_state <= S0;

else

pre_state <= next_state;

end



always@(*)

begin

case(pre_state)

S0:if(din[3]==1)

next_state <= S1;

else

next_state <= S0;

S1:if(din[0]==1)

next_state <= S2;

else

next_state <= S0;

S2:if(din[2]==1)

next_state <= S3;

else

next_state <= S0;

S3:if(din[2]==1)

next_state <= S4;

else

next_state <= S0;

S4:if(din[1]==1)

next_state <= S5;

else

next_state <= S0;

default:next_state <= S0;

endcase

end



always@(*)

begin

if(pre_state==S5)

dout <= 1;

else

dout <= 0;

end



endmodule

顶层文件.v:

module clk_top(

    input mclk,

input sw,

    input [3:0] btn,

    output led

    );



wire clr,clk190,clkp,btn01;

assign clr=sw;

assign btn01 = btn[0]|btn[1]|btn[2]|btn[3];

clk_div U1(.mclk(mclk),

.clr(clr),

.clk190(clk190)



);

clk_pause U2(.inp(btn01),

.cclk(clk190),

.clr(clr),

.outp(clkp)

);

pg2 U3(.clk(clkp),

.clr(clr),

.din(btn),

.dout(led)



);



endmodule

.ucf文件:

NET mclk LOC=D11;

NET led LOC=W3;

NET sw LOC=V5;

NET btn<0> LOC=E6;

NET btn<1> LOC=D5;

NET btn<2> LOC=A3;

NET btn<3> LOC=AB9;

实验结果截图如下:

上图为输入为30221的正确密码后,LED灯亮

六.实验总结

1.本实验的成功要点是要先对原始的100MHz的时钟进行分频和脉冲操作,这样就可以达到防抖的效果。

2.这次的实验可以用两种方法,一种是摩尔状态机,一种是米里状态机。两种方法都是没问题的,但是用不同的方法说对应的实验结果却有一些差异。前者若输入正确,LED则会一直亮着,直到下一个输入;而若后者输入正确,LED则会只闪一下就灭了。大家注意下这点就行了。

ps:这是最后一篇教程了,今天一下写完两篇,呼~~~心力憔悴啊

FPGA进阶教程四--有限状态机的Verilog实现(已完结)

FPGA进阶教程四--有限状态机的Verilog实现(已完结)

  -----2016.12.02

pps:当志愿者去了,待会再来更    ----2016.12.02

ppps:这两天的志愿者活动太忙了,每天早起晚归,一会宿舍倒床就睡,都没来的及更新。今天终于写完啦!----2016.12.05

由于笔者的知识和水平有限,文中不足之处在所难免,恳请各位读者赐正

---------------------------------------@weekdawn 版权所有------------------------------------------------

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值