HDLBits 系列(8)——Sequential Logic(Finite State Machines(一))

目录

3.2 Sequential Logic

3.2.5 Finite State Machines

1. Simple FSM 1 (asynchronous reset)

2. Simple FSM 1 (synchronous reset)

3. Simple FSM 2 (asynchronous reset)

4. Simple FSM 2 (synchronous reset)

5. Simple state transitions 3

6. Simple one-hot state transitions 3

7. Simple FSM 3 (asynchronous reset)

8. Simple FSM 3 (synchronous reset)

9. Design a Moore FSM

10. Lemmings 1

11. Lemmings 2

12. Lemmings 3

13. Lemmings 4

14. One-hot FSM

15. PS/2 packet parser

16. PS/2 packet parser and datapath

17. Serial receiver

18. Serial receiver and datapath

19. Serial receiver with parity checking

20. Sequence recognition


3.2 Sequential Logic

3.2.5 Finite State Machines

1. Simple FSM 1 (asynchronous reset)

尽量用三段式状态机进行描述,一段组合电路确定状态转移的过程,一段时序电路给出复位状态和随时钟向next_state转移,一段组合电路或者assign语言输出各个状态下需要输出信号的值。

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  

    parameter A=0, B=1; 
    reg state, next_state;

    always @(*) begin    // This is a combinational always block
        // State transition logic
        case(state)
           A:begin
               if(in) next_state<=A;
               else   next_state<=B;
           end
           B:begin
               if(in) next_state<=B;
               else   next_state<=A;
           end
            default: next_state<=B;  
        endcase
        
    end

    always @(posedge clk, posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset)begin
            state<=B;
        end 
        else begin
            state<=next_state;
        end       
    end

    // Output logic
    // assign out = (state == ...);
    assign out=state;

endmodule

2. Simple FSM 1 (synchronous reset)

与上面一样,区别在于同步复位。

// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;//  
    reg out;

    // Fill in state name declarations
   // parameter A=0,B=1;

   parameter A=0, B=1; 
    reg state, next_state;
 
always @(posedge clk) begin    // This is a sequential always block
        // State flip-flops with synchronous reset
        if(reset) state <= B;
        else state <= next_state;
    end
 
    always @(*) begin    // This is a combinational always block
        // State transition logic
        case(state)
            B: begin
                if(in == 1) next_state = B;
                else next_state = A;
            end
            A: begin
                if(in == 1) next_state = A;
                else next_state = B;
            end
        endcase
    end
 
    // Output logic
    // assign out = (state == ...);
    assign out = (state == A)?0:1;

endmodule

3. Simple FSM 2 (asynchronous reset)

与上面基本一致,区别在于状态转移收到j、k的控制。

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
              OFF: begin
                  if(j) next_state<=ON;
                  else next_state<=OFF;
              end
              ON:begin
                  if(k) next_state<=OFF;
                  else  next_state<=ON;
              end
        endcase  
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)begin
            state<=OFF;
        end
        else begin
             state<=next_state;
        end
    end

    // Output logic
    // assign out = (state == ...);
     assign out=(state==OFF)?1'b0:1'b1;

endmodule

4. Simple FSM 2 (synchronous reset)

同步复位。

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            OFF: next_state<=j?ON:OFF;
            ON:  next_state<=k?OFF:ON;
        endcase
    end

    always @(posedge clk) begin
        // State flip-flops with synchronous reset
        if(reset)begin
            state<=OFF;
        end
        else begin
            state<=next_state;
        end
    end

    // Output logic
    // assign out = (state == ...);
    assign out = state == OFF?1'b0:1'b1;
endmodule

5. Simple state transitions 3

根据表格来确定状态转移。

module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: next_state = f(state, in)
    always @(*)begin
        case(state)
            A: next_state<=in?B:A;
            B: next_state<=in?B:C;
            C: next_state<=in?D:A;
            D: next_state<=in?B:C;
        endcase
    end
   
    // Output logic:  out = f(state) for a Moore state machine
    assign out=(state==D)?1'b1:1'b0;

endmodule

