ECE 271 Final Project

These students agreed to their work being shared for the benefit of future course offerings.

June 2017 Contents

1 Introduction 3 1.1 Project Deliverables...... 3

2 High Level Description4 2.1 Top Level Hardware Diagram...... 4 2.2 Top Level HDL Schematic...... 5

3 Controller Descriptions6 3.1 Button Board Description...... 6 3.2 N64 Controller Description...... 6 3.3 VCR Controller Description...... 7 3.4 NES and SNES Input...... 8 3.4.1 NES Controller...... 8 3.4.2 SNES Controller...... 9

4 HDL Components 10 4.1 Top Module Components...... 10 4.1.1 Active Controller Selector...... 11 4.1.2 Active Console Selector...... 12 4.1.3 1MHz Clock Divider Module...... 12 4.2 Button Board Top Module...... 12 4.3 N64 Button Reader (Top Module)...... 13 4.3.1 N64 Counter Module...... 13 4.3.2 N64 Flip Data Mode Module...... 14 4.3.3 N64 Read Module...... 14 4.3.4 N64 Send CMD Module...... 14 4.3.5 N64 Send CMD Trigger Module...... 15 4.3.6 N64 Button Decoder...... 15 4.4 VCR Remote Top Module, Remote Translator...... 16 4.4.1 Negative Counter Module...... 16 4.4.2 Positive Counter Module...... 17 4.4.3 Button Identification Module...... 17 4.4.4 Signal Interpreter Module...... 17 4.5 Shared Modules...... 18 4.5.1 Shift Register SIPO...... 18 4.5.2 12-bit Parallel-In-Serial-Out Shift Register Module...... 18 4.5.3 8-bit Parallel-In-Serial-Out Shift Register Module...... 19

5 Appendix 19 5.1 Design Synthesis and Analysis...... 19 5.2 Source Code...... 19 5.2.1 top_module...... 19 5.2.2 n64_button_reader...... 21 5.2.3 n64_send_cmd...... 22 5.2.4 n64_read...... 23 5.2.5 n64_counter...... 24 5.2.6 flip_data_mode...... 24 5.2.7 n64_send_cmd_trigger...... 25 5.2.8 shift_register_SIPO...... 25 5.2.9 shift_register_PISO...... 26 5.2.10 shift_register_PISO_12bit...... 26 5.2.11 remote_translator...... 27 5.2.12 signal_interpreter...... 27 5.2.13 positive_counter...... 28 5.2.14 negative_counter...... 29 5.2.15 button_identification...... 29 5.2.16 active_console...... 30

1 5.2.17 active_controller...... 30 5.2.18 clock_counter_1MHz...... 31 5.3 Simulation Results...... 32 5.3.1 n64_send_cmd Module Simulation...... 32 5.3.2 n64_counter Module Simulation...... 33 5.3.3 flip_data_mode Module Simulation...... 34 5.3.4 n64_send_cmd_trigger Module Simulation...... 34 5.3.5 shift_register_SIPO Module Simulation...... 35 5.3.6 shift_register_PISO_8bit Module Simulation...... 35 5.3.7 remote_translator Module Simulation...... 36 5.3.8 signal_interpreter Module Simulation...... 38 5.3.9 positive_counter Module Simulation...... 39 5.3.10 negative_counter Module Simulation...... 41 5.3.11 button_identification Module Simulation...... 42 5.3.12 active_console Module Simulation...... 43 5.3.13 active_controller Module Simulation...... 43 5.3.14 clock_counter_1MHz Module Simulation...... 44

2 1 Introduction

Figure 1: An N64 controller. c Wikipedia, 2017.

The purpose of this project is to implement a digital logic design that is capable of using either a remote control, an N64 controller, or an eight push-button board (created in ECE272 lab) and apply functionality for a Entertainment System (NES) console or Super Nintendo Entertainment System (SNES) console. Neither of these devices would traditionally be functional with an NES or SNES console, but by designing logic that can shift the inputs of the controller as well as using several decoders and other modules, an output can be given to the system. Two decoders will be implemented to convert the N64 controller data and the remote data respectively into proper NES or SNES logic input. The data sent from the button board will not require such, and all three will be factored into a multiplexer that will, based on input wires, select a controller and send its data to a de-multiplexer which will then select either the NES or SNES console. This project has been offered and completed by several prestigious organizations, such as the University of Michigan[1] and the University of California at Berkeley[2]. The N64 controller, according to the University of Michigan’s design manual, describes the interfacing of an N64 controller as a challenging but intriguing feat because of hardware considerations, data protocol, and overall complexity. The University of California at Berkeley’s lab instructions specify for technical instructions, such as how to serialize data between the N64 controller and the device acquiring it. Mapping the various codes are vital to success, but various signals, such as clock, reset, and the serial data line, are all equally important as they provide transmitting and receiving capabilities.

1.1 Project Deliverables

• Supports communication protocol from both the NES and SNES consoles. • Implements button board, N64 controller and VCR remote interface to emulate NES and SNES controller inputs • (Extra Feature) User can select input flow from the listed controllers and forward to console.

3 Figure 2: The Nintendo Entertainment System. c Wikipedia, 2017.

2 High Level Description

2.1 Top Level Hardware Diagram

Figure 3: Hardware Diagram of the Button Board, N64 Controller, VCR Remote, FPGA, and NES Console

Inputs: This reads signals from a VCR remote, a N64 controller, or a button board Outputs: This is the converted signal from a controller that is read by an NES or SNES con- sole. Description: As shown in the hardware diagram above, the button board, N64 controller, and VCR remote are all connected to the FPGA. The button board and FPGA are connected by pins J8,

