You are an expert Verilog hardware designer working on a complete FPGA or ASIC project. You are given the full source code of a Verilog project. One of the modules in the project is incomplete — its implementation is missing and marked with:

// >>> Module Implementation Begin

// <<< Module Implementation End

Your task is to complete the missing implementation so that the entire project functions correctly. You must infer what the missing module or logic is supposed to do by analyzing the rest of the codebase: module names, signal connections, instantiations, comments, and usage patterns.

Follow these rules:

1. Only generate Verilog code to go between the `// >>> Module Implementation Begin` and `// <<< Module Implementation End` comments.
2. Use Verilog-2001 syntax. Ensure the code is synthesizable.
3. Assume the goal is a working, integrated hardware design — your code must make the whole system function as intended.
4. Analyze the naming, I/O ports, and how the module is instantiated or used in other parts of the project.
5. Implement correct behavior based on design context. Do not guess randomly — reason it out.
6. Avoid vendor-specific features unless explicitly required.
7. Do not output comments, explanation, or anything outside the required code region unless explicitly asked.

Your output should contain **only the Verilog code** that fits inside the marked region.

/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_brailliance (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

    // Internal reset signal (active high, inverted from rst_n)
    wire reset = ~rst_n;

    // Internal wire for reader1_out from braille_converter_top
    wire [7:0] reader1_out;

    // Instantiate the braille_converter_top module
    braille_converter_top braille_top_inst (
        .clk(clk),               // Clock comes from the template's clock input
        .reset(reset),           // Reset (active-high) from inverted rst_n
        .next(ui_in[0]),         // 'next' signal is now mapped to ui_in[0]
        .reader1_out(reader1_out) // Internal wire reader1_out connected to the output of the braille converter
    );

    // Assign the output reader1_out from braille_converter_top to uo_out
    assign uo_out = reader1_out;

    // Assign unused IO pins to 0
    assign uio_out = 8'b0;        // All unused IOs set to 0
    assign uio_oe  = 8'b0;        // Set IOs in input mode (0=input)

    // List all unused inputs to prevent warnings
    wire _unused = &{ena, uio_in, ui_in[7:1], 1'b0};  // Updated to account for ui_in[0] being used

endmodule


module braille_converter (
    input clk,                    // System clock
    input reset,                  // System reset
    input [7:0] mem_dout,         // Memory data input (ASCII characters)
    output reg [7:0] braille_out, // 6-bit Braille code output
    output reg braille_valid,     // Data valid signal
    output reg [7:0] mem_addr,    // Memory address for reading data
    output reg [7:0] braille_size // size of output braille code
);

// Internal registers and counters
reg [7:0] ascii_size;              // Size of the data to convert
reg [7:0] current_ascii_size;      // Internal register to track size calculation
reg [7:0] current_braille_size;
reg indi;                    // Indicator for capital letters/digits
reg size_done;               // Flag to indicate size calculation is complete

// Braille conversion function (abbreviated)
function [7:0] ascii_to_braille;
    input [7:0] ascii;
    begin
        case (ascii)
	    // Mapping for uppercase letters A-Z
            8'd65: ascii_to_braille = 8'b00100000; // A -> 0x20
            8'd66: ascii_to_braille = 8'b00101000; // B -> 0x28
            8'd67: ascii_to_braille = 8'b00110000; // C -> 0x30
            8'd68: ascii_to_braille = 8'b00110100; // D -> 0x34
            8'd69: ascii_to_braille = 8'b00100100; // E -> 0x24
            8'd70: ascii_to_braille = 8'b00111000; // F -> 0x38
            8'd71: ascii_to_braille = 8'b00111100; // G -> 0x3C
            8'd72: ascii_to_braille = 8'b00101100; // H -> 0x2C
            8'd73: ascii_to_braille = 8'b00011000; // I -> 0x18
            8'd74: ascii_to_braille = 8'b00011100; // J -> 0x1C
            8'd75: ascii_to_braille = 8'b00100010; // K -> 0x22
            8'd76: ascii_to_braille = 8'b00101010; // L -> 0x2A
            8'd77: ascii_to_braille = 8'b00110010; // M -> 0x32
            8'd78: ascii_to_braille = 8'b00110110; // N -> 0x36
            8'd79: ascii_to_braille = 8'b00100110; // O -> 0x26
            8'd80: ascii_to_braille = 8'b00111010; // P -> 0x3A
            8'd81: ascii_to_braille = 8'b00111110; // Q -> 0x3E
            8'd82: ascii_to_braille = 8'b00101110; // R -> 0x2E
            8'd83: ascii_to_braille = 8'b00011010; // S -> 0x1A
            8'd84: ascii_to_braille = 8'b00011110; // T -> 0x1E
            8'd85: ascii_to_braille = 8'b00100011; // U -> 0x23
            8'd86: ascii_to_braille = 8'b00101011; // V -> 0x2B
            8'd87: ascii_to_braille = 8'b00011101; // W -> 0x1D
            8'd88: ascii_to_braille = 8'b00110011; // X -> 0x33
            8'd89: ascii_to_braille = 8'b00110111; // Y -> 0x37
            8'd90: ascii_to_braille = 8'b00100111; // Z -> 0x27

            // Mapping for lowercase letters a-z
            8'd97: ascii_to_braille = 8'b00100000; // a -> 0x20
            8'd98: ascii_to_braille = 8'b00101000; // b -> 0x28
            8'd99: ascii_to_braille = 8'b00110000; // c -> 0x30
            8'd100: ascii_to_braille = 8'b00110100; // d -> 0x34
            8'd101: ascii_to_braille = 8'b00100100; // e -> 0x24
            8'd102: ascii_to_braille = 8'b00111000; // f -> 0x38
            8'd103: ascii_to_braille = 8'b00111100; // g -> 0x3C
            8'd104: ascii_to_braille = 8'b00101100; // h -> 0x2C
            8'd105: ascii_to_braille = 8'b00011000; // i -> 0x18
            8'd106: ascii_to_braille = 8'b00011100; // j -> 0x1C
            8'd107: ascii_to_braille = 8'b00100010; // k -> 0x22
            8'd108: ascii_to_braille = 8'b00101010; // l -> 0x2A
            8'd109: ascii_to_braille = 8'b00110010; // m -> 0x32
            8'd110: ascii_to_braille = 8'b00110110; // n -> 0x36
            8'd111: ascii_to_braille = 8'b00100110; // o -> 0x26
            8'd112: ascii_to_braille = 8'b00111010; // p -> 0x3A
            8'd113: ascii_to_braille = 8'b00111110; // q -> 0x3E
            8'd114: ascii_to_braille = 8'b00101110; // r -> 0x2E
            8'd115: ascii_to_braille = 8'b00011010; // s -> 0x1A
            8'd116: ascii_to_braille = 8'b00011110; // t -> 0x1E
            8'd117: ascii_to_braille = 8'b00100011; // u -> 0x23
            8'd118: ascii_to_braille = 8'b00101011; // v -> 0x2B
            8'd119: ascii_to_braille = 8'b00011101; // w -> 0x1D
            8'd120: ascii_to_braille = 8'b00110011; // x -> 0x33
            8'd121: ascii_to_braille = 8'b00110111; // y -> 0x37
            8'd122: ascii_to_braille = 8'b00100111; // z -> 0x27

            // Mapping for digits 0-9
            8'd48: ascii_to_braille = 8'b00001111; // 0 -> 0x0F
            8'd49: ascii_to_braille = 8'b00100000; // 1 -> 0x20
            8'd50: ascii_to_braille = 8'b00101000; // 2 -> 0x28
            8'd51: ascii_to_braille = 8'b00110000; // 3 -> 0x30
            8'd52: ascii_to_braille = 8'b00110100; // 4 -> 0x34
            8'd53: ascii_to_braille = 8'b00100100; // 5 -> 0x24
            8'd54: ascii_to_braille = 8'b00111000; // 6 -> 0x38
            8'd55: ascii_to_braille = 8'b00111100; // 7 -> 0x3C
            8'd56: ascii_to_braille = 8'b00101100; // 8 -> 0x2C
            8'd57: ascii_to_braille = 8'b00011000; // 9 -> 0x18

            // Mapping for common punctuation marks
            8'd32: ascii_to_braille = 8'b00000000; // Space -> 0x00
            8'd33: ascii_to_braille = 8'b00001110; // ! -> 0x0E
            8'd34: ascii_to_braille = 8'b00001010; // " -> 0x0A
            8'd35: ascii_to_braille = 8'b00010111; // # -> 0x2F
            8'd36: ascii_to_braille = 8'b00111001; // $ -> 0x39
            8'd37: ascii_to_braille = 8'b00110101; // % -> 0x35
            8'd38: ascii_to_braille = 8'b00101101; // & -> 0x2D
            8'd39: ascii_to_braille = 8'b00001000; // ' -> 0x08
            8'd40: ascii_to_braille = 8'b00011011; // ( -> 0x1B
            8'd41: ascii_to_braille = 8'b00011111; // ) -> 0x1F
            8'd42: ascii_to_braille = 8'b00100101; // * -> 0x25
            8'd43: ascii_to_braille = 8'b00010110; // + -> 0x16
            8'd44: ascii_to_braille = 8'b00000010; // , -> 0x02
            8'd45: ascii_to_braille = 8'b00001001; // - -> 0x09
            8'd46: ascii_to_braille = 8'b00000011; // . -> 0x03
            8'd47: ascii_to_braille = 8'b00010011; // / -> 0x13
            8'd58: ascii_to_braille = 8'b00010010; // : -> 0x12
            8'd59: ascii_to_braille = 8'b00011010; // ; -> 0x1A
            8'd60: ascii_to_braille = 8'b00010001; // < -> 0x
            default: ascii_to_braille = 8'b00000000; // Default (space)
        endcase
    end
endfunction

always @(posedge clk or negedge reset) begin
    if (!reset) begin
        // Resetting the internal variables
        mem_addr <= 0;
        current_ascii_size <= 0;
        ascii_size <= 0;
	current_braille_size <= 0;
	braille_size <= 0;
        braille_valid <= 0;
        size_done <= 0;
        indi <= 0;
	braille_out <= 0;
    end else begin
        if (!size_done) begin
            // Size calculation phase
            if (mem_dout == 8'd0 || mem_addr == 8'd255) begin
                // Finalize size when a zero character is detected
                ascii_size <= current_ascii_size;
	        braille_size <= current_braille_size;
                size_done <= 1;
	        braille_valid <= 1;
                mem_addr <= 0; // Reset mem_addr for the conversion phase
            end else begin
                // Accumulate size based on the type of character
                if (mem_dout >= 8'd65 && mem_dout <= 8'd90 || // Capital letters
                    mem_dout >= 8'd48 && mem_dout <= 8'd57) begin // Digits
                    //current_ascii_size <= current_ascii_size + 1;
	            current_braille_size <= current_braille_size + 2;
                end else begin
                    //current_ascii_size <= current_ascii_size + 1; // Lowercase or other characters
	            current_braille_size <= current_braille_size + 1;
                end
	            current_ascii_size <= current_ascii_size + 1;
                    mem_addr <= mem_addr + 1;
            end
        end else begin
            // Braille conversion phase
            braille_valid <= 0; // Reset valid signal at each clock cycle
            
            if (mem_addr < ascii_size) begin
                if (indi == 1) begin
                    // Output Braille for the current character (A-Z, 0-9)
                    braille_out <= ascii_to_braille(mem_dout);
                    mem_addr <= mem_addr + 1;
                    braille_valid <= 1;
                    indi <= 0;
                end else if (mem_dout >= 65 && mem_dout <= 90) begin
                    // Capital letter (A-Z) indicator
                    braille_out <= 8'b00000001;
                    braille_valid <= 1;
                    indi <= 1;
                end else if (mem_dout >= 48 && mem_dout <= 57) begin
                    // Digit (0-9) indicator
                    braille_out <= 8'b00010111;
                    braille_valid <= 1;
                    indi <= 1;
                end else begin
                    // Output Braille for the current character
                    braille_out <= ascii_to_braille(mem_dout);
                    mem_addr <= mem_addr + 1;
                    braille_valid <= 1;
                end
	    end
	    else begin
		    braille_out <= 0;
		    mem_addr <= mem_addr;
	    end
        end
    end
end

endmodule


module memory(
    input reset,
    input [7:0] mem_addr,        // 8-bit address to support 256 words, coming from size_calculator
    output reg [7:0] mem_dout    // Output data to size_calculator & braille_converter
);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




module reader (
    input clk,
    input reset,
    input [7:0] braille_out,      // Input data from braille_converter (8-bit)
    input [7:0] braille_size,     // Size of the data to be loaded (max 256)
    input braille_valid,          // Signal indicating data is valid
    input next,                   // Signal to load the next set of data
 
    output reg [7:0] reader1_out // Reader 1 output (8-bit)
);

    // States of the state machine
    parameter IDLE = 3'b000,
              LOADING = 3'b001,
              START_SIGNAL = 3'b010,
              SENDING = 3'b011,
              WAIT_NEXT = 3'b100,
              END_SIGNAL = 3'b101;

    reg [2:0] state, next_state;

    reg [7:0] buffer [0:255];       // Buffer to store up to 256 characters (8-bit)
    reg [7:0] buffer_index;         // Index to track buffer writing (8-bit to cover 256 entries)
    reg [7:0] read_addr;            // Read address for the current set of 4 characters
    reg [7:0] loaded_braille_size;  // Size of the loaded data (8-bit for up to 256 entries)

    reg next_prev;                  // Register to store previous state of 'next'
    reg next_sync;                  // Synchronized version of 'next'

    integer i;

    // Edge detection: detect falling edge of 'next'
    always @(posedge clk or negedge reset) begin
        if (!reset) begin
            next_prev <= 0;
            next_sync <= 0;
        end else begin
            next_prev <= next_sync;
            next_sync <= next;
        end
    end

    wire next_falling_edge = next_prev & ~next_sync;

    // State transition logic
    always @(posedge clk or negedge reset) begin
        if (!reset) begin
            state <= IDLE;
        end else begin
            state <= next_state;
        end
    end

    // Next state logic
    /* verilator lint_off CASEINCOMPLETE */
    always @(*) begin
        case (state)
            IDLE: begin
                if (braille_valid) begin
                    next_state = LOADING;
                end else begin
                    next_state = IDLE;
                end
            end
            LOADING: begin
                if (buffer_index < braille_size) begin
                    next_state = LOADING;
                end else begin
                    next_state = START_SIGNAL;  // Transition to START_SIGNAL after loading is done
                end
            end
            START_SIGNAL: begin
                next_state = SENDING;  // Move to SENDING state after displaying start signal
            end
            SENDING: begin
                if (next_falling_edge && read_addr < loaded_braille_size) begin
                    if (read_addr + 1 >= loaded_braille_size) begin
                        next_state = WAIT_NEXT;  // Move to WAIT_NEXT state if last set is reached
                    end else begin
                        next_state = SENDING;
                    end
                end else begin
                    next_state = SENDING;
                end
            end
            WAIT_NEXT: begin
                if (next_falling_edge) begin
                    next_state = END_SIGNAL;  // Transition to END_SIGNAL when next is pressed again
                end else begin
                    next_state = WAIT_NEXT;  // Stay in WAIT_NEXT until next is pressed
                end
            end
            END_SIGNAL: begin
                next_state = IDLE;  // Return to IDLE state after END_SIGNAL
            end
            default: next_state = IDLE;
        endcase
    end
    /* verilator lint_on CASEINCOMPLETE */

    // Sequential logic for loading data and sending data
    always @(posedge clk or negedge reset) begin
        if (!reset) begin
            // Reset all variables
            buffer_index <= 0;
            read_addr <= 0;
            loaded_braille_size <= 0;
            for (i = 0; i < 256; i = i + 1) begin
                //buffer[i] <= 8'b00000000;
		    buffer[i] = 8'b00000000; // changed for synthesis
            end
            reader1_out <= 0;
        end else begin
            case (state)
                IDLE: begin
                    if (braille_valid) begin
                        buffer_index <= 0;
                        read_addr <= 0;
                        loaded_braille_size <= braille_size;
                    end
                end
                LOADING: begin
                    if (braille_valid && buffer_index < braille_size) begin
                        buffer[buffer_index] <= braille_out;
                        buffer_index <= buffer_index + 1;
                    end
                end
                START_SIGNAL: begin
                    // Display start signal (00010111b, 17h) on all outputs
                    reader1_out <= 8'b00010111;
                end
                SENDING: begin
                    if (next_falling_edge && read_addr < loaded_braille_size) begin
                        // Output the current set of 4 characters
                        reader1_out <= buffer[read_addr];
                        // Move to the next set of 4 characters
                        read_addr <= read_addr + 1;
                    end
                end
                WAIT_NEXT: begin
                    // Keep the last set of data outputs or set an end signal here if desired
                end
                END_SIGNAL: begin
                    // Display 4 sets of '00000001'
                    reader1_out <= 8'b00000001;
                end
            endcase
        end
    end

endmodule


module braille_converter_top (
    input wire clk,
    input wire reset,
    input wire next,

    output wire [7:0] reader1_out
);

    wire [7:0] mem_dout;
    wire [7:0] mem_addr;
    wire [7:0] braille_size;
    wire [7:0] braille_out;
    wire braille_valid;

    // Instantiate the Braille Converter
    braille_converter cvt (
        .clk(clk),
        .reset(reset),
        .mem_dout(mem_dout),

	.mem_addr(mem_addr),
        .braille_out(braille_out),
	.braille_size(braille_size),
	.braille_valid(braille_valid)
    );

    // Instantiate the Memory Module
    memory mem (
	.reset(reset),
        .mem_addr(mem_addr),

        .mem_dout(mem_dout)
    );

    // Instantiate the Reader Module
    reader rdr (
        .clk(clk),
        .reset(reset),
        .braille_out(braille_out),
        .braille_size(braille_size),
        .braille_valid(braille_valid),
        .next(next),

        .reader1_out(reader1_out)
    );

endmodule


Reference solution:
rtl/generated.v: 
// Memory array with 256 words, each 8 bits wide
reg [7:0] memory [0:255];

integer i;

// Initialize memory, synthesizable in FPGA but not in ASIC
//initial begin
//    $readmemh("input.txt", memory); // Read data from a hex file into memory
//end

// Memory Initialization
always @(negedge reset) begin
	memory[0] <= 8'h54;
	memory[1] <= 8'h65;
	memory[2] <= 8'h78;
	memory[3] <= 8'h74;
	memory[4] <= 8'h20;
	memory[5] <= 8'h74;
	memory[6] <= 8'h6f;
	memory[7] <= 8'h20;
	memory[8] <= 8'h42;
	memory[9] <= 8'h72;
	memory[10] <= 8'h61;
	memory[11] <= 8'h69;
	memory[12] <= 8'h6c;
	memory[13] <= 8'h6c;
	memory[14] <= 8'h65;
	for (i = 15; i < 256; i = i + 1) begin
		memory[i] = 8'h00;
	end
end
	
// Memory read operation
always @(*) begin
    mem_dout = memory[mem_addr];  // Read data from memory
end