Finite State Machine (FSM) : Example

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 22

Finite State Machine (FSM) When the sequence of actions in your design depend on the state of sequential elements,

, a finite state machine (FSM) can be implemented FSMs are widely used in applications that require prescribed sequential activity
Example:
Sequence Detector Fancy counters Traffic Light Controller Data-path Controller Device Interface Controller etc.

Finite State Machine (FSM) (cont.) All state machines have the general feedback structure consisting of:
Combinational logic implements the next state logic
Next state (ns) of the machine is formed from the current state (cs) and the current inputs

State register holds the value of current state

Next State

Inputs

Next-State Logic

Memory

Current State

Types of State Machines Moore State Machine

Inputs

Next-State Logic

ns

cs State Register Output Logic

Outputs

Next state depends on the current state and the inputs but the output depends only on the present state
next_state(t) = h(current_state(t), input(t)) output = g(current_state(t))

Types of State Machines (cont.) Mealy State Machine


Output Logic

Inputs

Next-State Logic

ns

cs State Register

Outputs

Next state and the outputs depend on the current state and the inputs
next_state(t) = h(current_state(t), input(t)) output(t) = g(current_state(t), input(t))

Typical Structure of a FSM


module mod_name ( ); input ; output ; parameter size = ; reg [size-1: 0] current_state; wire [size-1: 0] next_state; // State definitions `define state_0 2'b00 `define state_1 2b01 always @ (current_state or the_inputs) begin // Decode for next_state with case or if statement // Use blocked assignments for all register transfers to ensure // no race conditions with synchronous assignments end always @ (negedge reset or posedge clk) begin if (reset == 1'b0) current_state <= state_0; else current_state <= next_state; end //Output assignments endmodule

Next State Logic

State Register

Sequence Detector FSM

Functionality: Detect two successive 0s or 1s in the serial input bit stream


reset reset_state 0

out_bit = 0
1

FSM Flow-Chart

out_bit = 0 read_1_zero
0
0 0

read_1_one

out_bit = 0

read_2_zero

read_2_one

out_bit = 1

out_bit = 1

Sequence Detector FSM (cont.)


module seq_detect (clock, reset, in_bit, out_bit); input clock, reset, in_bit; output out_bit; reg [2:0] state_reg, next_state; // State declaration parameter reset_state = parameter read_1_zero = parameter read_1_one = parameter read_2_zero = parameter read_2_one = always @ (state_reg or in_bit) case (state_reg) reset_state: if (in_bit == 0) next_state = read_1_zero; else if (in_bit == 1) next_state = read_1_one; else next_state = reset_state; read_1_zero: if (in_bit == 0) next_state = read_2_zero; else if (in_bit == 1) next_state = read_1_one; else next_state = reset_state; read_2_zero: if (in_bit == 0) next_state = read_2_zero; else if (in_bit == 1) next_state = read_1_one; else next_state = reset_state;

3'b000; 3'b001; 3'b010; 3'b011; 3'b100;

// state register always @ (posedge clock or posedge reset) if (reset == 1) state_reg <= reset_state; else state_reg <= next_state; // next-state logic

Sequence Detector FSM (cont.)


read_1_one: if (in_bit == 0) next_state = read_1_zero; else if (in_bit == 1) next_state = read_2_one; else next_state = reset_state; read_2_one: if (in_bit == 0) next_state = read_1_zero; else if (in_bit == 1) next_state = read_2_one; else next_state = reset_state; default: next_state = reset_state; endcase assign out_bit = ((state_reg == read_2_zero) || (state_reg == read_2_one)) ? 1 : 0; endmodule

Clock Domain Synchronization Larger designs generally consists of several parts that operate at independent clocks clock domains

Clock domain synchronization is required when ever a signal traverses from one clock domain to another clock domain
Problem can be treated as the case where flip-flop data input is asynchronous
Can cause metastabilty in the receiving flip-flop Rupture the sequential behavior

This can be avoided by using synchronization circuits

Clock Domain Synchronization (cont.) Note:


Metastability can not be avoided Metastability causes the flip-flop to take longer time than tclock-output to recover

Solution: Let the signal become stable before using it (i.e. increase the MTBF)
DA
Flip-flop1 Flip-flop2

D clkA

DB

clkB

Types of Synchronization Techniques Case-1: When the width of asynchronous input pulse is greater than the clock period i.e. Tasync_in > Tclock

async_in
Flip-flop1

q1
Flip-flop2

sync_out

clock reset

Simulation Results Presence of Metastable State


clock reset async_in q1 sync_out

metastable

not metastable

The flip flips get reset

The reset is de-asserted async_in becomes high simultaneously with the posedge of the clock, thus violating the setup time

Flip-flop1 enters metastability

Flip-flop1 comes back to a stable state, latching async_in Flip_flop2 latches the stable value of flip_flop1 (q1), thus delaying async_in by 3 clock cycles*

Flip-flop1 gets a stable input at this (2nd) edge

* As sync_out will be available to latch only at the next clock edge

Simulation Results (cont.) Absence of Metastable State


clock reset async_in q1 sync_out

The flip flips get reset

The reset is de-asserted async_in becomes high before the posedge of the clock, thus meeting the setup time

Flip-flop1 enters stable state latching async_in Flip_flop2 latches the stable value of flip_flop1 (q1), thus delaying async_in by 2 clock cycles

Types of Synchronization Techniques (cont.) Case-2: When the width of asynchronous input pulse is less than the clock period i.e. Tasync_in < Tclock
VDD async_in clock reset q1
Flip-flop1 Flip-flop2

q2
Flip-flop3

sync_out

Simulation Results

clock reset async_in q1 q2 sync_out first_reset

Reset Sequence for the synchronization circuit

Flip-flop1 gets a stable posedge of async_in Flip-flop1 latches 1

Sync_out becomes high after 2 clocks and causes flip-flop1 to reset

First-in First-out Memory (FIFO) When the source clock is higher than the destination clock, loss of data can occur due to inability of the destination to sample at the source speed How to avoid this?
Use handshake signals (i.e. supply data only when the destination is ready to receive e.g. master-slave protocol)
Transfer rates are lower

High performance parallel interfaces between independent clock domains are implemented with first-in first-out memory called FIFO.

FIFO Features
A FIFO consists of block of memory and a controller that manages the traffic of data to and from the FIFO A FIFO provides access to only one register cell at a time (not the entire array of registers) A FIFO has two address pointers, one for writing to the next available cell, and another one for reading the next unread cell

The pointers for reading and writing are relocated dynamically as commands to read or write are received
A pointer is moved after each operation

A FIFO can receive data until it is full and can be read until it is empty

FIFO Features (cont.)


A FIFO has:
Separate address pointers and datapaths for reading and writing data Status lines indicating the condition of the stack (full, almost full, empty etc.)

The input (write) and output (read) domains can be synchronized by two separate clocks, allowing the FIFO to act as a buffer between two clock domains

A FIFO can allow simultaneous reading and writing of data (however


synchronization is necessary if read/write parts are different clock domains)

The write signal is synchronized to the read clock using clock synchronizers FIFOs are usually implemented with dual-port RAMs with independent read- and write-address pointers and registered data ports (see www.idt.com)

FIFO Structure
stack_height -1

data_in
write_to_stack clk_write

stack_full stack_half stack_empty data_out read_from_stack clk_read

FIFO Buffer

rst

Internal Signals
write_ptr

0 stack_width -1 0

Input-output Ports
read_ptr

FIFO Model
Note: Prohibit write if the FIFO is full and Prohibit read if the FIFO is empty module FIFO_Buffer (clk, rst, write_to_stack, data_in, read_from_stack, data_out, stack_full, stack_half_full, stack_empty); parameter parameter parameter parameter stack_width stack_height stack_ptr_width HF_level = = = = 32; 8; 3; 4;

input clk, rst, write_to_stack, read_from_stack; input [stack_width-1:0] data_in; output stack_full, stack_half_full, stack_empty; output [stack_width-1:0] data_out; reg [stack_ptr_width-1:0] read_ptr, write_ptr; reg [stack_ptr_width:0] ptr_gap; // Gap between the pointers reg [stack_width-1:0] data_out; reg [stack_width:0] stack [stack_height-1:0]; // stack status signals assign stack_full = (ptr_gap == stack_height); assign stack_half_full = (ptr_gap == HF_level); assign stack_empty = (ptr_gap == 0);

FIFO Model (cont.)


always @ (posedge clock or posedge reset) if (rst == 1) begin data_out <= 0; read_ptr <= 0; write_ptr <= 0; ptr_gap <= 0; begin else if (write_to_stack && (!read_from_stack) && (!stack_full)) begin stack [write_ptr] <= data_in; write_ptr <= write_ptr + 1; ptr_gap <= ptr_gap + 1; end else if ((!write_to_stack) && read_from_stack && (!stack_empty)) begin data_out <= stack[read_ptr]; read_ptr <= read_ptr + 1; ptr_gap <= ptr_gap - 1; end else if (write_to_stack && read_from_stack && stack_empty) begin stack [write_ptr] <= data_in; write_ptr <= write_ptr + 1; ptr_gap <= ptr_gap + 1; end

FIFO Model (cont.)


else if (write_to_stack && read_from_stack && stack_full) begin data_out <= stack[read_ptr]; read_ptr <= read_ptr + 1; ptr_gap <= ptr_gap - 1; end else if (write_to_stack && read_from_stack && (!stack_empty) && (!stack_full)) begin stack [write_ptr] <= data_in; data_out <= stack[read_ptr]; write_ptr <= write_ptr + 1; read_ptr <= read_ptr + 1; end endmodule

You might also like