Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

APB-Interfaced die Roller with Seven-Segment Word Encoding

Status: Under active development


How It Works

This project implements a digital "die roller" that generates a pseudorandom number (1–6) on a rising clock edge when roll is asserted, and displays the result as a word ("one" through "six") across seven-segment displays.

Once a value is determined, the device translates this numeric data into a word format displayed via a seven-segment display. Because standard seven-segment displays are limited in their character set, the design employs a "visual cheating" technique. For instance, the letter ‘w’ in "two" is approximated using two adjacent display characters, and the ‘x’ in "six" is rendered across three characters. These complex segment encodings are retrieved from a behavioural memory model via an Advanced Peripheral Bus (APB) read transaction. The final output is driven to the segments port, with a valid signal asserting once the data is stable.

Project Scope & Contributions

This project was a structured hierarchical design exercise in Doulos's "Essential Digital Design Techniques" course, where the top-level of the design integrates different subcomponents as seen in Figure 1. The top-level design module, finite state machine, testbench, and behavioural memory model were provided.

My specific contributions to the design include:

  • Synchronous Modulo-6 Counter(Counter): Designed the Register Transfer Level (RTL) for the synchronous modulo-6 counter, which is instantiated and integrated as both random_counter and address_counter in the top-level design module.
  • Synchronizer: Designed a two-flop synchronizer to reduce the probability that metastability from the asynchronous roll input propagates into the FSM.
  • APB Manager-Side Read Control and Memory Integration: Implemented the setup, access and idle control logic for zero-wait-state APB reads and integrated it with the course provided behavioural memory subordinate and segment-output path.

Note: RTL designs not authored by me are excluded from this repository for copyright compliance.

image

Figure 1: Project Architecture Block Diagram (Source: Essential Digital Design Techniques, Doulos).

Behavioural Memory Model Features

  • Functions as a 7-segment font lookup table which stores the mapped word encodings of a rolled die value.
  • Utilizes the APB protocol for its read transactions.
  • Stores word encodings in 8-byte blocks of 7-segment visual display patterns.

Synchronous Modulo-6 Counter Features

The synchronous modulo-6 counter (Counter) increments on the rising edge of clk and wraps back around to its initial value.

  1. Instance 1 (Pseudorandom Generator / random_counter):
    • Continuously cycles through values to simulate a rolling die.
    • Freezes on its current count when a roll is initiated (random_value_enable = 0).
    • This frozen state becomes random_value, serving as the 3-bit memory block selector for the selected die value.
image

Figure 2a: random_counter waveform showing continuous incrementing and value freezing when disabled.

  1. Instance 2 (Offset Indexing / address_counter):
    • Remains idle until the FSM initiates the display read sequence.
    • Increments on clock edges (address_counter_enable = 1) to step through characters of the selected die word.
    • This incrementing state becomes address_offset, serving as the lower 3 bits (byte offset index) of the memory lookup.
image

Figure 2b: address_counter waveform demonstrating idle holding and sequential address stepping when enabled.

Top-Level Design Features

1. Top-Level Input/Output Ports

Inputs

  • Global System Clock: The primary timing reference for the top-level design and subcomponents.
  • Asynchronous Reset: Initializes the resettable sequential blocks, including the FSM, modulo-6 counter, and behavioural memory model, to their defined startup states.
  • Data Input: The asynchronous roll signal is synchronized to the system clock on the rising edge of clk before entering the FSM control logic.
Synchronizer : process(clk)
begin
    if rising_edge(clk) then
        Roll_Sync1 <= roll;
        Roll_Sync2 <= Roll_Sync1;
    end if;
end process;

Outputs

  • Segments: Each element of segments corresponds to a single seven-segment display element and displays the generated die roller value as an array of logic values.

  • Valid: Asserted when display output is stable and valid.

2. Moore Finite State Machine (FSM)

The FSM uses registered state with separate next-state and output-decoding logic, keeping Moore outputs independent of direct input changes and supporting predictable synchronous behaviour.