4 J7, J6, J5, J4, J3, J2, J1 to pins 107, 106, 105, 104, 100, 99, 98, 97 respectively and GND to GND. Each of the pins on the button board correspond to a button which would be on a simple Nintendo controller: Up, Down, Left, Right, A, B, Start, and Select. The N64 and the FPGA are connected by VCC to 3.3V, Data to pin 69, and GND to GND respectively. The VCR sends a signal that the FPGA receives on pin 120. The FPGA is then connected to the NES console through pins 112, 111, 110, and 109 to Data, Clock, Latch, and Reset respectively.

2.2 Top Level HDL Schematic

Figure 4: Top module of the various module components, the button board, the N64 controller, the VCR remote, and the NES console

Inputs: This takes data from a VCR remote, a N64 controller, or a button board. Outputs: This is the converted signal from a controller that is read by an NES or SNES con- sole. Description: As shown in the top level HDL schematic above, the N64 controller and the VCR remote go into decoders that process information and prepare it to be read into the multiplexer module. The button board is able to take its raw input and read it into the multiplexer module. The multiplexer reads inputs of 8 bits, which is why the N64 controller and the remote have to be converted but the button board doesn’t (as by default, the button board already gives an 8-bit input). Then, with the selection of various inputs for the A and B wires, a controller will be chosen to be read for the NES or SNES console. A data bus wire is used to connect them together. A 4MHz oscillator is also implemented to account for timing and converted to a 1MHz signal. A clock divider is used to achieve this.

5 3 Controller Descriptions

3.1 Button Board Description

The push button board takes in an 8-bit bus, each bit corresponding to a button input. The buttons are active low, thus a 0 is sent to the FPGA when pressed and a 1 when not pressed. The 8-bit input is sent to a parallel-to-serial converter. This type of shift register will load 8 bits in parallel and then under a clock, shift each bit out of the register serially one bit at a time. The shift register has clock input, clk, from the NES, reset input, load input, an 8-bit parallel input, d, and a serial output, Sout [3]. An example of a shift register with a parallel load is shown in Figure 5.

Figure 5: Shift Register with Parallel Load, 2012

3.2 N64 Controller Description

Figure 6: The black box diagram for the N64 shows how each of the modules are interconnected.

The N64 controller connects to the FPGA through three connections: GND, Data, and VCC and can handle a maximum voltage of 3.6V. Figure 4 displays the communication protocol when the N64 is sending it’s data.

Figure 7: N64 Signal Shapes for Zero and One, 2012

6 Both signals have a period of 4µs. For zero, the signal is low for 3µs and high for 1µs. For one, the signal is low for 1µs and high for 3µs. The controller sends what is represented as a 33 bit response which gives the status of all the buttons on the controller, the position of the , and a stop bit. Dissimilar from the button board, the buttons on the N64 controller are active high, thus a 1 is read when a button is pressed and a 0 when not pressed. Figure 5 shows the default positions of each of the button states. 0 A 9 Not Used 32 Stop Bit 1 B 10 L 2 Z 11 R 3 Start 12 C-Up 4 Up 13 C-Down 5 Down 14 C-Left 6 Left 15 C-Right 7 Right 16-23 X-Axis 8 Not Used 24-32 Y-Axis When the A button is pressed, the 1st element of this output array will read 1. The joystick’s position is determined by the two bytes given by the X- and Y-Axis. The N64 will send the 33-bit data array once a 9-bit polling signal is sent from the FPGA. The only polling signal that we are concerned with is 0b000000011 [4].

3.3 VCR Controller Description

The VCR remote communicates information with the NEC IR protocol. The information is sent in a serial list, with a long active period to signal the start of the transmission. There are then two possible wait times, 4.5µs or 2.25µs. The longer pulse signifies a new button was pressed, the 2.25µs pulse says the same button was pressed. After the 4.5µs pulse the remote sends 32 bits of information, with a zero or a one being determined by the time in between pulses [5].

Figure 8: Description of NEC Transmission Protocol [5]

The first 16-bits are specific to the remote and do not impact button selection. With this infor- mation the button can be identified using just the last eight bits. Unlike the other controllers the remote can only process one button being pressed at a time [5].

7 3.4 NES and SNES Input

3.4.1 NES Controller

The button data is stored in an 8-bit shift register with two input pins: CLK and LATCH, and one DATA output pin. NES buttons are pull-up resistors, and will send a 1 to the register when not pressed. The buttons on the NES are assigned a value from 0 to 7: 1 A 5 Up 2 B 6 Down 3 Select 7 Left 4 Start 8 Right The least significant bit in an 8-bit binary number corresponds to A and continues down this list. For the shift register to grab the data from the buttons a starting signal must be sent on the LATCH pin in the sequence LOW-HIGH-LOW. One this transition is made on LATCH, the current state of the buttons it latched into the shift register. A NES protocol is that the transition LATCH high must be kept for 12 µs. After the data is latched, the first button’s state becomes available on the DATA line. The DATA line will scroll to the next value every clock pulse. Example: 1. The A button is pressed, and sends a 0 on its wire. 2. The LATCH pulses LOW-HIGH-LOW and the data 11111110 (everything not pressed but A) is copied into the shift register. 3. The data line reads and saves the least significant bit in the register. 4. Pulse the clock so the shift register shifts its bits to the right (11111110 becomes x1111111) and now read the least significant bit and save its state. 5. Repeat step 4 six more times to read all the button states. 6. We now have all the button sava for one LATCH cycle. Repeat every frame we want to take data from.

