【小罗的hdlbits刷题笔记5】基于fifo思想的fsm设计(Exams/2014 q3fsm)

在写状态机时,经常会有检测输入信号波形的情况,这种情况下,如果采用三段式状态机书写,则需要通过穷举法把输入信号所有可能存在的情况书写出来,在检测一到两个周期的输入信号时工作量不会很大,但是在检测多于三个信号时,工作量将会几何倍数增长,空说的话会很抽象,不如参考下这个例子:

Consider a finite state machine with inputs s and w. Assume that the FSM begins in a reset state called A, as depicted below. The FSM remains in state A as long as s = 0, and it moves to state B when s = 1. Once in state B the FSM examines the value of the input w in the next three clock cycles. If w = 1 in exactly two of these clock cycles, then the FSM has to set an output z to 1 in the following clock cycle. Otherwise z has to be 0. The FSM continues checking w for the next three clock cycles, and so on. The timing diagram below illustrates the required values of z for different values of w.
Use as few states as possible. Note that the s input is used only in state A, so you need to consider just the w input.
翻译:考虑一个有输入s和w的有限状态机。假设FSM以一种称为a的复位状态开始,如下所示。当s = 0时,FSM一直处于状态A;当s = 1时,FSM进入状态B。一旦进入状态B, FSM在接下来的三个时钟周期内检查输入的w的值。如果在两个时钟周期中w = 1,那么FSM必须在接下来的时钟周期中设置输出z为1。否则z等于0。FSM继续检查w,以确定接下来的三个时钟周期,以此类推。下面的时序图说明了不同w值所需要的z值。
使用尽可能少的州。注意,s输入只在状态A中使用,所以你只需要考虑w输入。【小罗的hdlbits刷题笔记5】基于fifo思想的fsm设计(Exams/2014 q3fsm)_第1张图片
图1.最终结果的波形
【小罗的hdlbits刷题笔记5】基于fifo思想的fsm设计(Exams/2014 q3fsm)_第2张图片图2.状态机示意图

如果采用最广泛的三段式状态机,则需要穷举出所有的状态,如下所示:
【小罗的hdlbits刷题笔记5】基于fifo思想的fsm设计(Exams/2014 q3fsm)_第3张图片
我已经看的头大了,如果你说我就是要写三段式状态机,就是玩,那我也没辙了,当然还有更好的方法,就是借鉴fifo的思路,搭建一个建议的先进先出的小模块来装载这三个时钟周期的w信号,fifo的原理简单的说来就是下面这张图:
【小罗的hdlbits刷题笔记5】基于fifo思想的fsm设计(Exams/2014 q3fsm)_第4张图片
比较爽的是,这个fifo不需要读指针,写指针,只需要其中的两个数据为1即可输出为1,因此在这个小模块的基础上,加上一个计数变量,每三个时钟周期置零一次,从而完成检查波形,其完整的代码如下所示:

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);

	localparam  A  = 1'b0,
			    B  = 1'b1;	
	reg [1:0] state,next_state;
	reg [2:0] data;
	reg [1:0] cnt;
	
	always@(posedge clk)begin
		if(reset)
			state <= A;
		else 
			state <= next_state; 
	end
	
	always@(*)begin
		case (state)
			A: next_state = s?B:A;
			B: next_state = B;
        endcase
	end
	
	always@(posedge clk)begin
		if(reset)
		data <= 3'b0;
		else case (next_state)		
		A: data <= 3'b0;
		B: begin
				data[0] <= w;
				data[1] <= data[0];
				data[2] <= data[1];		//	loop assignment	
		   end	
        endcase
	end
	
	always@(posedge clk)begin
		if(reset)
			cnt <= 2'h0;
		else if(state == A)
			cnt <= 2'h0;
		else if(cnt==2'h3&&(state == B))
			cnt <= 2'h1;
		else 
			cnt <= cnt+2'h1;
	end
	
	assign z = ((data==3'b011)|(data==3'b101)|(data==3'b110))&&(cnt==2'h3);  
	
endmodule

你可能感兴趣的:(小罗的刷题日记,状态机,fpga,verilog)