graph TB
    %% Define Block Shapes (Using standard text strings to fix the glitch)
    IN([Inputs])
    NEXT_LOGIC["Next-State Logic\nCombinational"]
    REG["State Register\n(Clocked Flip-Flops)"]
    STATE_DOT((( )))
    OUT_LOGIC["Output Logic\nCombinational"]
    OUT([Outputs])

    %% Main Forward Path
    IN --> NEXT_LOGIC
    NEXT_LOGIC -->|next_state| REG
    
    %% State line exits the register and hits the wire junction split
    REG -->|state| STATE_DOT
    
    %% Junction splits into the Output Logic and the Feedback Loop
    STATE_DOT --> OUT_LOGIC
    OUT_LOGIC --> OUT
    
    %% The True Feedback Loop
    STATE_DOT ==>|state feedback loop| NEXT_LOGIC

    %% Direct Styling
    style STATE_DOT fill:#333,stroke:#333
    style IN fill:#eaeaea,stroke:#333,stroke-width:1px
    style NEXT_LOGIC fill:#d4e6f1,stroke:#2980b9,stroke-width:2px
    style REG fill:#d4e6f1,stroke:#2980b9,stroke-width:2px
    style OUT_LOGIC fill:#d4e6f1,stroke:#2980b9,stroke-width:2px
    style OUT fill:#eaeaea,stroke:#333,stroke-width:1px
Loading

Figure 3a: Synchronous Moore FSM Block Diagram

The operational behavior of the 5-state FSM is mapped out in the state diagram below.

stateDiagram-v2
    direction TB

    [*] --> initialization : Asynchronous reset

    state "Initialization" as initialization
    state "Start Reading" as start_reading
    state "Continue Reading" as continue_reading
    state "Save Data" as save_data
    state "Output Segments" as output_segments

    note right of initialization
        Moore outputs:
        random_value_enable = 1
    end note

    note right of start_reading
        Moore outputs:
        APB_1st_Cycle = 1
        random_value_enable = 0
        address_counter_enable = 0
    end note

    note right of continue_reading
        Moore outputs:
        APB_2nd_Cycle = 1
        address_counter_enable = 1
        random_value_enable = 0
    end note

    note right of save_data
        Moore outputs:
        APB_save_data = 1
        random_value_enable = 0
    end note

    note right of output_segments
        Moore outputs:
        valid = 1
        address_counter_enable = 1
        random_value_enable = 1
    end note

    initialization --> start_reading : Roll_Sync2 = '1'
    initialization --> initialization : Roll_Sync2 = '0'

    start_reading --> continue_reading : Unconditional
    continue_reading --> save_data : Unconditional

    save_data --> start_reading : read_another = '1'
    save_data --> output_segments : read_another = '0'

    output_segments --> start_reading : Roll_Sync2 = '1'
    output_segments --> initialization : Roll_Sync2 = '0'
Loading

Figure 3b: Five-State Moore FSM State Diagram

State Description Table

The table below details the exact behavioural purpose of each operational state and the corresponding transition requirements:

State Name System Activity (What the Hardware is Doing) Transition Condition (How it leaves this state)
initialization Enables random_value_enable = 1 to cycle the pseudorandom generator while holding APB setup lines idle and data flags invalid. Moves to start_reading if data input Roll_Sync2 goes high; otherwise, it remains in this idle loop.
start_reading Triggers the 1st cycle of the APB read transaction control signal (APB_1st_Cycle) and freezes the random generator control signal (random_value_enable = 0). Automatically advances to continue_reading on the very next clock edge (Unconditional).
continue_reading Asserts the second cycle of the APB read transaction control signal (APB_2nd_Cycle) and triggers the offset indexing control signal address_counter_enable = 1. Automatically advances to save_data on the very next clock edge (Unconditional).
save_data Asserts the data save flag (APB_save_data) to store incoming data bus signals into internal registers. Loops back to start_reading if the read_another boundary check passes. Otherwise, it moves to output_segments.
output_segments Asserts the data valid output flag, re-enables the random_counter, and continues driving the address_counter. Loops directly back to start_reading if data input (Roll_Sync2) is high. Otherwise, returns to initialization.