Figure 9: Schematic of the NES controller board [6]

8 3.4.2 SNES Controller

The SNES controller acts very similar to the NES controller. The main difference being that now the shift register is 16 bits wide instead of 8. The buttons assignments are as follows: 1 B 9 A 2 Y 10 X 3 Select 11 L 4 Start 12 R 5 Up 13 none, always high 6 Down 14 none, always high 7 Left 15 none, always high 8 Right 16 none, always high Since the SNES controller has twelve buttons, the last four bits in the shift register (and the last four clock cycles) go unused and always remain high. Another big difference in the SNES controller is that since the B button is latches first it has to be on the falling edge of the clock since the clock is normally HIGH, and its first transition is from HIGH to LOW. Data for the other eleven buttons is driven at the rising edge of the remaining clock ticks.

Figure 10: Waveforms for the LATCH cycle of the SNES controller. [7]

9 4 HDL Components

4.1 Top Module Components

Figure 11: Top Module schematic for the entire project.

Input: This takes in data from the VCR Remote, N64 controller, and the push button board which comes from the user. Selection inputs include a 2-bit bus to select the controller to use and a 1-bit data line to select the console. Inputs to control the data output include an active low reset for the clock counter and an NES reset, Latch, and clock for transmitting the parsed data to the NES console. Output: This module outputs an 8-bit data line to the NES console or a 12-bit data line to the SNES module. Description: This is the top module for the entire project. It contains instantiations for the built in 4.29MHz oscillator, a 1MHz clock counter, an N64 button reader, a VCR Remote reader, an active controller selector, an active console selector, an 8-bit PISO shift register, 12-bit PISO shift register, and a SIPO shift register.

10 4.1.1 Active Controller Selector

Figure 12: Active Controller Selector

Inputs: This reads a 2-bit value. Based on this 2-bit value, this selector will read in data from either the remote, N64 controller, or button board. Outputs: This sends a 12-bit value that is compatible with the NES and SNES console. Description: The purpose of this selector is to chose what data is sent to the console. The 8-bit data will come from either the VCR remote, the N64 controller, or the button board. This selector takes in two inputs, select_a and select_b. If select_a gets 0 and select_b gets 0, remote_data will be outputted on a 12-bit data bus to a demultiplexer which will select the console to send the data to. If select_a gets 0 and select_b gets 1, n64_data will be outputted to the console selector. If select_a gets 1 and select_b gets 0, buttons, data from the button board, will be outputted to the console selector.

11 4.1.2 Active Console Selector

Figure 13: Active Console Selector Module Diagram.

Inputs: This reads a 12-bit input from the controller selector. Outputs: This sends 12-bit data line to the NES or SNES respectively. Description: The data which gets outputted from the controller selector is sent to the console selector. The console selector is implemented as a demultiplexer in which one data line comes in and one select bit selects which of the two consoles (NES or SNES) to output the data to. The data will come in on a 12-bit data bus with the least significant 8-bits holding the data from the controller. The remaining upper four bits, bits 8-11, will hold a value ’1’ meaning the buttons connected to those bits are not pressed. These excess bits are transmitted in case the data is routed to the SNES which takes a 12-bit input.

4.1.3 1MHz Clock Divider Module

Figure 14: 1MHz Clock Counter Module Diagram.

Inputs: This reads a 4MHz clock signal and an active low reset. Outputs: A 1MHz clock signal is outputted every 3 clock cycles. Description: This clock divider divides a 4MHz clock signal into a 1MHz signal. The period for the 4MHz clock (4.29MHz is the actual frequency outputted by the oscillator on the MachXO3LF this project is intended to run on) is 233ns. This means that the resulting period of the 1MHz clock should be 932ns.

4.2 Button Board Top Module

The solution is designed such that a module is not necessary for the button board. The 8-bit button board input can be forwarded to the controller select MUX.

12 4.3 N64 Button Reader (Top Module)

Figure 15: N64 Button Reader Top Module.

Inputs: This receives a 4MHz and 1MHz clock signal. Input/Outputs: n64_data is the serial line for communication with the N64 controller. Outputs: The n64 returns 32 bits of button state but we are only interested in the first eight, the buttons that correspond to the SNES buttons. Description: This is the top module for the n64 controller. This top module instantiates and uses modules that transmit, receive, parse, and output data for an NES console. This module receives inputs from a 4Mhz and 1Mhz clock that govern reading data from the n64 controller and sending the "send button state" command respectively. Input/output is received and sent as a serial line for communication with the n64 controller. An 8-bit bus and a clock signal is outputted from the n64 controller.

4.3.1 N64 Counter Module

Figure 16: N64 counter module.

Inputs: This receives a clock and reset signal. When reset is active, count is set to M. Outputs: This outputs a signal, done, when the counter is completed, when counter is 0. Description: This counter decrements its contents by one on the clock edge. Once the counter’s contents are empty, all zeros, done flag is activated. This flag does not reset the counter, but it is a flag to transition to the next state of the reader.

13 4.3.2 N64 Flip Data Mode Module

Figure 17: Flip Data Mode Module.

Inputs: This receives a read_start and enable_output signal. The enable_output signal is active when the FPGA is transmitting to the N64 controller and read_start is active when the N64 controller is transmitting to the FPGA. Outputs: This sends a receive_trigger signal that is active on the rising edge of read_start signal. Receive_trigger turns off the N64 data transmission. Description: This module switches the logic that enables sending an inputted command from the N64 controller. It also enables reading data from the controller to the FPGA.

