Skip to content

User Input

Diogo Valadares Reis dos Santos edited this page Aug 20, 2025 · 3 revisions

[← Previous Page | Next Page →]

User Input

User Input consists of 4 bytes, each representing a different device. These bytes can be accessed using the following instructions:

la t0 0x00fffffc
lb t0 t0 device_byte

Here, device_byte is a number between 0 and 3.

The Keyboard

The keyboard is responsible for reading input and transmitting it in ASCII format.

In Logisim Evolution, it is a native component that stores a string of characters and outputs the first typed character through a 7-bit output. This output is combined with an additional bit that indicates whether there are characters in the buffer. This bit is placed in the most significant position of the byte, effectively representing the sign of the number, which makes it easier to test whether the value is valid.

Whenever the keyboard receives a read signal, the first character is deleted from the buffer. This continues until the buffer is empty. The keyboard also transmits an external interrupt signal to the processor, allowing the currently running program to be interrupted so the available input can be processed immediately.

image

The Joystick

The joystick is a simple input device that allows directional control within the simulation. In the current version of the project, it is only available in the Logisim simulation.

image

Joystick data is accessed by reading the third byte of the user input. It returns the X and Y values in the format 0xXY. To use this data effectively, an additional processing step may be required to separate each axis from the byte.

The Switches

Switches are components that allow individual bit input through the second byte of the User Input. Like the joystick, this device is not available in the SystemVerilog simulation.

image

The Random Number Generator

Although not a user input device, the Random Number Generator is accessed through the first byte. It generates a new random value every time the user input word is read.

image

SystemVerilog Code

In SystemVerilog, these components cannot be accessed directly. To enable interaction, an external program was developed that facilitates communication with the simulation via a shared text file.

The image below shows this program, with the keyboard component highlighted:

image

Below is the code responsible for handling user input:

`timescale 1s/1s
module user_input #(
    parameter KEYBOARD_FILE = "keyboard.mem"
) (
    input read,
    input clock,
    input reset,
    output [31:0] data_out
);

integer file_ptr = 0;
integer char1, char2;  // Use integers to handle EOF (-1)
reg [31:0] data_reg;
reg [7:0] random;
reg [7:0] separator;   // Explicit register for separator

assign data_out = read ? data_reg : 32'hZ;

function automatic [3:0] hex_to_nibble(input [7:0] c);
    case(c)
        "0": return 4'h0;
        "1": return 4'h1;
        "2": return 4'h2;
        "3": return 4'h3;
        "4": return 4'h4;
        "5": return 4'h5;
        "6": return 4'h6;
        "7": return 4'h7;
        "8": return 4'h8;
        "9": return 4'h9;
        "A","a": return 4'hA;
        "B","b": return 4'hB;
        "C","c": return 4'hC;
        "D","d": return 4'hD;
        "E","e": return 4'hE;
        "F","f": return 4'hF;
        default: return 4'hF;
    endcase
endfunction

always @(negedge clock) begin
    if (reset) begin
        // Close file if already open
        if (file_ptr) begin
            $fclose(file_ptr);
            file_ptr = 0;
        end
        // Open in read mode
        file_ptr = $fopen(KEYBOARD_FILE, "r");
        if (file_ptr == 0)
            $display("Error: Cannot open %s", KEYBOARD_FILE);
        data_reg = 32'hFF000000;  // Default reset value
    end
    else if (read) begin
        random = $random;  // Get new random value

        if (file_ptr == 0) begin
            // File not open - use default
            data_reg = {8'hFF, 16'h0, random};
        end
        else begin
            char1 = $fgetc(file_ptr);  // Read first char

            if (char1 == -1) begin  // Check EOF
                data_reg = {8'hFF, 16'h0, random};
            end
            else begin
                char2 = $fgetc(file_ptr);  // Read second char

                if (char2 == -1) begin
                    // Single character case
                    data_reg = {
                        {hex_to_nibble(char1[7:0]), 4'h0},
                        16'h0,
                        random
                    };
                end
                else begin
                    // Read separator normally
                    separator = $fgetc(file_ptr);  // Discard separator

                    // Process both characters
                    data_reg = {
                        {hex_to_nibble(char1[7:0]), hex_to_nibble(char2[7:0])},
                        16'h0,
                        random
                    };
                end
            end
        end
    end
end

endmodule

Clone this wiki locally