3. Integration of Instance 1 & 2 of Synchronous Modulo-6 Counter

Instance 1 (random_counter):

random_counter :
entity work.Counter(RTL)
port map (Reset => reset,
          Clock => clk,
          Enable => random_value_enable,
          Q => random_value);

Instance 2 (address_counter):

address_counter :
entity work.Counter(RTL)
port map (Reset => reset,
          Clock => clk,
          Enable => address_counter_enable,
          Q => address_offset);

4. APB Manager-Side Read Control and Memory Integration

Implemented the setup, access and idle control logic for zero-wait-state APB reads and integrated it with the course provided behavioural memory subordinate and segment-output path.

The top-level design uses glue logic to concatenate a 2-bit vector with random_value and address_offset to form the full target address (read_address) for memory lookups.

Behavioural Memory Model Integration

  mem1 :
    entity work.memory(behav_mem)
    port map (reset => reset,
              pclk => clk,
              penable => penable,
              psel => psel,
              pwrite => pwrite,
              paddr => paddr,
              pwdata => pwdata,
              prdata => prdata,
              pready => pready );

APB Manager 1st, 2nd, and idle cycles read transaction integrations

The manager executes read transactions using APB timing protocol:

  • 1st Cycle (Setup Phase / APB_1st_Cycle): psel is asserted while penable remains low, to signal transaction initiation. Simultaneously, subordinate selection (psel = '1'), read mode (pwrite = '0'), and address (paddr = read_address) are presented to the bus.
  • 2nd Cycle (Access Phase / APB_2nd_Cycle): penable is asserted high ('1') while control signals (psel, paddr) remain valid. The memory subordinate drives character data onto prdata during this phase. pwdata remains inactive.
  • PREADY & Wait States: Operates on a zero wait-state model where pready must remain '1'. An internal assertion halts simulation (severity failure) if pready goes low, ensuring fixed 2-cycle completion.
  • Idle State: During idle, psel is low, so no APB transaction is active; this implementation leaves penable high until the next setup phase.
 APB_Control :
  process(APB_1st_Cycle, APB_2nd_Cycle, read_address)
  begin

    -- APB signals 1st cycle
    if APB_1st_Cycle = '1' then
      penable <= '0';
      psel <= '1';
      pwrite <= '0';
      paddr <= read_address;
      pwdata <= (others => '0');

    -- APB signals 2nd cycle
    elsif APB_2nd_Cycle = '1' then
      penable <= '1';
      psel <= '1';
      pwrite <= '0';
      paddr <= read_address;
      pwdata <= (others => '0');

    -- APB signals idle cycle
    else
      penable <= '1';
      psel <= '0';
      pwrite <= '0';
      paddr <= (others => '0');
      pwdata <= (others => '0');
    end if;
  end process APB_Control;

Testbench

The course provided testbench generates twenty roll transactions. I used its simulator output to verify the operation of my counter, synchronizer and APB integration within the complete system.

image

Figure 4: Word encodings of the random die roll value.


Repository Structure

Digital-Design/
├── .gitignore                #  Simulator generated files and directories
├── README.md                 # Project description
└── VHDL/
    └── die/                 # Specific contribution module
        ├── Counter.vhd       # Synchronous modulo-6 counter module
        └── Run.do            # Executes simulation workflow but depends on excluded course files                                     

Requirements

QuestaSim/ModelSim or another compatible VHDL simulator

VHDL-2008 support

Course provided source and testbench files for full system simulation


Local Simulation Workflow

Clone the repository:

git clone https://github.com/DamiProject/Digital-Design.git
cd Digital-Design/VHDL/die

Reproducibility Note: The complete design cannot be compiled directly from this repository because the course provided top-level module, FSM, memory model and testbench are excluded for copyright compliance. This repository contains only the RTL authored by me, along with selected integration excerpts and simulation evidence demonstrating its operation within the complete system.

Author

Damilola Awotunde

MEng, Communications & Signal Processing - Western University | LinkedIn

About

VHDL RTL design exercises covering counters, synchronization, FSM control and APB integration.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages