【 FPGA 】序列检测器的Moore状态机实现
设计一个序列检测器,检测序列1101,检测到输出1,否则输出0.
用状态机来实现序列检测器是非常合适的,下面先给出状态转移图,之后用Moore状态机来实现这个序列检测器:
(注:此处所画为无重叠检测,有重叠检测只需要改变最后一个状态即可,例如本例里,有重叠检测,如果S4状态下输入为1,则需要转向S2状态,其他不变。)
图1:Moore状态机状态转移图
先给出行为仿真示意图,示例代码后面贴出:
可见,每经历一个1101,输出就会是一个高脉冲,持续一个周期,也即输出是一个1.
该状态机的Verilog HDL描述为:
-
`timescale 1ns / 1ps
-
-
// Company:
-
// Engineer:
-
//
-
// Create Date: 2019/01/04 11:16:29
-
// Design Name:
-
// Module Name: seq_det_moore
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
-
-
-
module seq_det_moore(
-
input clk,
-
input reset,
-
input din,
-
output reg dout
-
);
-
//状态声明
-
localparam [2:0]
-
s0 = 3'b000,
-
s1 = 3'b001,
-
s2 = 3'b010,
-
s3 = 3'b011,
-
s4 = 3'b100;
-
-
reg [2:0] current_state,next_state;
-
-
always @(posedge clk, posedge reset)
-
begin
-
if(reset)
-
current_state <= s0;
-
else
-
current_state <= next_state;
-
end
-
-
always @ *
-
begin
-
case(current_state)
-
s0:
-
if(din == 1'b1) next_state = s1;
-
else next_state = s0;
-
s1:
-
if(din == 1'b1) next_state = s2;
-
else next_state = s0;
-
s2:
-
if(din == 1'b0) next_state = s3;
-
else next_state = s2;
-
s3:
-
if(din == 1'b1) next_state = s4;
-
else next_state = s0;
-
s4:
-
if(din == 1'b1) next_state = s1;
-
else next_state = s0;
-
default: next_state = s0;
-
-
endcase
-
-
end
-
-
always @*
-
begin
-
if(current_state == s4) dout = 1;
-
else dout = 0;
-
end
-
-
-
endmodule
RTL电路:
行为仿真代码:
-
`timescale 1ns / 1ps
-
-
// Company:
-
// Engineer:
-
//
-
// Create Date: 2019/01/04 15:24:59
-
// Design Name:
-
// Module Name: seq_det_moore_tb
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
-
-
-
module seq_det_moore_tb;
-
reg clk,reset;
-
reg din;
-
wire dout;
-
reg [20:0] din_mid;
-
integer i;
-
-
// Note: CLK must be defined as a reg when using this method
-
-
parameter PERIOD = 10;
-
-
always begin
-
clk = 1'b0;
-
#(PERIOD/2) clk = 1'b1;
-
#(PERIOD/2);
-
end
-
-
initial begin
-
-
reset = 1'b1;
-
din_mid = 21'b110111010110100101101;
-
-
# 20
-
reset = 1'b0;
-
-
din = 1'b0;
-
for(i = 0;i < 21;i = i + 1)
-
begin
-
#PERIOD
-
din = din_mid[i];
-
end
-
-
end
-
-
seq_det_moore uu1(.clk(clk),.reset(reset),.din(din),.dout(dout));
-
-
-
endmodule
编写这个简单的程序,并非毫无意义的,包括这个Testbench文件,自己动手编写往往能发现一些小的细节问题,你可能并不懂,例如,在测试文件(testbench)中,我使用到了for循环,出现了如下问题,首先我尝试使用了generate for循环语法,可是Vivado软件总是报错!!!
之后,我直接使用for循环,可是变量i的类型是什么呢?
reg,real都不对,最后使用了integer才成功,这说明了什么问题,当然是基础知识不牢固导致的,基础知识为什么不牢固,往往是因为练习的不多,语法书读的次数再多,往往很枯燥无味,问题还是需要在实践中去寻找,Verilog语言很类似C,这导致我们往往很不情愿去仔仔细细地去学,稍微关注些可综合的语法,之后拿来就用。至今我仍不愿意去细看所有的语法。解决的办法就是实践。
第二个问题就是在测试文件中,定义了参数parameter PERIOD,可是后面为什么不能对此参数进行运算呢?例如我想延时2 * PERIOD,Vivado仍然报错。让我郁闷!
上述这些问题都出现在我的初次表写测试文件的代码中,这里给出错误的初稿代码:(供大家发现问题)
-
`timescale 1ns / 1ps
-
-
// Company:
-
// Engineer:
-
//
-
// Create Date: 2019/01/04 15:24:59
-
// Design Name:
-
// Module Name: seq_det_moore_tb
-
// Project Name:
-
// Target Devices:
-
// Tool Versions:
-
// Description:
-
//
-
// Dependencies:
-
//
-
// Revision:
-
// Revision 0.01 - File Created
-
// Additional Comments:
-
//
-
-
-
-
module seq_det_moore_tb;
-
reg clk,reset;
-
reg din;
-
wire dout;
-
reg [20:0] din_mid;
-
-
// Note: CLK must be defined as a reg when using this method
-
-
parameter PERIOD = 10;
-
-
always begin
-
clk = 1'b0;
-
#(PERIOD/2) clk = 1'b1;
-
#(PERIOD/2);
-
end
-
-
initial begin
-
-
reset = 1'b1;
-
din_mid = 21'b110111010110100101101;
-
-
#2*PERIOD
-
reset = 1'b0;
-
-
generate
-
genvar i;
-
for(i = 0;i < 21;i ++)
-
begin
-
#PERIOD
-
din = din_mid[i];
-
end
-
endgenerate
-
-
-
-
end
-
-
seq_det_moore uu1(.clk(clk),.reset(reset),.din(din),.dout(dout));
-
-
-
endmodule
-
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/85763185
- 点赞
- 收藏
- 关注作者
评论(0)