Verilog 15 :Memory Modeling and Finite State Machines (FSMs)

1. Introduction to Sequential Logic


Before we dive into memories and FSMs, we need to understand sequential logic.

  • Combinational logic: output depends only on current inputs. Examples: adders, multiplexers, logic gates.

  • Sequential logic: output depends on current inputs and previous state. Examples: flip-flops, registers, counters.

Key Building Blocks:

  1. Flip-flops: Store a single bit of data. Types include D, T, JK flip-flops.

  2. Registers: Group of flip-flops storing multiple bits.

  3. Clock signal: Controls when sequential elements update their state.

Why Sequential Logic Matters:
Memories and FSMs are sequential circuits. Without understanding how data flows over time (clock cycles), modeling these components becomes impossible.


2. Memory Modeling in Verilog

Memory in digital systems is simply a collection of registers or arrays of storage elements.


2.1. Memory Basics

  1. Memory Address: Unique location index (like 0, 1, 2, …).

  2. Memory Word: Data stored at an address (8-bit, 16-bit, etc.).

  3. Memory Depth: Total number of storage locations.

  4. Data Width: Number of bits per word.

Example Analogy:
Think of a spreadsheet: rows = addresses, columns = bits in each word.


2.2. Declaring Memories in Verilog

reg [7:0] mem [0:15]; // 16 words, 8 bits each
  • [7:0] → 8 bits per word

  • [0:15] → 16 addresses (0 to 15)

  • Access like mem[3] → reads or writes the 4th word


2.3. Writing to Memory

always @(posedge clk) begin if(write_enable) mem[address] <= data_in; end
  • write_enable controls whether the memory is updated.

  • Non-blocking assignment (<=) ensures correct sequential behavior.


2.4. Reading from Memory

Synchronous Read (clocked):

always @(posedge clk) begin data_out <= mem[address]; end

Asynchronous Read (immediate):

assign data_out = mem[address];

Tip: Use synchronous read for sequential circuits, asynchronous for lookup tables or ROMs.


2.5. Accessing Bits in Memory

wire bit_val; assign bit_val = mem[address][3]; // 3rd bit of selected word

2.6. Initializing Memory

Option 1: Hard-coded Initialization

initial begin mem[0] = 8'h00; mem[1] = 8'hFF; mem[2] = 8'hAA; end

Option 2: Using a Memory File

initial $readmemb("memory.list", mem); // binary file
  • Each line of memory.list contains one word in binary.

  • $readmemh works for hexadecimal format.


2.7. Simple Memory Example

module simple_memory( input clk, input write_enable, input [3:0] address, input [7:0] data_in, output reg [7:0] data_out ); reg [7:0] mem [0:15]; always @(posedge clk) begin if(write_enable) mem[address] <= data_in; data_out <= mem[address]; end endmodule

Explanation:

  • Synchronous memory write and read.

  • 16 words × 8-bit each.

  • data_out reflects content at selected address.


3. Introduction to Finite State Machines (FSMs)

FSMs are sequential circuits used to control operations based on current state and inputs.

3.1. FSM Components

  1. States: Represent the status of the system (IDLE, RUNNING, ERROR).

  2. Inputs: External signals that trigger transitions.

  3. Outputs: System responses.

  4. Transitions: Rules that move from one state to another.

Real-life Analogy:
Traffic light controller: states = Red, Yellow, Green; transitions = timer or sensor; outputs = light signals.


3.2. Types of FSM

TypeOutput depends onCharacteristics
MooreCurrent state onlyStable outputs, fewer glitches
MealyCurrent state + inputsPotential glitches, fewer states needed

3.3. Moore vs Mealy Example

Moore FSM – output = 1 if in RUN state.

assign output_signal = (state == RUN);

Mealy FSM – output = 1 if in RUN state AND input start is high.

assign output_signal = (state == RUN) & start;

4. Modeling FSMs in Verilog

FSMs are modeled in two main sections:

  1. Combinational logic – calculates next_state

  2. Sequential logic – updates current_state at clock edge


4.1. Step-by-Step FSM Design

Step 1: Define all states

typedef enum reg [1:0] {IDLE=2'b00, GRANT_A=2'b01, GRANT_B=2'b10} state_t; state_t current_state, next_state;

Step 2: Sequential section (state register)

always @(posedge clk or negedge reset) begin if(!reset) current_state <= IDLE; else current_state <= next_state; end

Step 3: Combinational section (next state logic)

always @(*) begin case(current_state) IDLE: if(request_a) next_state = GRANT_A; else if(request_b) next_state = GRANT_B; else next_state = IDLE; GRANT_A: if(request_b) next_state = GRANT_B; else next_state = GRANT_A; GRANT_B: if(request_a) next_state = GRANT_A; else next_state = GRANT_B; default: next_state = IDLE; endcase end

Step 4: Output logic (Moore or Mealy)

always @(*) begin grant_a = (current_state == GRANT_A); grant_b = (current_state == GRANT_B); end

4.2. FSM Encoding Techniques

  1. Binary Encoding – minimal flip-flops. Efficient for ASICs.

  2. One-Hot Encoding – one flip-flop per state. Fast for FPGAs.

  3. Gray Encoding – only one bit changes between states, reduces glitches.

Example – One-Hot:

typedef enum reg [3:0] {IDLE=4'b0001, GRANT_A=4'b0010, GRANT_B=4'b0100} state_t;

4.3. Complete Arbiter FSM Example

module arbiter( input clk, reset, input request_a, request_b, output reg grant_a, grant_b ); typedef enum reg [1:0] {IDLE=2'b00, GRANT_A=2'b01, GRANT_B=2'b10} state_t; state_t current_state, next_state; // Sequential Section always @(posedge clk or negedge reset) begin if(!reset) current_state <= IDLE; else current_state <= next_state; end // Combinational Section always @(*) begin case(current_state) IDLE: if(request_a) next_state = GRANT_A; else if(request_b) next_state = GRANT_B; else next_state = IDLE; GRANT_A: if(request_b) next_state = GRANT_B; else next_state = GRANT_A; GRANT_B: if(request_a) next_state = GRANT_A; else next_state = GRANT_B; default: next_state = IDLE; endcase end // Output Logic (Moore) always @(*) begin grant_a = (current_state == GRANT_A); grant_b = (current_state == GRANT_B); end endmodule

5. Best Practices

  1. Use non-blocking assignments (<=) in sequential logic.

  2. Initialize FSM states and memory elements to avoid X (unknown) values.

  3. Prefer separate combinational and sequential blocks for readability.

  4. Choose encoding style based on hardware: one-hot for FPGAs, binary for ASICs.

  5. Test FSMs with simulation and waveform inspection before synthesis.


6. Summary

  • Memory Modeling: Create arrays of registers, read/write synchronously or asynchronously, initialize using code or files.

  • FSMs: Use sequential logic for states, combinational logic for next state, Moore vs Mealy output logic.

  • State Encodings: Binary, one-hot, gray – choose depending on design requirements.

  • Proper understanding of clocked sequential logic is key to robust memory and FSM design.

Comments

Popular posts from this blog

Fundamental of python : 1.Python Numbers