6. Simple one-hot state transitions 3

What does "derive equations by inspection" mean?

One-hot state machine encoding guarantees that exactly one state bit is 1. This means that it is possible to determine whether the state machine is in a particular state by examining only one state bit, not all state bits. This leads to simple logic equations for the state transitions by examining the incoming edges for each state in the state transition diagram.

For example, in the above state machine, how can the state machine can reach state A? It must use one of the two incoming edges: "Currently in state A and in=0" or "Currently in state C and in = 0". Due to the one-hot encoding, the logic equation to test for "currently in state A" is simply the state bit for state A. This leads to the final logic equation for the next state of state bit A: next_state[0] = state[0]&(~in) | state[2]&(~in). The one-hot encoding guarantees that at most one clause (product term) will be "active" at a time, so the clauses can just be ORed together.

When an exercise asks for state transition equations "by inspection", use this particular method. The judge will test with non-one-hot inputs to ensure your logic equations follow this method, rather that doing something else (such as resetting the FSM) for illegal (non-one-hot) combinations of the state bits.

Although knowing this algorithm isn't necessary for RTL-level design (the logic synthesizer handles this), it is illustrative of why one-hot FSMs often have simpler logic (at the expense of more state bit storage), and this topic frequently shows up on exams in digital logic courses.

根据状态转移结果进行反推,确定此状态是怎么来的,不同路径的或就是此状态转移而来的组合。

module top_module(
    input in,
    input [3:0] state,
    output [3:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: Derive an equation for each state flip-flop.
    assign next_state[A] =(state[A]&&in==1'b0)|(state[C]&&in==1'b0);
    assign next_state[B] =(state[A]&&in==1'b1)|(state[B]&&in==1'b1)|(state[D]&&in==1'b1);
    assign next_state[C] =(state[B]&&in==1'b0)|(state[D]&&in==1'b0);
    assign next_state[D] =(state[C]&&in==1'b1);

    // Output logic: 
    assign out = (state[D])?1'b1:1'b0;

endmodule

7. Simple FSM 3 (asynchronous reset)

异步复位:

module top_module(
    input clk,
    input in,
    input areset,
    output out); //
    parameter A=4'b0001,B=4'b0010,C=4'b0100,D=4'b1000;
    reg [3:0] state,next_state;
    // State transition logic
    always @(*)begin
        case(state)
            A:next_state<=in?B:A;
            B:next_state<=in?B:C;
            C:next_state<=in?D:A;
            D:next_state<=in?B:C;
            default: next_state<=A;
        endcase
    end

    // State flip-flops with asynchronous reset
    always @(posedge clk or posedge areset)begin
        if(areset)begin
            state<=A;
        end
        else begin
            state<=next_state;
        end
    end
    // Output logic
    assign out=(state==D)?1'b1:1'b0;

endmodule

8. Simple FSM 3 (synchronous reset)

与上面的区别仅仅是同步复位而已。

module top_module(
    input clk,
    input in,
    input reset,
    output out); //

    parameter A=4'b0001,B=4'b0010,C=4'b0100,D=4'b1000;
    reg [3:0] state,next_state;
    // State transition logic
    always @(*)begin
        case(state)
            A:next_state<=in?B:A;
            B:next_state<=in?B:C;
            C:next_state<=in?D:A;
            D:next_state<=in?B:C;
            default: next_state<=A;
        endcase
    end

    // State flip-flops with synchronous reset
    always @(posedge clk)begin
        if(reset)begin
            state<=A;
        end
        else begin
            state<=next_state;
        end
    end
    // Output logic
    assign out=(state==D);

endmodule

9. Design a Moore FSM

画出状态转移图,注意△FR为1的条件:S1或者由高向低转移的时候。

module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output dfr
); 
    parameter S1=2'b00,S1S2=2'b01,S2S3=2'b10,S3=2'b11;
    reg [1:0]state,next_state,state_last;
    
    always @(*)begin
        case(state)
            S1:begin
                if(s[1]) next_state=S1S2;
                else next_state=S1;
            end
            S1S2:begin
                if(~s[1]) next_state=S1;      //s[1]=0
                else begin
                    if(s[2]) next_state=S2S3; //s[1]=1,s[2]=1
                    else       next_state=S1S2; //s[1]=1,s[2]=0
                end
            end
            S2S3:begin
                if(~s[2]) next_state=S1S2;
                else begin
                    if(s[3]) next_state=S3;
                    else       next_state=S2S3;
                end
            end
            S3:begin
                if(~s[3]) next_state=S2S3;
                else  next_state=S3;
            end
        endcase
    end
    always @(posedge clk)begin
        if(reset)begin
            state<=S1;
        	state_last<=S1;
        end
        else begin
            state<=next_state;
            state_last<=state;
        end
    end
    
    assign fr3=(state==S1);
    assign fr2=(state==S1)|(state==S1S2);
    assign fr1=(state==S1)|(state==S1S2)|(state==S2S3);
    
    always @(*) begin
        if(state == S1)
             dfr = 1'b1;
        else if(state_last > state)
             dfr = 1'b1;
         else if(state_last < state)
             dfr = 1'b0;
        else
             dfr = dfr;         
    end  
    
 //  以下为错误答案,没有考虑其他状态保持不变化和为零的情况
//assign dfr=(state==S1)|(state_last==S2S3&&state==S1S2)|(state_last==S3&&state==S2S3);

endmodule

10. Lemmings 1

The game Lemmings involves critters with fairly simple brains. So simple that we are going to model it using a finite state machine.

In the Lemmings' 2D world, Lemmings can be in one of two states: walking left or walking right. It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left, it will walk right. If it's bumped on the right, it will walk left. If it's bumped on both sides at the same time, it will still switch directions.

Implement a Moore state machine with two states, two inputs, and one output that models this behaviour.

画出状态转移图:

 参考官方的标准答案:

module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	output walk_left,
	output walk_right
);

	// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
	// It doesn't really matter what assignment is used, as long as they're unique.
	parameter WL=0, WR=1;
	reg state;
	reg next;
    
    
    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always@(*) begin
		case (state)
			WL: next = bump_left  ? WR : WL;
			WR: next = bump_right ? WL : WR;
		endcase
    end
    
    
    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always @(posedge clk, posedge areset) begin
		if (areset) state <= WL;
        else state <= next;
	end
		
		
	// Combinational output logic. In this problem, an assign statement are the simplest.
	// In more complex circuits, a combinational always block may be more suitable.		
	assign walk_left = (state==WL);
	assign walk_right = (state==WR);

	
endmodule

11. Lemmings 2

Lemmings2.gif

In addition to walking left and right, Lemmings will fall (and presumably go "aaah!") if the ground disappears underneath them.

In addition to walking left and right and changing direction when bumped, when ground=0, the Lemming will fall and say "aaah!". When the ground reappears (ground=1), the Lemming will resume walking in the same direction as before the fall. Being bumped while falling does not affect the walking direction, and being bumped in the same cycle as ground disappears (but not yet falling), or when the ground reappears while still falling, also does not affect the walking direction.

时序图: 

 状态转移图:

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    output walk_left,
    output walk_right,
    output aaah ); 
	
    parameter LEFT=0,RIGHT=1,FALL_L=2,FALL_R=3;
    reg [1:0] state,next_state;
    
    always @(*)begin
        case (state)
            LEFT:begin
                if(ground) next_state=bump_left?RIGHT:LEFT;
                else       next_state=FALL_L;
            end
            RIGHT:begin
                if(ground) next_state=bump_right?LEFT:RIGHT;
                else       next_state=FALL_R;
            end
            FALL_L:begin
                if(ground) next_state=LEFT;
                else       next_state=FALL_L;
            end
            FALL_R:begin
                if(ground) next_state=RIGHT;
                else       next_state=FALL_R;
            end
        endcase               
    end
    
    always @(posedge clk or posedge areset)begin
        if(areset) state<=LEFT;
        else state<=next_state;
    end
    
    assign walk_left=(state==LEFT);
    assign walk_right=(state==RIGHT);
    assign aaah=(state==FALL_L | state==FALL_R);
     
endmodule

12. Lemmings 3

Lemmings3.gif

.In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored.

(In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)

Extend your finite state machine to model this behaviour.

对于状态机的题,只要把状态机画出来,剩下的工作就是三段式机械的写出来就好了,完全是体力活。

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 
    
    parameter LEFT=0,RIGHT=1,FALL_L=2,FALL_R=3,DIGGING_L=4,DIGGING_R=5;
    reg [2:0] state,next_state;
    
    always @(*)begin
        case (state)
            LEFT:begin
                if(ground) begin
                    if(dig) next_state=DIGGING_L;
                    else  next_state=bump_left?RIGHT:LEFT;
                end
                else   next_state=FALL_L;
            end
            RIGHT:begin
                if(ground) begin
                    if(dig) next_state=DIGGING_R;
                    else    next_state=bump_right?LEFT:RIGHT;
                end
                else       next_state=FALL_R;
            end
            FALL_L:begin
                if(ground) next_state=LEFT;
                else       next_state=FALL_L;
            end
            FALL_R:begin
                if(ground) next_state=RIGHT;
                else       next_state=FALL_R;
            end
            DIGGING_L:begin
                if(ground) next_state=DIGGING_L;
                else       next_state=FALL_L;
            end
            DIGGING_R:begin
                if(ground) next_state=DIGGING_R;
                else       next_state=FALL_R;
            end 
            default: next_state=LEFT;
            
        endcase               
    end
    
    always @(posedge clk or posedge areset)begin
        if(areset) state<=LEFT;
        else state<=next_state;
    end
    
    assign walk_left=(state==LEFT);
    assign walk_right=(state==RIGHT);
    assign aaah=(state==FALL_L | state==FALL_R);
    assign digging=(state==DIGGING_R |state==DIGGING_L);

endmodule

13. Lemmings 4

Lemmings4.gif

Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.

Extend your finite state machine to model this behaviour.

 

module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 
    
    parameter LEFT=0,RIGHT=1,FALL_L=2,FALL_R=3,DIGGING_L=4,DIGGING_R=5,SPLATTER=6;
    reg [2:0] state,next_state;
    reg [7:0] fall_cnt_20;
    
    always @(*)begin
        case (state)
            LEFT:begin
                if(ground) begin
                    if(dig) next_state=DIGGING_L;
                    else  next_state=bump_left?RIGHT:LEFT;
                end
                else   next_state=FALL_L;
            end
            RIGHT:begin
                if(ground) begin
                    if(dig) next_state=DIGGING_R;
                    else    next_state=bump_right?LEFT:RIGHT;
                end
                else       next_state=FALL_R;
            end
            FALL_L:begin
                if(~ground) next_state=FALL_L; 
                else begin
                    if(fall_cnt_20>5'd20) next_state=SPLATTER;
                    else  next_state=LEFT;
                end 
            end
            FALL_R:begin
                if(~ground) next_state=FALL_R;
               else begin
                    if(fall_cnt_20>'d20) next_state=SPLATTER;
                    else  next_state=RIGHT;
                end              
            end
            DIGGING_L:begin
                if(ground) next_state=DIGGING_L;
                else       next_state=FALL_L;
            end
            DIGGING_R:begin
                if(ground) next_state=DIGGING_R;
                else       next_state=FALL_R;
            end 
            SPLATTER: next_state=SPLATTER;
            default: ; 
        endcase               
    end
    always @(posedge clk or posedge areset)begin
        if(areset) state<=LEFT;
        else state<=next_state;
    end
    
    always @(posedge clk)begin
        if(areset)
            fall_cnt_20<='d0;
        else begin
            if(~ground)
            fall_cnt_20 <=fall_cnt_20+1'b1;
            else 
            fall_cnt_20<='d0;
        end
    end
    
    assign walk_left=(state==LEFT);
    assign walk_right=(state==RIGHT);
    assign aaah=(state==FALL_L | state==FALL_R);
    assign digging=(state==DIGGING_L | state==DIGGING_R);
        
endmodule

14. One-hot FSM

Suppose this state machine uses one-hot encoding, where state[0] through state[9] correspond to the states S0 though S9, respectively. The outputs are zero unless otherwise specified.

Implement the state transition logic and output logic portions of the state machine (but not the state flip-flops). You are given the current state in state[9:0] and must produce next_state[9:0] and the two outputs. Derive the logic equations by inspection assuming a one-hot encoding. (The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).

根据结果反推来源,即根据next_state反过来写出next_state 怎么由state得出。

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    
    always@(*)begin
        next_state[0] = (state[0]|state[1]|state[2]|state[3]|state[4]|state[7]|state[8]|state[9])&(~in);
        next_state[1] = (state[0]|state[8]|state[9])&in;
        next_state[2] = state[1]&in;
        next_state[3] = state[2]&in;
        next_state[4] = state[3]&in;
        next_state[5] = state[4]&in;
        next_state[6] = state[5]&in;
        next_state[7] = state[6]&in|state[7]&in;
        next_state[8] = state[5]&~in;
        next_state[9] = state[6]&~in;
    end
    
    assign out1 = state[8]|state[9];
    assign out2 = state[7]|state[9];
    

endmodule

15. PS/2 packet parser

The PS/2 mouse protocol sends messages that are three bytes long. However, within a continuous byte stream, it's not obvious where messages start and end. The only indication is that the first byte of each three byte message always has bit[3]=1 (but bit[3] of the other two bytes may be 1 or 0 depending on data).

We want a finite state machine that will search for message boundaries when given an input byte stream. The algorithm we'll use is to discard bytes until we see one with bit[3]=1. We then assume that this is byte 1 of a message, and signal the receipt of a message once all 3 bytes have been received (done).

The FSM should signal done in the cycle immediately after the third byte of each message was successfully received.

画出状态流程图:

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
   localparam D1=0,D2=1,D3=2,DONE=3;
    reg [1:0] state,next_state;
    
        
    // State transition logic (combinational)
   always @(*)begin
       case(state)
           D1:begin
               if(in[3]) next_state=D2;
               else next_state=D1;
           end
           D2:next_state=D3;
           D3:next_state=DONE;
           DONE:begin
               if(in[3]) next_state=D2;
               else next_state=D1;
           end
          default:next_state=D1;
       endcase
   end
    // State flip-flops (sequential)
       always @(posedge clk)begin
           if(reset) state<=D1;
           else state<=next_state;
       end
       
    // Output logic
     assign done=(state==DONE);
endmodule

16. PS/2 packet parser and datapath

Now that you have a state machine that will identify three-byte messages in a PS/2 byte stream, add a datapath that will also output the 24-bit (3 byte) message whenever a packet is received (out_bytes[23:16] is the first byte, out_bytes[15:8] is the second byte, etc.).

out_bytes needs to be valid whenever the done signal is asserted. You may output anything at other times (i.e., don't-care).

For example:

在上题的基础上,接收done信号的时候输出接收的数据,先接收高位,后接收低位。

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //
    
    parameter D0=0,D1=1,D2=2,DONE=3;
    reg [1:0] state,next_state;
    reg [7:0] data_temp1,data_temp2,data_temp3;
    
    // FSM from fsm_ps2
    always @(*)begin
        case(state)
            D0:next_state<=in[3]?D1:D0;
            D1:next_state<=D2;
            D2:next_state<=DONE;
            DONE:next_state<=in[3]?D1:D0;
            default:next_state<=D0;
        endcase
    end
    always @(posedge clk)begin
            if(reset) state<=D0;
            else state<=next_state;
   end
        
    // New: Datapath to store incoming bytes.
    assign done=(state==DONE);
    always @(posedge clk)begin
        if(reset)begin
            data_temp1<='d0;
            data_temp2<='d0;
            data_temp3<='d0;
        end
        else begin
            case(next_state)
              D1:data_temp1<=in;
              D2:data_temp2<=in;
              DONE:data_temp3<=in; 
            endcase
        end
    end
    
    assign out_bytes={data_temp1,data_temp2,data_temp3};
endmodule

17. Serial receiver

In many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle).

Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    
    parameter START=0,B1=1,B2=2,B3=3,B4=4,B5=5,B6=6,B7=7,B8=8,STOP=9,DONE0=10,DONE1=11;
    reg [3:0] state,next_state;
    always @(*)begin
        case(state)
            START:begin
                if(~in) next_state=B1;
                else    next_state=START;
            end
            B1:next_state=B2;
            B2:next_state=B3;
            B3:next_state=B4;
            B4:next_state=B5;
            B5:next_state=B6;
            B6:next_state=B7;
            B7:next_state=B8;
            B8:next_state=STOP;
            STOP:begin
                if(in) next_state<=DONE0;
                else next_state<=DONE1;
            end
            DONE0:begin
                if(in) next_state<=START;
                else   next_state<=B1;
            end
            DONE1:begin
                if(in) next_state<=START;
                else   next_state<=DONE1;
            end
            default:next_state<=START;
        endcase
    end
    always @(posedge clk)begin
        if(reset) state<=START;
        else state<=next_state;
    end
    assign done=(state==DONE0);
    

endmodule

18. Serial receiver and datapath

Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don't-care otherwise.

Note that the serial protocol sends the least significant bit first.

状态转移与上题基本一样,注意接收数据先接收低位(最没有意义的位least significant bit first.

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

     parameter START=0,B1=1,B2=2,B3=3,B4=4,B5=5,B6=6,B7=7,B8=8,STOP=9,DONE0=10,DONE1=11;
    reg [3:0] state,next_state;
    reg [7:0]data_temp;
    always @(*)begin
        case(state)
            START:begin
                if(~in) next_state=B1;
                else    next_state=START;
            end
            B1:next_state=B2;
            B2:next_state=B3;
            B3:next_state=B4;
            B4:next_state=B5;
            B5:next_state=B6;
            B6:next_state=B7;
            B7:next_state=B8;
            B8:next_state=STOP;
            STOP:begin
                if(in) next_state<=DONE0;
                else next_state<=DONE1;
            end
            DONE0:begin
                if(in) next_state<=START;
                else   next_state<=B1;
            end
            DONE1:begin
                if(in) next_state<=START;
                else   next_state<=DONE1;
            end
            default:next_state<=START;
        endcase
    end
    always @(posedge clk)begin
        if(reset) state<=START;
        else state<=next_state;
    end
    assign done=(state==DONE0);
    always @(posedge clk)begin
        if(reset)begin
            data_temp<='d0;
        end
        else begin
            case(next_state)
                B2:data_temp[0]=in;
                B3:data_temp[1]=in;
                B4:data_temp[2]=in;
                B5:data_temp[3]=in;
                B6:data_temp[4]=in;
                B7:data_temp[5]=in;
                B8:data_temp[6]=in;
                STOP:data_temp[7]=in;
            endcase
        end
    end
    
   // assign out_byte=(state==DONE0)?data_temp:out_byte;
   assign out_byte=data_temp;
endmodule

19. Serial receiver with parity checking

We want to add parity checking to the serial receiver. Parity checking adds one extra bit after each data byte. We will use odd parity, where the number of 1s in the 9 bits received must be odd. For example, 101001011 satisfies odd parity (there are 5 1s), but 001001011 does not.

Change your FSM and datapath to perform odd parity checking. Assert the done signal only if a byte is correctly received and its parity check passes. Like the serial receiver FSM, this FSM needs to identify the start bit, wait for all 9 (data and parity) bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

You are provided with the following module that can be used to calculate the parity of the input stream (It's a TFF with reset). The intended use is that it should be given the input bit stream, and reset at appropriate times so it counts the number of 1 bits in each byte.

module parity (
    input clk,
    input reset,
    input in,
    output reg odd);

    always @(posedge clk)
        if (reset) odd <= 0;
        else if (in) odd <= ~odd;

endmodule

Note that the serial protocol sends the least significant bit first, and the parity bit after the 8 data bits.

在上面题的基础上增加了奇偶校验,校验通过并且in=1才能进行done0状态。校验不通过进入wait状态,知道再次重新开始接收。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

     parameter START=0,B1=1,B2=2,B3=3,B4=4,B5=5,B6=6,B7=7,B8=8,B9=9,STOP=10,DONE0=11,DONE1=12,WAITTING=13;
    reg [3:0] state,next_state;
    reg [7:0] data_temp;
    reg      odd_flag;
    always @(*)begin
        case(state)
            START:begin
                if(~in) next_state=B1;
                else    next_state=START;
            end
            B1:begin
                next_state=B2;
                data_temp[0]=in;
            end    
            B2:begin
                next_state=B3;
                data_temp[1]=in;
            end
            B3:begin
                next_state=B4;
                data_temp[2]=in;
            end
            B4:begin
                next_state=B5;
                data_temp[3]=in;
            end
            B5:begin
                next_state=B6;
                data_temp[4]=in;
            end
            B6:begin
                next_state=B7;
                data_temp[5]=in;
            end
            B7:begin
                next_state=B8;
                data_temp[6]=in;
            end
            B8:begin
                next_state=B9;
                data_temp[7]=in;
            end
            B9:begin
                next_state=STOP;
                odd_flag=^data_temp^in;  //奇偶校验计算方法
            end
            STOP:begin
                if(odd_flag && in) next_state=DONE0;
                else if(~odd_flag && in) next_state=WAITTING;
                else next_state=DONE1;
            end
            DONE0:begin
                if(in) next_state=START;
                else   next_state=B1;
            end
            DONE1:begin
                if(in) next_state=START;
                else   next_state=DONE1;
            end
            WAITTING: begin
                if(in) next_state=WAITTING;
                else next_state=B1;
            end
            default:next_state<=START;
        endcase
    end
    always @(posedge clk)begin
        if(reset) state<=START;
        else state<=next_state;
    end
    assign done=(state==DONE0);
    assign out_byte=done?data_temp:8'd0;

endmodule

20. Sequence recognition

Synchronous HDLC framing involves decoding a continuous bit stream of data to look for bit patterns that indicate the beginning and end of frames (packets). Seeing exactly 6 consecutive 1s (i.e., 01111110) is a "flag" that indicate frame boundaries. To avoid the data stream from accidentally containing "flags", the sender inserts a zero after every 5 consecutive 1s which the receiver must detect and discard. We also need to signal an error if there are 7 or more consecutive 1s.

Create a finite state machine to recognize these three sequences:

  • 0111110: Signal a bit needs to be discarded (disc).
  • 01111110: Flag the beginning/end of a frame (flag).
  • 01111111...: Error (7 or more 1s) (err).

When the FSM is reset, it should be in a state that behaves as though the previous input were 0.

Here are some example sequences that illustrate the desired operation.

 

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
     parameter S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4, S5 = 4'd5,
    S6 = 4'd6, S7 = 4'd7, DISC = 4'd8, ERR = 4'd9, FLAG = 4'd10;
    
    reg	[3:0]	state;
    reg [3:0]	next_state; 
    always@(*)begin
        case(state)
            S1:begin
                next_state = in ? S2 : S1;
            end
            S2:begin
                next_state = in ? S3 : S1;
            end
            S3:begin
                next_state = in ? S4 : S1;
            end
            S4:begin
                next_state = in ? S5 : S1;
            end
            S5:begin
                next_state = in ? S6 : S1;
            end
            S6:begin
                next_state = in ? S7 : DISC;
            end
            S7:begin
                next_state = in ? ERR : FLAG;
            end
            DISC:begin
                next_state = in ? S2 : S1;
            end
            ERR:begin
                next_state = in ? ERR : S1;
            end
            FLAG:begin
                next_state = in ? S2 : S1;
            end
            default:begin
                next_state = S1;
            end
        endcase
    end
       
    always@(posedge clk)begin
        if(reset)
            state <= S1;
        else 
            state <= next_state;
    end
    
    
    
    assign disc = (state == DISC);
    assign err = (state == ERR);
    assign flag = (state == FLAG);

endmodule
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bronceyang131

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值