This is a Moore state machine with two states, one input, and one output. Implement this state machine. Notice that the reset state is B.
Using asynchronous reset.
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
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
endcase
// State transition logic
end
always @(posedge clk, posedge areset) begin // This is a sequential always block
if(areset)
state<=B;
else
state<=next_state;// State flip-flops with asynchronous reset
end
// Output logic
assign out=(state)?1'b1:1'b0;
// assign out = (state == ...);
endmodule
This is a Moore state machine with two states, one input, and one output. Implement this state machine. Notice that the reset state is B.
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;
reg present_state, next_state
always @(posedge clk) begin
if (reset)
present_state<=B;
else
present_state<=next_state;
end
always @(*) begin
case(present_state)
A :
if(in)
next_state <= A;
else
next_state <= B;
B :
if(in)
next_state <= B;
else
next_state <= A;
default: ;
endcase
end
assign out=(present_state)?1'b1:1'b0;
endmodule
This is a Moore state machine with two states, two inputs, and one output. Implement this state machine.
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
case(state)
OFF:begin
if(j)
next_state<=ON;
else
next_state<=OFF;
end// State transition logic
ON:begin
if(k)
next_state<=OFF;
else
next_state<=ON;
end
default: ;
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)
state<=OFF;
else
state<=next_state;// State flip-flops with asynchronous reset
end
// Output logic
assign out=(state==ON);
// assign out = (state == ...);
endmodule
This is a Moore state machine with two states, two inputs, and one output. Implement this state machine.
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
case(state)
OFF:begin
if(j == 0)
next_state <= OFF;
else
next_state <= ON;
end
ON:begin
if(k == 0)
next_state <= ON;
else
next_state <= OFF;
end
endcase
end
always @(posedge clk) begin
if(reset)
state <= OFF;
else
state <= next_state;// State flip-flops with synchronous reset
end
// Output logic
assign out=(state==ON);
// assign out = (state == ...);
endmodule
The following is the state transition table for a Moore state machine with one input, one output, and four states. Use the following state encoding: A=2'b00, B=2'b01, C=2'b10, D=2'b11.
Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. Given the current state (state
), compute the next_state
and output (out
) based on the state transition table.
State | Next state | Output | |
---|---|---|---|
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
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;
always @(*) begin
case(state)
A:begin
if(in==0)begin
next_state <= A;
end
else begin
next_state <= B;
end
end
B:begin
if(in==0)begin
next_state <= C;
end
else begin
next_state <= B;
end
end
C:begin
if(in==0)begin
next_state <= A;
end
else begin
next_state <= D;
end
end
D:begin
if(in==0)begin
next_state <= C;
end
else begin
next_state <= B;
end
end
endcase
end
// State transition logic: next_state = f(state, in)
assign out=(state==D);
// Output logic: out = f(state) for a Moore state machine
endmodule
The following is the state transition table for a Moore state machine with one input, one output, and four states. Use the following one-hot state encoding: A=4'b0001, B=4'b0010, C=4'b0100, D=4'b1000.
Derive state transition and output logic equations by inspection assuming a one-hot encoding. Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. (The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).
State | Next state | Output | |
---|---|---|---|
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
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) | (state[C] & ~in);
assign next_state[B] = (state[A]&in) | (state[D]&in) | (state[B]&in);
assign next_state[C] = (state[B]&~in) | (state[D]&~in);
assign next_state[D] = (state[C]&in);
// Output logic:
assign out = (state[D]);
endmodule
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.
本题中作者想让我们以one-hot(独热码)的编码逻辑来完成。一般状态机为了方便编码都是设置为二进制;但若状态转移是按顺序进行转移的话,我们可以使用格雷码,因为两相邻状态之间只变化1bit,这样可以节约功耗;若想提升速度,可以使用one-hot编码,因为每次仅需判断一位,这是用寄存器资源换组合逻辑资源,以达到更高的速度
The following is the state transition table for a Moore state machine with one input, one output, and four states. Implement this state machine. Include an asynchronous reset that resets the FSM to state A.
State | Next state | Output | |
---|---|---|---|
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
module top_module(
input clk,
input in,
input areset,
output out); //
parameter A=0,B=1,C=2,D=3;
reg [1:0] state,next_state;
// State transition logic
always @(*)begin
case(state)
A:begin
if(in==0)
next_state<=A;
else
next_state<=B;
end
B:begin
if(in==0)
next_state<=C;
else
next_state<=B;
end
C:begin
if(in==0)
next_state<=A;
else
next_state<=D;
end
D:begin
if(in==0)
next_state<=C;
else
next_state<=B;
end
endcase
end
// State flip-flops with asynchronous reset
always @(posedge clk,posedge areset)begin
if(areset)
state<=A;
else
state<=next_state;
end
assign out=(state==D);
// Output logic
endmodule
The following is the state transition table for a Moore state machine with one input, one output, and four states. Implement this state machine. Include a synchronous reset that resets the FSM to state A.
State | Next state | Output | |
---|---|---|---|
in=0 | in=1 | ||
A | A | B | 0 |
B | C | B | 0 |
C | A | D | 0 |
D | C | B | 1 |
module top_module(
input clk,
input in,
input reset,
output out); //
parameter A=0,B=1,C=2,D=3;
reg [1:0] current_state,next_state;
// State transition logic
always@(*)begin
case(in)
1'b0:
case(current_state)
A:next_state<=A;
B:next_state<=C;
C:next_state<=A;
D:next_state<=C;
default : ;
endcase
1'b1:
case(current_state)
A:next_state<=B;
B:next_state<=B;
C:next_state<=D;
D:next_state<=B;
default : ;
endcase
endcase
end
// State flip-flops with synchronous reset
always@(posedge clk)begin
if(reset)
current_state<=A;
else
current_state<=next_state;
end
// Output logic
assign out=(current_state==D);
endmodule
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
parameter A2=3'd0,B1=3'd1,B2=3'd2,C1=3'd3,C2=3'd4,D1=3'd5;
reg [2:0] state,next_state;
always @(*)begin
case(state)
A2:{fr3,fr2,fr1,dfr} = 4'b1111;
B1:{fr3,fr2,fr1,dfr} = 4'b0110;
B2:{fr3,fr2,fr1,dfr} = 4'b0111;
C1:{fr3,fr2,fr1,dfr} = 4'b0010;
C2:{fr3,fr2,fr1,dfr} = 4'b0011;
D1:{fr3,fr2,fr1,dfr} = 4'b0000;
default:{fr3,fr2,fr1,dfr} = 'x;
endcase
end
always @(*)begin
case(state)
A2:next_state <= s[1]?B1:A2;
B1:next_state <= s[2]?C1:(s[1]?B1:A2);
B2:next_state <= s[2]?C1:(s[1]?B2:A2);
C1:next_state <= s[3]?D1:(s[2]?C1:B2);
C2:next_state <= s[3]?D1:(s[2]?C2:B2);
D1:next_state <= s[3]?D1:C2;
default:next_state <= 'x;
endcase
end
always @(posedge clk)begin
if(reset)begin
state <= A2;
end
else begin
state <= next_state;
end
end
endmodule
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, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
parameter LEFT=0, RIGHT=1;
// parameter LEFT=0, RIGHT=1, ...
reg state, next_state;
wire [1:0] bump;
assign bump={bump_left,bump_right};
always @(*) begin
case(state)
LEFT:begin
if((bump==2'b10)||(bump==2'b11))
next_state<=RIGHT;
else
next_state<=LEFT;
end// State transition logic
RIGHT:begin
if((bump==2'b01)||(bump==2'b11))
next_state<=LEFT;
else
next_state<=RIGHT;
end
endcase
end
always @(posedge clk, posedge areset) begin
if(areset)
state<=LEFT;
else
state<=next_state;// State flip-flops with asynchronous reset
end
// Output logic
assign walk_left=(state==LEFT);
assign walk_right=(state==RIGHT);
// assign walk_left = (state == ...);
// assign walk_right = (state == ...);
endmodule
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.
Build a finite state machine that models this behaviour.
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=2'b0;
parameter RIGHT=2'b1;
parameter AH_LEFT=2'b10;
parameter AH_RIGHT=2'b11;
reg [1:0] state,next_state;
wire [1:0] bump;
assign bump={bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground==1'b0)begin
next_state<=AH_LEFT;
end
else if((bump==2'b10)||(bump==2'b11))begin
next_state<=RIGHT;
end
else begin
next_state<=LEFT;
end
end
RIGHT:begin
if(ground==1'b0)begin
next_state<=AH_RIGHT;
end
else if((bump==2'b01)||(bump==2'b11))begin
next_state<=LEFT;
end
else begin
next_state<=RIGHT;
end
end
AH_LEFT:begin
if(ground==1'b0)begin
next_state<=AH_LEFT;
end
else begin
next_state<=LEFT;
end
end
AH_RIGHT:begin
if(ground==1'b0)begin
next_state<=AH_RIGHT;
end
else begin
next_state<=RIGHT;
end
end
endcase
end
always@(posedge clk,posedge areset)begin
if(areset)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
assign walk_left=(state==LEFT);
assign walk_right=(state==RIGHT);
assign aaah=((state==AH_LEFT)|(state==AH_RIGHT));
endmodule
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=3'b0;
parameter RIGHT=3'b1;
parameter DIG_LEFT=3'b10;
parameter DIG_RIGHT=3'b11;
parameter FALL_LEFT=3'b100;
parameter FALL_RIGHT=3'b101;
reg [2:0] state,next_state;
wire [1:0] bump;
assign bump={bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground==1'b0)begin
next_state<=FALL_LEFT;
end
else if(dig==1'b1)begin
next_state<=DIG_LEFT;
end
else if((bump==2'b10)||(bump==2'b11))begin
next_state<=RIGHT;
end
else begin
next_state<=LEFT;
end
end
RIGHT:begin
if(ground==1'b0)begin
next_state<=FALL_RIGHT;
end
else if(dig==1'b1)begin
next_state<=DIG_RIGHT;
end
else if((bump==2'b01)||(bump==2'b11))begin
next_state<=LEFT;
end
else begin
next_state<=RIGHT;
end
end
DIG_LEFT:begin
if(ground==1'b0)begin
next_state<=FALL_LEFT;
end
else begin
next_state<=DIG_LEFT;
end
end
DIG_RIGHT:begin
if(ground==1'b0)begin
next_state<=FALL_RIGHT;
end
else begin
next_state<=DIG_RIGHT;
end
end
FALL_LEFT:begin
if(ground==1'b0)begin
next_state<=FALL_LEFT;
end
else begin
next_state<=LEFT;
end
end
FALL_RIGHT:begin
if(ground==1'b0)begin
next_state<=FALL_RIGHT;
end
else begin
next_state<=RIGHT;
end
end
endcase
end
always @(posedge clk,posedge areset)begin
if(areset)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
assign walk_left=(state==LEFT);
assign walk_right=(state==RIGHT);
assign digging=((state==DIG_LEFT)|(state==DIG_RIGHT));
assign aaah=((state==FALL_LEFT)|(state==FALL_RIGHT));
endmodule
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.
Falling for 20 cycles is survivable:
Falling for 21 cycles causes splatter:
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=3'b0;
parameter RIGHT=3'b1;
parameter DIG_LEFT=3'b10;
parameter DIG_RIGHT=3'b11;
parameter FALL_LEFT=3'b100;
parameter FALL_RIGHT=3'b101;
parameter DEAD=3'b110;
parameter SPLATTER=3'b111;
reg [2:0] state,next_state;
reg [4:0] Cycle_Count;
wire [1:0] bump;
assign bump={bump_left,bump_right};
always @(*)begin
case(state)
LEFT:begin
if(ground==1'b0)begin
next_state<=FALL_LEFT;
end
else if(dig == 1'b1)begin
next_state<=DIG_LEFT;
end
else if((bump==2'b10)||(bump==2'b11))begin
next_state<=RIGHT;
end
else begin
next_state<=LEFT;
end
end
RIGHT:begin
if(ground==1'b0)begin
next_state<=FALL_RIGHT;
end
else if(dig==1'b1)begin
next_state<=DIG_RIGHT;
end
else if((bump==2'b01)||(bump==2'b11))begin
next_state<=LEFT;
end
else begin
next_state<=RIGHT;
end
end
DIG_LEFT:begin
if(ground==1'b0)begin
next_state<=FALL_LEFT;
end
else begin
next_state<=DIG_LEFT;
end
end
DIG_RIGHT:begin
if(ground==1'b0)begin
next_state<=FALL_RIGHT;
end
else begin
next_state<=DIG_RIGHT;
end
end
FALL_LEFT:begin
if((ground==1'b0)&&(Cycle_Count<5'd20))begin
next_state<=FALL_LEFT;
end
else if((ground ==1'b0)&&(Cycle_Count>=5'd20))begin
next_state<=SPLATTER;
end
else begin
next_state<=LEFT;
end
end
FALL_RIGHT:begin
if((ground==1'b0)&&(Cycle_Count<5'd20))begin
next_state<=FALL_RIGHT;
end
else if((ground==1'b0)&&(Cycle_Count>=5'd20))begin
next_state<=SPLATTER;
end
else begin
next_state<=RIGHT;
end
end
SPLATTER:begin
if(ground==1'b1)begin
next_state<=DEAD;
end
else begin
next_state<=SPLATTER;
end
end
DEAD:begin
next_state<=DEAD;
end
endcase
end
always @(posedge clk,posedge areset)begin
if(areset)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
always @(posedge clk,posedge areset)begin
if(areset)begin
Cycle_Count<=5'd0;
end
else if((next_state==FALL_LEFT)||(next_state==FALL_RIGHT))begin
Cycle_Count<=Cycle_Count+1'b1;
end
else begin
Cycle_Count<=5'd0;
end
end
assign walk_left=(state==LEFT);
assign walk_right=(state==RIGHT);
assign aaah=((state==FALL_LEFT)||(state==FALL_RIGHT)||(state==SPLATTER));
assign digging=((state==DIG_LEFT)||(state==DIG_RIGHT));
endmodule
Given the following state machine with 1 input and 2 outputs:
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).
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
parameter S0=4'd0;
parameter S1=4'd1;
parameter S2=4'd2;
parameter S3=4'd3;
parameter S4=4'd4;
parameter S5=4'd5;
parameter S6=4'd6;
parameter S7=4'd7;
parameter S8=4'd8;
parameter S9=4'd9;
assign next_state[0]=~in&(state[S0]|state[S1]|state[S2]|state[S3]|state[S4]|state[S7]|state[S8]|state[S9]);
assign next_state[1]=in&(state[S0]|state[S8]|state[S9]);
assign next_state[2]=in&state[S1];
assign next_state[3]=in&state[S2];
assign next_state[4]=in&state[S3];
assign next_state[5]=in&state[S4];
assign next_state[6]=in&state[S5];
assign next_state[7]=in&(state[S6]|state[S7]);
assign next_state[8]=~in&state[S5];
assign next_state[9]=~in&state[S6];
assign out1=(state[S8]|state[S9]);
assign out2=(state[S7]|state[S9]);
endmodule
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); //
parameter BYTE_FIRST = 2'd0;
parameter BYTE_SECOND = 2'd1;
parameter BYTE_THIRD = 2'd2;
parameter WAIT = 2'd3;
reg [1:0] state,next_state;
// State transition logic (combinational)
always @(*)begin
case(state)
BYTE_FIRST:begin
next_state <= BYTE_SECOND;
end
BYTE_SECOND:begin
next_state <= BYTE_THIRD;
end
BYTE_THIRD:begin
if(in[3] == 1'b1)begin
next_state <= BYTE_FIRST;
end
else begin
next_state <= WAIT;
end
end
WAIT:begin
if(in[3] == 1'b1)begin
next_state <= BYTE_FIRST;
end
else begin
next_state <= WAIT;
end
end
endcase
end
// State flip-flops (sequential)
always @(posedge clk)begin
if(reset)begin
state <= WAIT;
end
else begin
state <= next_state;
end
end
// Output logic
assign done = (state == BYTE_THIRD);
endmodule
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:
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
parameter BYTE_FIRST = 2'd0;
parameter BYTE_SECOND = 2'd1;
parameter BYTE_THIRD = 2'd2;
parameter DONE = 2'd3;
reg [1:0] state,next_state;
reg [23:0] out_bytes_reg;
// FSM from fsm_ps2
always @(posedge clk)begin
if(reset)begin
state <= BYTE_FIRST;
end
else begin
state <= next_state;
end
end
always @(*)begin
case(state)
BYTE_FIRST:begin
if(in[3])begin
next_state <= BYTE_SECOND;
end
else begin
next_state <= BYTE_FIRST;
end
end
BYTE_SECOND:begin
next_state <= BYTE_THIRD;
end
BYTE_THIRD:begin
next_state <= DONE;
end
DONE:begin
if(in[3])begin
next_state <= BYTE_SECOND;
end
else begin
next_state <= BYTE_FIRST;
end
end
endcase
end
always @(posedge clk)begin
if(next_state == BYTE_SECOND)begin
out_bytes_reg[23:16] <= in;
end
else if(next_state == BYTE_THIRD)begin
out_bytes_reg[15:8] <= in;
end
else if(next_state == DONE)begin
out_bytes_reg[7:0] <= in;
end
else begin
out_bytes_reg <= 24'd0;
end
end
// New: Datapath to store incoming bytes.
assign done = (state == DONE);
assign out_bytes = out_bytes_reg;
endmodule
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 [3:0] START = 4'd0;
parameter [3:0] ONE = 4'd1;
parameter [3:0] TWO = 4'd2;
parameter [3:0] THREE = 4'd3;
parameter [3:0] FOUR = 4'd4;
parameter [3:0] FIVE = 4'd5;
parameter [3:0] SIX = 4'd6;
parameter [3:0] SEVEN = 4'd7;
parameter [3:0] EIGHT = 4'd8;
parameter [3:0] STOP = 4'd9;
parameter [3:0] IDLE = 4'd10;
parameter [3:0] WAIT = 4'd11;
reg [3:0] state,next_state;
always @(*)begin
case(state)
START:begin
next_state <= ONE;
end
ONE:begin
next_state <= TWO;
end
TWO:begin
next_state <= THREE;
end
THREE:begin
next_state <= FOUR;
end
FOUR:begin
next_state <= FIVE;
end
FIVE:begin
next_state <= SIX;
end
SIX:begin
next_state <= SEVEN;
end
SEVEN:begin
next_state <= EIGHT;
end
EIGHT:begin
if(in)begin
next_state <= STOP;
end
else begin
next_state <= WAIT;
end
end
STOP:begin
if(in)begin
next_state <= IDLE;
end
else begin
next_state <= START;
end
end
WAIT:begin
if(in)begin
next_state <= IDLE;
end
else begin
next_state <= WAIT;
end
end
IDLE:begin
if(~in)begin
next_state <= START;
end
else begin
next_state <= IDLE;
end
end
endcase
end
always @(posedge clk)begin
if(reset)begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
assign done = (state == STOP);
endmodule
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.
/* way 1*/
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
parameter [3:0] START = 4'd0;
parameter [3:0] ONE = 4'd1;
parameter [3:0] TWO = 4'd2;
parameter [3:0] THREE = 4'd3;
parameter [3:0] FOUR = 4'd4;
parameter [3:0] FIVE = 4'd5;
parameter [3:0] SIX = 4'd6;
parameter [3:0] SEVEN = 4'd7;
parameter [3:0] EIGHT = 4'd8;
parameter [3:0] STOP = 4'd9;
parameter [3:0] IDLE = 4'd10;
parameter [3:0] WAIT = 4'd11;
reg [3:0] state,next_state;
reg [7:0] par_in;
always @(*)begin
case(state)
START:begin
next_state <= ONE;
par_in[0] <= in;
end
ONE:begin
next_state <= TWO;
par_in[1] <= in;
end
TWO:begin
next_state <= THREE;
par_in[2] <= in;
end
THREE:begin
next_state <= FOUR;
par_in[3] <= in;
end
FOUR:begin
next_state <= FIVE;
par_in[4] <= in;
end
FIVE:begin
next_state <= SIX;
par_in[5] <= in;
end
SIX:begin
next_state <= SEVEN;
par_in[6] <= in;
end
SEVEN:begin
next_state <= EIGHT;
par_in[7] <= in;
end
EIGHT:begin
if(in)begin
next_state <= STOP;
end
else begin
next_state <= WAIT;
end
end
STOP:begin
if(in)begin
next_state <= IDLE;
end
else begin
next_state <= START;
end
end
WAIT:begin
if(in)begin
next_state <= IDLE;
end
else begin
next_state <= WAIT;
end
end
IDLE:begin
if(~in)begin
next_state <= START;
end
else begin
next_state <= IDLE;
end
end
endcase
end
always @(posedge clk)begin
if(reset)begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
assign done = (state == STOP);
assign out_byte = (state == STOP) ? par_in : 8'd0;
endmodule
/* way 2 */
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
);
parameter IDLE = 3'd0, START = 3'd1, DATA = 3'd2;
parameter STOP = 3'd3, WAIT = 3'd4;
reg [3:0] current_state;
reg [3:0] next_state;
reg [3:0] counter;
reg [7:0] par_in;
// Use FSM from Fsm_serial
always @(*)begin
case(current_state)
IDLE:begin
if(~in)begin
next_state = START;
end
else begin
next_state = IDLE;
end
end
START:begin
next_state = DATA;
end
DATA:begin
if(counter == 4'd8)begin
next_state = in? STOP:WAIT;
end
else begin
next_state = DATA;
end
end
STOP:begin
next_state = in? IDLE:START;
end
WAIT:begin
next_state = in? IDLE:WAIT;
end
default:begin
next_state = IDLE;
end
endcase
end
always @(posedge clk)begin
if(reset)begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always @(posedge clk)begin
if(reset)begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
else begin
case(next_state)
IDLE:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
START:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
DATA:begin
done <= 1'd0;
out_byte <= 8'd0;
par_in[counter] <= in;
counter <= counter + 1'd1;
end
STOP:begin
done <= 1'd1;
out_byte <= par_in;
counter <= 4'd0;
end
WAIT:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
endcase
end
end
// New: Datapath to latch input bits.
endmodule
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.
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
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output [7:0] out_byte,
output done
); //
parameter IDLE = 3'd0,START = 3'd1,DATA = 3'd2;
parameter STOP = 3'd3,WAIT = 3'd4;
reg [2:0] current_state,next_state;
reg [3:0] counter;
reg [8:0] data_in;
reg odd_temp;
wire Isdone;
// Modify FSM and datapath from Fsm_serialdata
always @(*) begin
case(current_state)
IDLE:begin
if(~in)begin
next_state = START;
end
else begin
next_state = IDLE;
end
end
START:begin
next_state = DATA;
end
DATA:begin
if(counter == 4'd9)begin
next_state = in ? STOP : WAIT;
end
else begin
next_state = DATA;
end
end
STOP:begin
next_state = in ? IDLE : START;
end
WAIT:begin
next_state = in ? IDLE : WAIT;
end
default:begin
next_state = IDLE;
end
endcase
end
always @(posedge clk) begin
if(reset)begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always @(posedge clk) begin
if(reset)begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
else begin
case(next_state)
IDLE:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
START:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
DATA:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= counter + 1'd1;
data_in[counter] <= in;
end
STOP:begin
done <= odd_temp ? 1'd1 : 1'd0;
out_byte <= odd_temp ? data_in[7:0] : 8'd0;
counter <= 4'd0;
end
WAIT:begin
done <= 1'd0;
out_byte <= 8'd0;
counter <= 4'd0;
end
endcase
end
end
// New: Add parity checking.
assign Isdone = (next_state == START);
parity u0(clk,Isdone,in,odd_temp);
endmodule
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.
Discard 0111110:
Flag 01111110:
Reset behaviour and error 01111111...:
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
parameter NONE = 4'd0,ONE = 4'd1,TWO = 4'd2;
parameter THREE = 4'd3,FOUR = 4'd4,FIVE = 4'd5;
parameter SIX = 4'd6,ERROR = 4'd7;
parameter DISC = 4'd8,FLAG = 4'd9;
reg [3:0] current_state,next_state;
always @(*) begin
case(current_state)
NONE:begin
next_state = in ? ONE : NONE;
end
ONE:begin
next_state = in ? TWO : NONE;
end
TWO:begin
next_state = in ? THREE : NONE;
end
THREE:begin
next_state = in ? FOUR : NONE;
end
FOUR:begin
next_state = in ? FIVE : NONE;
end
FIVE:begin
next_state = in ? SIX : DISC;
end
SIX:begin
next_state = in ? ERROR : FLAG;
end
DISC:begin
next_state = in ? ONE : NONE;
end
FLAG:begin
next_state = in ? ONE : NONE;
end
ERROR:begin
next_state = in ? ERROR : NONE;
end
endcase
end
always @(posedge clk) begin
if(reset)begin
current_state <= NONE;
end
else begin
current_state <= next_state;
end
end
always @(posedge clk) begin
if(reset)begin
disc <= 1'd0;
flag <= 1'd0;
err <= 1'd0;
end
else begin
case(next_state)
DISC:begin
disc <= 1'd1;
flag <= 1'd0;
err <= 1'd0;
end
FLAG:begin
disc <= 1'd0;
flag <= 1'd1;
err <= 1'd0;
end
ERROR:begin
disc <= 1'd0;
flag <= 1'd0;
err <= 1'd1;
end
default:begin
disc <= 1'd0;
flag <= 1'd0;
err <= 1'd0;
end
endcase
end
end
endmodule
Implement a Mealy-type finite state machine that recognizes the sequence "101" on an input signal named x. Your FSM should have an output signal, z, that is asserted to logic-1 when the "101" sequence is detected. Your FSM should also have an active-low asynchronous reset. You may only have 3 states in your state machine. Your FSM should recognize overlapping sequences.
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter S0 = 2'd0,S1 = 2'd1,S2 = 2'd2;
reg [1:0] current_state,next_state;
always @(*) begin
case(current_state)
S0: next_state = x ? S1 : S0;
S1: next_state = x ? S1 : S2;
S2: next_state = x ? S1 : S0;
endcase
end
always @(posedge clk or negedge aresetn) begin
if(~aresetn)begin
current_state <= S0;
end
else begin
current_state <= next_state;
end
end
always @(*) begin
z=(current_state==S2)?x:1'b0;
end
endmodule
You are to design a one-input one-output serial 2's complementer Moore state machine. The input (x) is a series of bits (one per clock cycle) beginning with the least-significant bit of the number, and the output (Z) is the 2's complement of the input. The machine will accept input numbers of arbitrary length. The circuit requires an asynchronous reset. The conversion begins when Reset is released and stops when Reset is asserted.
module top_module (
input clk,
input areset,
input x,
output z
);
parameter S0=2'd0, S1=2'd1, S2=2'd2;
reg [1:0] current_state, next_state;
always @(*) begin
case(current_state)
S0:next_state=x?S1:S0;
S1:next_state=x?S2:S1;
S2:next_state=x?S2:S1;
endcase
end
always @(posedge clk or posedge areset) begin
if(areset)begin
current_state<=S0;
end
else begin
current_state<=next_state;
end
end
assign z=(current_state==S1);
endmodule
The following diagram is a Mealy machine implementation of the 2's complementer. Implement using one-hot encoding.
module top_module (
input clk,
input areset,
input x,
output z
);
parameter A=0,B=1;
reg current_state,next_state;
always @(*) begin
case(current_state)
A:next_state=x?B:A;
B:next_state=B;
endcase
end
always @(posedge clk or posedge areset) begin
if(areset)
current_state<=A;
else
current_state<=next_state;
end
assign z=((current_state==A)&&x)||((current_state==B)&&~x);
endmodule
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.
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter S0=1'd0, S1=1'd1;
reg current_state, next_state;
reg [1:0] counter,num_one;
always @(*) begin
case(current_state)
S0:next_state=s?S1:S0;
S1:next_state=S1;
default:next_state=S0;
endcase
end
always @(posedge clk) begin
if(reset)begin
current_state<=S0;
end
else begin
current_state<=next_state;
end
end
always @(posedge clk) begin
if(reset)begin
counter<=2'd0;
end
else if(counter==2'd2) begin
counter<=2'd0;
end
else if(current_state==S1) begin
counter<=counter+1'd1;
end
end
always @(posedge clk) begin
if(reset) begin
num_one<=1'd0;
end
else begin
if(counter==2'd0)begin
num_one<=w?1'd1:1'd0;
end
else if(current_state==S1) begin
num_one<=w?(num_one+1'd1):num_one;
end
end
end
assign z=(current_state==S1&&num_one==2'd2&&counter==2'd0);
endmodule
Given the state-assigned table shown below, implement the finite-state machine. Reset should reset the FSM to state 000.
Present state y[2:0] | Next state Y[2:0] | Output z | |
---|---|---|---|
x=0 | x=1 | ||
000 | 000 | 001 | 0 |
001 | 001 | 100 | 0 |
010 | 010 | 001 | 0 |
011 | 001 | 010 | 1 |
100 | 011 | 100 | 1 |
module top_module (
input clk,
input reset, // Synchronous reset
input x,
output z
);
parameter S0 = 3'd0, S1 = 3'd1, S2 = 3'd3;
parameter S3 = 3'd4, S4 = 3'd5;
reg [2:0] current_state, next_state;
always @(*) begin
case(current_state)
S0:next_state=x?S1:S0;
S1:next_state=x?S4:S1;
S2:next_state=x?S1:S2;
S3:next_state=x?S2:S1;
S4:next_state=x?S4:S3;
default:next_state=S0;
endcase
end
always @(posedge clk) begin
if(reset)begin
current_state<=S0;
end
else begin
current_state<=next_state;
end
end
always @(posedge clk) begin
if(reset)begin
z<=1'b0;
end
else begin
case(next_state)
S3:z<=1'b1;
S4:z<=1'b1;
default:z<=1'b0;
endcase
end
end
endmodule
Given the state-assigned table shown below, implement the logic functions Y[0] and z.
Present state y[2:0] | Next state Y[2:0] | Output z | |
---|---|---|---|
x=0 | x=1 | ||
000 | 000 | 001 | 0 |
001 | 001 | 100 | 0 |
010 | 010 | 001 | 0 |
011 | 001 | 010 | 1 |
100 | 011 | 100 | 1 |
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
assign Y0 = ((~y[2]&y[0])|(y==3'b100))&~x | (~y[2]&~y[0])&x;
assign z = (y == 3'b011) | (y == 3'b100);
endmodule
Consider the state machine shown below, which has one input w and one output z.
Assume that you wish to implement the FSM using three flip-flops and state codes y[3:1] = 000, 001, ... , 101 for states A, B, ... , F, respectively. Show a state-assigned table for this FSM. Derive a next-state expression for the flip-flop y[2].
Implement just the next-state logic for y[2]. (This is much more a FSM question than a Verilog coding question. Oh well.)
module top_module (
input [3:1] y,
input w,
output Y2);
assign Y2=(y==3'b001|y==3'b101)&~w|(y==3'b001|y==3'b010|y==3'b100|y==3'b101)&w;
endmodule
Consider the state machine shown below, which has one input w and one output z.
For this part, assume that a one-hot code is used with the state assignment 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000 for states A, B,..., F, respectively.
Write a logic expression for the next-state signals Y2 and Y4. (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).
module top_module (
input [6:1] y,
input w,
output Y2,
output Y4);
assign Y2=~w&y[1];
assign Y4=(w&y[2])|(w&y[3])|(w&y[5])|(w&y[6]);
endmodule
Consider the state machine shown below, which has one input w and one output z
Implement the state machine. (This part wasn't on the midterm, but coding up FSMs is good practice).
module top_module (
input clk,
input reset, // synchronous reset
input w,
output z);
parameter A=3'd0,B=3'd1,C=3'd2;
parameter D=3'd3,E=3'd4,F=3'd5;
reg [2:0] current_state, next_state;
always @(*) begin
case(current_state)
A:next_state=w?A:B;
B:next_state=w?D:C;
C:next_state=w?D:E;
D:next_state=w?A:F;
E:next_state=w?D:E;
F:next_state=w?D:C;
default:next_state=A;
endcase
end
always @(posedge clk) begin
if(reset)begin
current_state<=A;
end
else begin
current_state<=next_state;
end
end
assign z=(current_state==E|current_state==F);
endmodule
Consider the state diagram shown below
Write complete Verilog code that represents this FSM. Use separate always blocks for the state table and the state flip-flops, as done in lectures. Describe the FSM output, which is called z, using either continuous assignment statement(s) or an always block (at your discretion). Assign any state codes that you wish to use.
module top_module (
input clk,
input reset, // Synchronous active-high reset
input w,
output z
);
parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
reg [2:0] current_state,next_state;
always @(*) begin
case(current_state)
A:next_state=w?B:A;
B:next_state=w?C:D;
C:next_state=w?E:D;
D:next_state=w?F:A;
E:next_state=w?E:D;
F:next_state=w?C:D;
default:next_state<=A;
endcase
end
always @(posedge clk) begin
if(reset)
current_state<=A;
else
current_state<=next_state;
end
assign z=(current_state==E)|(current_state==F);
endmodule
The state diagram for this question is shown again below.
Assume that a one-hot code is used with the state assignment y[5:0] = 000001(A), 000010(B), 000100(C), 001000(D), 010000(E), 100000(F)
Write a logic expression for the signal Y1, which is the input of state flip-flop y[1].
Write a logic expression for the signal Y3, which is the input of state flip-flop y[3].
(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).
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
assign Y1=y[0]&w;
assign Y3=(y[1]|y[2]|y[4]|y[5])&~w;
endmodule
Consider the FSM described by the state diagram shown below:
This FSM acts as an arbiter circuit, which controls access to some type of resource by three requesting devices. Each device makes its request for the resource by setting a signal r[i] = 1, where r[i] is either r[1], r[2], or r[3]. Each r[i] is an input signal to the FSM, and represents one of the three devices. The FSM stays in state A as long as there are no requests. When one or more request occurs, then the FSM decides which device receives a grant to use the resource and changes to a state that sets that device’s g[i] signal to 1. Each g[i] is an output from the FSM. There is a priority system, in that device 1 has a higher priority than device 2, and device 3 has the lowest priority. Hence, for example, device 3 will only receive a grant if it is the only device making a request when the FSM is in state A. Once a device, i, is given a grant by the FSM, that device continues to receive the grant as long as its request, r[i] = 1.
Write complete Verilog code that represents this FSM. Use separate always blocks for the state table and the state flip-flops, as done in lectures. Describe the FSM outputs, g[i], using either continuous assignment statement(s) or an always block (at your discretion). Assign any state codes that you wish to use.
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output [3:1] g // grant
);
parameter A=2'd0,B=2'd1;
parameter C=2'd2,D=2'd3;
reg [1:0] current_state, next_state;
always @(*) begin
case(current_state)
A:begin
if(r[1]==1'b1) begin
next_state=B;
end
else if(r[2]==1'b1) begin
next_state=C;
end
else if(r[3]==1'b1) begin
next_state=D;
end
else begin
next_state=A;
end
end
B:next_state=r[1]?B:A;
C:next_state=r[2]?C:A;
D:next_state=r[3]?D:A;
default: next_state=A;
endcase
end
always @(posedge clk) begin
if(~resetn) begin
current_state<=A;
end
else begin
current_state<=next_state;
end
end
assign g[1]=current_state==B;
assign g[2]=current_state==C;
assign g[3]=current_state==D;
endmodule
Consider a finite state machine that is used to control some type of motor. The FSM has inputs x and y, which come from the motor, and produces outputs f and g, which control the motor. There is also a clock input called clk and a reset input called resetn.
The FSM has to work as follows. As long as the reset input is asserted, the FSM stays in a beginning state, called state A. When the reset signal is de-asserted, then after the next clock edge the FSM has to set the output f to 1 for one clock cycle. Then, the FSM has to monitor the x input. When x has produced the values 1, 0, 1 in three successive clock cycles, then g should be set to 1 on the following clock cycle. While maintaining g = 1 the FSM has to monitor the y input. If y has the value 1 within at most two clock cycles, then the FSM should maintain g = 1 permanently (that is, until reset). But if y does not become 1 within two clock cycles, then the FSM should set g = 0 permanently (until reset).
(The original exam question asked for a state diagram only. But here, implement the FSM.)
module top_module(
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter IDLE=4'd0,FOUT=4'd1,S1=4'd2;
parameter S2=4'd3,S3=4'd4,S4=4'd5;
parameter S5=4'd6,ALL_ONE=4'd7,ALL_ZERO=4'd8;
reg [3:0] current_state,next_state;
always @(*) begin
case(current_state)
IDLE:next_state=FOUT;
FOUT:next_state=S1;
S1:next_state=x?S2:S1;
S2:next_state=x?S2:S3;
S3:next_state=x?S4:S1;
S4:next_state=y?ALL_ONE:S5;
S5:next_state= y?ALL_ONE:ALL_ZERO;
ALL_ONE:next_state=ALL_ONE;
ALL_ZERO:next_state=ALL_ZERO;
default:next_state=IDLE;
endcase
end
always @(posedge clk) begin
if(~resetn) begin
current_state<=IDLE;
end
else begin
current_state<=next_state;
end
end
assign f=current_state==FOUT;
assign g=current_state==S4|current_state==S5|current_state==ALL_ONE;
endmodule