目录
1. Simple FSM 1 (asynchronous reset)
2. Simple FSM 1 (synchronous reset)
3. Simple FSM 2 (asynchronous reset)
4. Simple FSM 2 (synchronous reset)
6. Simple one-hot state transitions 3
7. Simple FSM 3 (asynchronous reset)
8. Simple FSM 3 (synchronous reset)
16. PS/2 packet parser and datapath
18. Serial receiver and datapath
19. Serial receiver with parity checking
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
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
.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
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])∈
next_state[2] = state[1]∈
next_state[3] = state[2]∈
next_state[4] = state[3]∈
next_state[5] = state[4]∈
next_state[6] = state[5]∈
next_state[7] = state[6]&in|state[7]∈
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