4.3.3 N64 Read Module

Figure 18: N64 Read Module Diagram.

Inputs: This receives a 4MHz clock signal, data input line from the n64 controller, and an enable signal. Enable only samples when it is active. Outputs: This sends a 32-bit register that corresponds with the n64 controller’s state. The con- troller’s clock is also outputted and is sampled at negative edge. Description: This module enables the n64 controller to read the command parser and receiver.

4.3.4 N64 Send CMD Module

Figure 19: N64 Send CMD Module Diagram.

Inputs: This receives a 1MHz clock signal and a read start signal that triggers when to start the "send read command".

14 Outputs: This outputs an enable signal that triggers when to enable reading the output of the n64 data line and a dout signal that corresponds to the data line for the n64 controller’s output. Description: This module sends a command to the n64 controller to send the button status.

4.3.5 N64 Send CMD Trigger Module

Figure 20: N64 Send CMD Trigger Module Diagram.

Inputs: This receives a clock signal. Outputs: This sends a trigger signal. The trigger is activated every rising clock edge. Description: This is an infinite counter that signals every time it reaches 0 by assigning output trigger to 1. This is the module that controls the polling signal.

4.3.6 N64 Button Decoder

Figure 21: N64 Button Decoder Module Diagram.

Inputs: button_state, a 32-bit representation of the n64 controller’s button state. Outputs: nes_output, an 8-bit truncated version of the n64_button state. Description: This module simply takes the output from the n64 controller and selects only the bits that correspond to the buttons that the N64 can read.

15 4.4 VCR Remote Top Module, Remote Translator

Figure 22: VCR top module diagram.

Input: This takes in serial input from an IR receiver, a reset signal, and a 1MHz clock signal. Output: This outputs a 12-bit bus to the shift register. Description: This module receives a serial input from an IR receiver and outputs a 12-bit bus to go to the NES or SNES console. Machine must be reset before using.

4.4.1 Negative Counter Module

Figure 23: Negative Counter Module.

Inputs: This reads data from the remote and a 1MHz clock signal. Outputs: [13:0] final_count will hold the final value of the counter. Description: This counter begins counting when remote data goes to zero and will reset when remote data goes to one. The counter will never be above 9000, so 214 = 16384 was chosen as the maximum possible value. The value is passed only if it is above the threshold to trigger the state machine.

16 4.4.2 Positive Counter Module

Figure 24: Positive Counter Module.

Inputs: This reads data from the remote and a 1MHz clock signal. Outputs: [13:0] final_count will hold the final value of the counter. Description: This counter begins counting when remote data goes to one and will reset when remote data goes to zero. This counter will also never be above 9000, so 214 = 16384 was chosen as the maximum possible value. This is the opposite of the negative counter.

4.4.3 Button Identification Module

Figure 25: Button identification module.

Inputs: This takes in a 32-bit bus that represents the remote’s signal. Outputs: This outputs a 12-bit signal that can be interpreted by the NES or SNES console. Description: This module takes a 32-bit string and processes it so that it is converted into a form that is usable by the NES or SNES console. The order of the buttons comes from Jim Christy [7].

4.4.4 Signal Interpreter Module

Figure 26: Signal interpreter module diagram.

Input: This takes in the two 13-bit final counts from both the positive and negative counters as well as a reset and 1MHz clock signal.

17 Output: This outputs a 32-bit parallel bus. Description: This receives the counts from the positive and negative counters. It decides to pass a 1 or 0 based on how long the pulse is. The basic template for a state machine was based on an example in the class textbook [3].

4.5 Shared Modules

4.5.1 Shift Register SIPO

Figure 27: Shift Register Serial-In-Parallel Module Diagram.

Parameters: "Width" specifies the width of the Parallel input while "init_val" dictates what value to load onto the register by default. Inputs: CLK and enable to tell the module to shift bits, and ’serial_in’ is where the data is read from. Outputs: Data is a variably sized parallel output. Description: This module can load an initial value and shift them out, emulating a parallel to serial shift register, as well as taking a serial input and shifting it into data.

4.5.2 12-bit Parallel-In-Serial-Out Shift Register Module

Figure 28: Shift Register PISO module for 12 bits.

Inputs: This reads an 12-bit data input and a clock, reset, and load signal. Outputs: This outputs the 12-bit bus serially. Description: This shift register is loaded with 12-bits of data simultaneously and this data is shifted out of the register bit-by-bit based on the clock. This shift register is necessary because data from the controller is sent in parallel, but the NES and SNES reads data serially.

18 4.5.3 8-bit Parallel-In-Serial-Out Shift Register Module

Figure 29: Shift Register Module Diagram for the Parallel-In-Serial-Out regard.

Inputs: This reads an 8-bit data input and a clock, reset, and load signal. Outputs: This outputs the 8-bit bus serially. Description: This shift register is loaded with 8-bits of data simultaneously and this data is shifted out of the register bit-by-bit based on the clock. This shift register is necessary because data from the controller is sent in parallel, but the NES and SNES reads data serially.

5 Appendix

5.1 Design Synthesis and Analysis

Figure 30: Top level Synplify Pro

Figure 31: Synplify Pro synthesis analysis, specifies the number of LUTs in the design

According to SynplifyPro synthesis, the design would take up 21 LUTs, .3% of 6900 LUTs of non-volatile memory the MachX03 FPGA.

5.2 Source Code

