<< INTRODUCTION >> << OVERVIEW >> << AUDIO >> << GAMEPLAY >> << VIDEO >> << IMPROVEMENTS >> << ZBT RAMS >> << TIPS AND TRICKS >> << NES INPUT FSM >> << TOOLS >> |
Appendix: NES Input FSM /* NINTENDO CONTROLLER INPUT FSM The NES controller connects to the system via 5 wires. 2 wires are power and ground The others are latch, pulse and data. Latch and pulse are signals from the FSM to the controller. Data is a signal from the controller to the FSM. The data read process starts on the gameclock signal. The data protocol (exactly as used by Nintento itself) is as follows: 1. FSM sends latch signal high for 12 us to controller (LATCH) 2. "A" button data (high or low) is ready on data line (READ_A) 3. FSM waits 6 us (WAIT) 4. FSM sends pulse signal high for 6 us to controller (PULSE) 5. "B" button data (high or low) is ready on data line (READ_B) 6. Repeat steps 3-5 for (in order): select button (READ_SELECT) start button (READ_START) up button (READ_UP) down button (READ_DOWN) left button (READ_LEFT) right button (READ_RIGHT) For each WAIT-PULSE sequence, the return read state is stored in returnstate. Output data is registered with the 27 MHz clock before passing it on. */ module gameinput(clock, gameclock, reset, latch, pulse, data, plyr_input); input clock, gameclock, reset, data; output latch, pulse; reg latch, latch1, pulse, pulse1, data1; output [7:0] plyr_input; reg left, right, up, down, A, B, select, start; reg left1, right1, up1, down1, A1, B1, select1, start1; assign plyr_input = {left, right, up, down, A, B, select, start}; reg [3:0] state, nextstate, returnstate, nextreturnstate; reg [11:0] count, nextcount; parameter INIT = 0; parameter IDLE = 1; parameter LATCH = 2; parameter WAIT = 3; parameter PULSE = 4; parameter READ_A = 5; parameter READ_B = 6; parameter READ_SEL = 7; parameter READ_STRT = 8; parameter READ_UP = 9; parameter READ_DOWN = 10; parameter READ_LEFT = 11; parameter READ_RIGHT = 12; parameter TWELVE_US = 12'h144; //count for 12 us on a 27 MHz clock parameter SIX_US = 12'h0A2; //count for 6 us on a 27 MHz clock always @ (posedge clock) begin if (!reset) begin state <= INIT; returnstate <= INIT; count <= 0; end else begin state <= nextstate; returnstate <= nextreturnstate; count <= nextcount; end data1 <= data; latch <= latch1; pulse <= pulse1; left <= left1; right <= right1; up <= up1; down <= down1; A <= A1; B <= B1; select <= select1; start <= start1; end always @ (state or returnstate or count or gameclock or data1) begin //defaults nextstate = state; nextreturnstate = returnstate; nextcount = count; latch1 = latch; pulse1 = pulse; left1 = left; right1 = right; up1 = up; down1 = down; A1 = A; B1 = B; select1 = select; start1 = start; case (state) INIT: begin nextstate = IDLE; nextcount = 0; end IDLE: begin nextcount = 0; //get input at input rate specified by game clock if (gameclock) nextstate = LATCH; end LATCH: begin //latch 12 us, then go to read A latch1 = 1; if (count == TWELVE_US) begin nextcount = 0; latch1 = 0; nextstate = READ_A; end else nextcount = count + 1; end WAIT: begin //wait 6 us, then go to pulse if (count == SIX_US) begin nextcount = 0; nextstate = PULSE; end else nextcount = count + 1; end PULSE: begin //pulse 6 us, then go to returnstate and read data pulse1 = 1; if (count == SIX_US) begin nextcount = 0; pulse1 = 0; nextstate = returnstate; end else nextcount = count + 1; end READ_A: begin A1 = ~data1; nextreturnstate = READ_B; nextstate = WAIT; end READ_B: begin B1 = ~data1; nextreturnstate = READ_SEL; nextstate = WAIT; end READ_SEL: begin select1 = ~data1; nextreturnstate = READ_STRT; nextstate = WAIT; end READ_STRT: begin start1 = ~data1; nextreturnstate = READ_UP; nextstate = WAIT; end READ_UP: begin up1 = ~data1; nextreturnstate = READ_DOWN; nextstate = WAIT; end READ_DOWN: begin down1 = ~data1; nextreturnstate = READ_LEFT; nextstate = WAIT; end READ_LEFT: begin left1 = ~data1; nextreturnstate = READ_RIGHT; nextstate = WAIT; end READ_RIGHT: begin right1 = ~data1; nextstate = IDLE; end endcase end endmodule |