【 FPGA 】序列检测器的Moore状态机实现

版权声明:本博客内容来自于个人学习过程中的总结,参考了互联网、数据手册、帮助文档、书本以及论文等上的内容,仅供学习交流使用,如有侵权,请联系,我会重写!转载请注明地址! https://blog.csdn.net/Reborn_Lee/article/details/85763185

设计一个序列检测器,检测序列1101,检测到输出1,否则输出0.

用状态机来实现序列检测器是非常合适的,下面先给出状态转移图,之后用Moore状态机来实现这个序列检测器:

图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

猜你喜欢

转载自blog.csdn.net/Reborn_Lee/article/details/85763185