5.2.1 top_module module top_module(input logic N64_data, input logic remote_data, input logic [7:0] buttons, input logic nes_clk, snes_clk, n64_clk,

19 input logic NES_latch, SNES_latch, input logic nes_reset, snes_reset, input logic remote_reset, input logic reset_n,//reset for clock_counter_1MHz input logic [1:0] controller_select, input logic console_select, output logic nes_output[7:0]//nes controller output data line output logic snes_output[11:0] );

l o g i c nes_data_bus; l o g i c clk_bus; l o g i c clk_4M; l o g i c clk_1M; l o g i c remote_selection;//12 − b i t data line from controller MUX to console DEMUX l o g i c [7:0] N64_state_bus;

l o g i c [11:0] to_NES_12; l o g i c [7:0] to_NES_8; l o g i c [11:0] to_SNES; l o g i c [11:0] to_active_controller;

a s s i g n to_NES_8= to_NES_12[7:0];

//TODO: //4 modules

//Instance of built in module to select 4.29MHz clock OSCH #("4.29") osc_int( .STDBY(1’b0),//Specifies active state .OSC(clk_4M),//Output 4.29MHz to clk_4M net .SEDSTDBY());//Leaves SEDSTDBY pin unconnected

//Instantiation of1MHz clock divider (4MHz input,1MHz output) clock_counter_1MHz clk_divider( . clk_4MHz(clk_4M), .reset_n(reset_n), . clk_1MHz(clk_1M));

//Active Controller selector(MUX) active_controller( . remote_data(to_active_controller),//8 − b i t raw remote data input . N64_data(N64_state_bus),//8 − b i t raw N64 data input . button_data(buttons),//8 − b i t raw button input .select_bits(controller_select),//2 − b i t data input .selection(remote_selection)//Output 12 − b i t selection );

//Active Console selector(DEMUX) active_console console_select( . controller_selection(remote_selection), .select_bit(console_select),//Bit to select console . NES_console(to_NES_12),//12 − b i t data output . SNES_console(to_SNES)//12 − b i t data output );

shift_register_PISO_8bit NES( .clk(nes_clk), .reset(nes_reset), .load(NES_latch), .data(to_NES_8), .sout(nes_output) );

shift_register_PISO_12bit SNES( .clk(snes_clk), .reset(snes_reset), .load(SNES_latch), .data(to_SNES), .sout(snes_output) );

20 //N64 Controller Reader n64_button_reader N64_C( . clk_4M(clk_4M), . clk_1M(clk_1M), . n64_data(N64_data), . n64_button_state(N64_state_bus), . n64_controller_clk(n64_clk) );

//Remote Reader

remote_translator IR_translator( . serial_from_IR(remote_data), . OneMHz_clock(clk_1M), .reset(remote_reset), . to_NES_shift_register(to_active_controler) ); endmodule ./source/top_module.sv

5.2.2 n64_button_reader

// Top module for the n64 controller reader, instantiates and uses modules that // transmit, recieve, parse, and output button data for an NES // Author: Dan Van Horn // Inputs: // clk_4M.....4 MHz clock that governs reading data from the controller // clk_1M.....1 MHz clock that governs sending the"send button state" // command // Input/Output: // n64_data.... serial line for communication with the N64 controller // Outputs: // n64_button_state.....8 − b i t output, must be selected from standard 32 // return signal from N64 // N64_controller_clk... clock signal from the N64 controller module n64_button_reader( input logic clk_4M, input logic clk_1M, inout logic n64_data, output logic [7:0] n64_button_state, output logic n64_controller_clk);

l o g i c [31:0] n64_controller_state;// holds the full state of the controller l o g i c read_start;// trigger to start reading from the c o n t r o l l e r l o g i c enable_output;// active during data transmission to c o n t r o l l e r

// module to switch between read and send on n64_data // while we read from the n64, we assigna floating output l o g i c data_in, data_out; a s s i g n n64_data= read_start? data_out: 1’bZ;

// module to send read command N64_send_command fpga_to_n64( . clk_1M(clk_1M), . read_start(read_start), . enable_output(enable_output), .dout(data_out));

// module to trigger read from controller l o g i c receive; flip_data_mode flip( . read_start(read_start), . enable_output(enable_output), . receive_trigger(recieve));

// module to read from controller

21 n64_read n64_to_fgpa( . clk_4M(clk_4M), . n64_data(n64_data), . enable_recieve(recieve), . controller_status(n64_controller_state), . controller_clk());

// module to send periodic read signal n64_send_cmd_trigger trigger( .clk(clk_1M), .trigger(read_start));

//TODO: Createa module that takes the inputs from the n64 controller // and selects only the buttons necessary for the NES inputs, formatting // them accordingly. We could support SNEs output as well n64_to_nes_encoder encode_output( . n64_buttons(n64_controller_state), . nes_output(n64_button_state));

endmodule module n64_to_nes_encoder(input logic [31:0] n64_buttons, output logic [7:0] nes_output); always_comb begin // left nes_output[7] = n64_buttons[7]; // right nes_output[6] = n64_buttons[6]; // down nes_output[5] = n64_buttons[5]; // up nes_output[4] = n64_buttons[4]; // start nes_output[3] = n64_buttons[3]; // select gets set toZ on n64 controller nes_output[2] = n64_buttons[2]; //B nes_output[1] = n64_buttons[1]; //A nes_output[0] = n64_buttons[0];

end endmodule ./source/n64_button_reader.sv

5.2.3 n64_send_cmd

// Module to send command to n64 to send button status // Author: Dan Van Horn // Inputs: // clk_1M1MHz clock // read_start trigger to start the"send read command" // Outputs: // enable_output trigger to enable reading the output of the n64 data l i n e // dout data line for n64 output module N64_send_command( input logic clk_1M, input logic read_start, output logic enable_output, output logic dout);

// shift resigter parallel output l o g i c [33:0] data; l o g i c nothing=0; // after the read command has been sent, we set enable_out to1 //(trigger button status from controller)

22 l o g i c counter_done=0;

// assign dout the most significant bit of data always_comb begin dout <= data[33]; end

a s s i g n enable_output=~counter_done;

n64_counter#(.count(34)) count_down(.clk(clk_1M), .reset(read_start), .done(counter_done));

// load the read command asa waveform that can be sent every1 microsecond shift_register_SIPO#(.width(34) , .init_val(34’b0001000100010001000100010001011101)) send_command( .clk(clk_1M), .enable(~counter_done), .serial_in(nothing), .data(data)); endmodule ./source/n64_send_cmd.sv

5.2.4 n64_read

// N64 controller read command parser/receiver // Author: Dan Van Horn // Inputs: // clk_4M4 MHz clock // din data input line from n64 // enable Only samples when this is active // Outputs: // controller_status 32− b i t register with controller state // controller_clk Output clock, sample at negative edge module n64_read(input logic clk_4M, input logic n64_data, input logic enable_recieve, output logic [31:0] controller_status, output logic controller_clk);

// In sample window, we can read the value of the // last8 samples of the input signal. // Sampling frequency is4 MHz l o g i c [6:0] sampling_window;

shift_register_SIPO#(.width(7), .init_val(7’b1111111)) sample_data( .clk(clk_4M), .enable(enable_recieve), .serial_in(n64_data), .data(sampling_window) );

// When we detecta falling edge at the oldest bit of // the sampling window, we already have our desired // bit at the newest position l o g i c [32:0] controller_state_load;

shift_register_SIPO#(.width(33), .init_val(33’b0)) controller_state( .clk(~sampling_window[6]), .enable(enable_recieve), .serial_in(sampling_window[0]), .data(controller_state_load) );

// We only update controller_status when the counter has finished

23 n64_counter#(.count(32)) counter_signal_complete( .clk(~sampling_window[6]), .reset(controller_clk), .done(controller_clk) );

// load the controller data into controller status, minus the stop bit i n i t i a l controller_status = 32’b0; always@(posedge controller_clk) controller_status <= controller_state_load[32:1]; endmodule ./source/n64_read.sv

5.2.5 n64_counter

// Descending resettable counter // Author: Dan Van Horn // Inputs: // clk Counter clock // reset When active, set count toM // Outputs: // empty Active when counter is0 module n64_counter #(parameter count = 35) (input logic clk, input logic reset, output logic done);

//logicN= $clog2(count)+ 1;

// declare the counter l o g i c[$clog2(count):0] divcounter= count;

// starting at"count", counts down by one on clock edge always_ff@(posedge clk, posedge reset) begin i f(reset) divcounter <= count; i f(divcounter == 0) done <= 1; e l s e divcounter <= divcounter − 1 ; end

// when the counter is empty(all zeros), activate done_flag endmodule ./source/n64_counter.sv

5.2.6 flip_data_mode

// This module is resposible for switching the logic that enables sendinga // command the the n64 controller and enables reading data from the controller // Author: Dan Van Horn // Inputs: // read_start active when the fpga is transmitting to the n64 controller // enable_output active when the n64 controller is transmitting the the fpga // Outputs: // recieve_trigger active on the rising edge of read_start, turns off n64 // data transmission module flip_data_mode(input logic read_start, input logic enable_output, output logic recieve_trigger);

l o g i c flag=0;

// when read start goes high, set flag to1 always_ff@(posedge read_start) flag=1;

24 // recieve trigger turns off when the flag is high recieve_trigger=~enable_output& flag; endmodule ./source/n64_io_flag.sv

5.2.7 n64_send_cmd_trigger

// infinite counter that signals each time it reaches0 // Author: Dan Van Horn // Parameters: // countdown value to count down from //Inputs: // clk input clk // trigger triggers every(countdown) rising clk edges module n64_send_cmd_trigger #(parameter countdown = 512) (input logic clk, output logic trigger);

// Number of bits needed to store the counter value //logicN= $clog2(countdown);

// Register for storing the counter’s value l o g i c[$clog2(countdown+1):0] divcounter= countdown;

// Infinite counter(starts over when divcounter underflows) always_ff@(posedge clk) begin i f(divcounter> 0) divcounter <= divcounter − 1 ; e l s e divcounter <= countdown; end

always_comb begin i f(divcounter == 0) a s s i g n trigger=1; e l s e a s s i g n trigger=0; end endmodule ./source/n64_send_cmd_trigger.sv

5.2.8 shift_register_SIPO

//M −b i t SIPO(Serial in/ Peripheral Out) shift register // Author: Dan Van Horn // Parameters: width. Width of the desired parallel output // init_val. initial value to load onto the shift register // Inputs: clk. Clock for shifting // enable. On active, enable module // serin. Serial input // Outputs: data. Parallel output module shift_register_SIPO #(parameter width = 32, parameter init_val =1) (input logic clk,//pass in clock to control shifting input logic enable,//signal to enable read input logic serial_in,//serial input line output logic[width −1:0] data);//bus for parallel output

l o g i c[width −1:0] shift= init_val;

// Shift register always_ff@(posedge clk) begin i f(enable == 1) begin // shift the data bits to the left by1 s h i f t[0] <= serial_in; s h i f t[width −1:1] <= shift[width − 2 : 0 ] ; end

25 e l s e shift <= init_val; end

a s s i g n data= shift; endmodule ./source/shift_register_SIPO.sv

5.2.9 shift_register_PISO subsectionshift_register_PISO_8bit //The NES controller usesa 4021 PSO register; 4021 shifts to the right //Example: 1100110 is in the register. The least significant bit, 0, is read onto data //Then it is shifted one bit to the right: x110011. But what gets placed there i n s t e a d? //It doesn’t really matter, soI am going to program it as puttinga1 there for no button pressed. module shift_register_PISO #(parameterN= 8) (input logic clk, input logic reset, load, input logic[N −1:0] data, output logic sout);

l o g i c[N −1:0]q;

always_ff@(posedge clk, posedge reset) i f(reset)q <= 0; e l s e if(load)q <= data; e l s eq <= {1,q[N − 1 : 1 ] } ; //Bit sequence: 1100110 //[N −1:1] of that bit sequence: 110011 //Append that witha1 on the most significant bit: 1110011 //We are now ready to send the next button to the data line. a s s i g n sout=q[0]; endmodule ./source/shift_register_PISO_8bit.sv

5.2.10 shift_register_PISO_12bit

//The NES controller usesa 4021 PSO register; 4021 shifts to the right //Example: 1100110 is in the register. The least significant bit, 0, is read onto data //Then it is shifted one bit to the right: x110011. But what gets placed there i n s t e a d? //It doesn’t really matter, soI am going to program it as puttinga1 there for no button pressed. module shift_register_PISO #(parameterN= 12) (input logic clk, input logic reset, load, input logic[N −1:0] data, output logic sout);

l o g i c[N −1:0]q;

always_ff@(posedge clk, posedge reset) i f(reset)q <= 0; e l s e if(load)q <= data; e l s eq <= {1,q[N − 1 : 1 ] } ; //Bit sequence: 1100110 //[N −1:1] of that bit sequence: 110011 //Append that witha1 on the most significant bit: 1110011 //We are now ready to send the next button to the data line. a s s i g n sout=q[0];

26 endmodule ./source/shift_register_PISO_12bit.sv

5.2.11 remote_translator

/∗ This is the top module for the remote_translator. I t recievesa serial input from anIR reciever and outputsa 12 bit bus to go to the NES or SNES. I t is important to reset the mamchine before using it. ∗/ module remote_translator( input logic serial_from_IR, input logic OneMHz_clock, input logic reset, output logic [11:0] to_NES_shift_register);

//Internal Variables between modules l o g i c [13:0] positive_final_count; l o g i c [13:0] negative_final_count; l o g i c [31:0] remote_value; positive_counter counter_one( . remote_data(serial_from_IR), . OneMHz_clock(OneMHz_clock), . final_count(positive_final_count)); negative_counter counter_two( . remote_data(serial_from_IR), . OneMHz_clock(OneMHz_clock), . final_count(negative_final_count)); signal_interpreter interpretation( . positive_final_count(positive_final_count), . negative_final_count(negative_final_count), .reset(reset), .clock(OneMHz_clock), . parallel_output(remote_value)); button_identification identification( . signal_interpreter_output(remote_value), . to_NES_input_register(to_NES_shift_register)); endmodule ./source/remote_translator.sv

5.2.12 signal_interpreter

/∗ This module recieves the counts from the two counters and decides to passa1 or0 based on how long the pulse is The base template of the state machine is based on an example i n the class textbook. ∗/ module signal_interpreter( input logic [13:0] positive_final_count, input logic [13:0] negative_final_count, input logic reset, input clock,//1MHz Clock output logic [31:0] parallel_output);

l o g i c [4:0] total_output; //There are three states: wait for long low pulse, //wait for long high pulse, and gather data t y p ed e f enum logic [1:0] {S0, S1, S2} statetype; s t a t e t y p e state, next_state; always_ff@(posedge clock) s t a t e <= next_state; always_comb

27 begin clk_1MHz <= ~clk_1MHz;//Flip1MHz clock count <= 0;//Reset the counter end end endmodule ./source/clock_counter_1MHz.sv

5.3 Simulation Results

5.3.1 n64_send_cmd Module Simulation

Figure 32: the waveform above shows that the module can send out the raw waveform "send button state" cmd to the controller

Do file vsim.work. n64_send_cmd add wave ∗ f o r c e clk_1M0 0, 1{1ns} −r2 ns f o r c e output_enable1@0 f o r c e read_start0@0 run 100 ns

32 5.3.2 n64_counter Module Simulation

Figure 33: This module is parameterized, It was tested with a countdown value of 4 and the waveform reflects the expected behavior

Do file vsim.work. n64_counter add wave ∗ f o r c e clk_1M0 0, 1{1ns} −r2 ns f o r c e t_reset0@0 run 30 ns

33 5.3.3 flip_data_mode Module Simulation

Figure 34: This module’s responsibility is solely to switch between reading and writing to the con- troller, The falling edge of the "read_start" signal assigns "enable_output" and "recieve_trigger" to their complements.

Do file vsim.work. flip_data_mode add wave ∗ f o r c e enable_output1@0 f o r c e read_start1@ 10 run 30 ns

5.3.4 n64_send_cmd_trigger Module Simulation

Figure 35: The waveform confirms the expected behavior of periodically sending a signal that triggers the polling signal to the controller.

34 Do File vsim.work. n64_send_cmd_trigger add wave ∗ f o r c e clk_1M0 0, 1{1ns} −r2 ns f o r c e t_reset0@0 run 30 ns

5.3.5 shift_register_SIPO Module Simulation

Figure 36: The serial to parallel shift register that is heavily used in the N64 communication protocol shifts inputs as expected.

Do file vsim.work. shift_register_PISO add wave ∗ f o r c e clk_1M0 0, 1{1ns} −r2 ns f o r c e enable1@0 f o r c e serial_in0@0 f o r c e data 34’b0001000100010001000100010001011101@0 run 100 ns

5.3.6 shift_register_PISO_8bit Module Simulation

Figure 37: The parallel to serial shift register that is used to send data to the imaginary NES console. There exists a 12bit module for the SNES, but it is functionally the same as the 8-bit and will not be simulated.

35 Do file f o r c e reset1@0, 0@ 50 f o r c e load0@0, 1@ 250, 0@ 350 f o r c e clk0@0, 1@ 100, 0@ 200, 1@ 300, 0@ 400, 1@ 500, 0@ 600, 1@ 700, 0 @ 800, 1@ 900, 0@ 1000, 1@ 1100, 0@ 1200, 1@ 1300, 0@ 1400, 1@ 1500, 0 @ 1600, 1@ 1700, 0@ 1800, 1@ 1900, 0@ 2000 f o r c e data 8’b01010101@ 150, 8’b11111111@ 350

5.3.7 remote_translator Module Simulation

Figure 38: This waveform shows the main remote module working with two button presses, with a condensed time interval between, to keep the simulation readable.

Do file vsim work. remote_translator

add wave serial_from_IR add wave OneMHz_clock add wave reset add wave to_NES_shift_register add wave positive_final_count add wave negative_final_count add wave remote_value

f o r c e reset1@1,0@ 10 f o r c e OneMHz_clock −r {1000 ns} 0@ {0 ns} ,1@ {500 ns} f o r c e serial_from_IR0@ {99 us} f o r c e serial_from_IR1@ {8754 us} f o r c e serial_from_IR0@ {13006 us} f o r c e serial_from_IR1@ {13584 us} f o r c e serial_from_IR0@ {15198 us} f o r c e serial_from_IR1@ {15769 us} f o r c e serial_from_IR0@ {16311 us} f o r c e serial_from_IR1@ {16915 us} f o r c e serial_from_IR0@ {17422 us} f o r c e serial_from_IR1@ {18028 us} f o r c e serial_from_IR0@ {19611 us} f o r c e serial_from_IR1@ {20193 us} f o r c e serial_from_IR0@ {21804 us} f o r c e serial_from_IR1@ {22378 us} f o r c e serial_from_IR0@ {23996 us} f o r c e serial_from_IR1@ {24573 us} f o r c e serial_from_IR0@ {25109 us} f o r c e serial_from_IR1@ {25707 us} f o r c e serial_from_IR0@ {26238 us} f o r c e serial_from_IR1@ {26842 us} f o r c e serial_from_IR0@ {27349 us} f o r c e serial_from_IR1@ {27955 us} f o r c e serial_from_IR0@ {29539 us} f o r c e serial_from_IR1@ {30119 us} f o r c e serial_from_IR0@ {31730 us} f o r c e serial_from_IR1@ {32304 us} f o r c e serial_from_IR0@ {32843 us} f o r c e serial_from_IR1@ {33448 us} f o r c e serial_from_IR0@ {33953 us} f o r c e serial_from_IR1@ {34551 us} f o r c e serial_from_IR0@ {35063 us} f o r c e serial_from_IR1@ {35664 us}

36 Do file vsim work. active_controller

add wave remote_data add wave N64_data add wave button_data add wave select_bits

f o r c e/remote_data 2#00001111@0 f o r c e/N64_data 2#11110000@0 f o r c e/button_data 2#11001100@0 f o r c e/select_bits 2#00@ 0, 2#01@ 100, 2#10@ 200, 2#11@ 300

run 400 ns

5.3.14 clock_counter_1MHz Module Simulation

Figure 45: This waveform shows the 4MHz clock input and the 1MHz output.

Do file vsim work. active_console

add wave clk_4MHz add wave reset_n add wave clk_1MHz

f o r c e clk_4MHz −r 234 0@0, 1@ 117 f o r c e reset_n0@0, 1@ 200

run 3000 ns

References

[1] U. of Michigan, “Design problem: Interfacing to a controller.” https://www.eecs. umich.edu/courses/eecs270/lectures/270L23NotesF14.pdf, 2014. [2] U. of California At Berkeley, “N64 controller.” http://www-inst.eecs.berkeley.edu/ ~cs150/fa04/Lab/Checkpoint1.PDF, 2004. [3] D. Harris and S. Harris, “Digital design and computer architecture.” http://ebookcentral. proquest.com.ezproxy.proxy.library.oregonstate.edu/lib/osu/detail.action? docID=980017, 2013. [4] Pieter-Jan, “Reading nintendo 64 controller with pic microcontroller.” http://www. pieter-jan.com/node/10, 2012. [5] A. Limited, “Nec infrared transmission protocol.” http://techdocs.altium.com/display/ FPGA/NEC+Infrared+Transmission+Protocol, 2013.

44 [6] J. Corleto, “Nes controller interface with an arduino uno.” https://www.allaboutcircuits. com/projects/nes-controller-interface-with-an-arduino-uno/, 2016. [7] J. Christy, “Super nintendo entertainment system: pinouts protocol.” https://www.gamefaqs. com/snes/916396-super-nintendo/faqs/5395, 1996.

45