report13

report13 - 6.111 Final Project Report Due: May 13, 2004...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: 6.111 Final Project Report Due: May 13, 2004 Paratroopers Tushara C. Karunaratna, Chun-Chieh Lin, George Heming Contents 1 Introduction 2 Design Overview 3 Camera input subsystem 3.1 Overview . . . . . . . . . . . . . . . . . . . . . . 3.2 Description of hardware used for Video Capture . 3.3 Control and Processing Logic . . . . . . . . . . . 3.4 Testing and Debugging . . . . . . . . . . . . . . . 3.5 Conclusions and Reflections . . . . . . . . . . . . 4 Game Controller 4.1 Introduction . . . . . . . . . 4.2 Random Number Generator 4.3 Shoot Register . . . . . . . 4.4 RAM . . . . . . . . . . . . . 4.5 Output FSM . . . . . . . . 4.6 Collission detection . . . . . 4.7 Updating game state . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 2 2 3 6 8 9 9 9 10 10 10 11 11 5 Video Output subsystem 12 5.1 Output Generator FSM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.2 Video Display Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.3 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 A Selected Verilog code for Camera Input subsystem B Selected Verilog code for Game Controller C Selected Verilog code for Video Output subsystem 15 22 28 List of Figures 1 2 3 4 5 6 7 8 9 10 11 12 Block diagram of the Video Capture Unit. . . . . . . . . . Controller of the Video Capture Unit. . . . . . . . . . . . Digitizer FSM of the Video Capture Unit. . . . . . . . . . Calibrator FSM of the Video Capture Unit. . . . . . . . . Processor FSM of the Video Capture Unit. . . . . . . . . Major FSM of the game controller. . . . . . . . . . . . . . The game FSM of the game controller. . . . . . . . . . . . The Video Output subsystem. . . . . . . . . . . . . . . . . State transition diagram for the Output Generator FSM. Chroma Decoder. . . . . . . . . . . . . . . . . . . . . . . . Generating VSync. . . . . . . . . . . . . . . . . . . . . . . Monitor cable pins. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 4 5 6 7 9 10 12 13 14 15 15 1 Introduction We present a hardware implementation of the classic Paratroopers video game, in which we have replaced the analog joystick with the motion and gestures of a human player in a playing area. Our design uses video input from a camera to detect the motion of the player and translates this motion into positional data to control the player's gun position. A player uses arm gestures to trigger the gun by raising and then lowering his arm. This game play concept was inspired by the recent use of video games as exercising aids. Our objective was to give the player a workout while enjoying a classic video game. The Paratroopers video game has a simple objective, which is to destroy enemy helicopters, bombs and paratroopers as they appear on the screen. During the game the helicopters release bombs and paratroopers at random positions while moving across the screen. The player, rep resented by a gun sprite at the bottom of the screen, has the objective of shooting these enemy objects before they hit the ground or move out of the screen. The player is allowed to move left or right, in addition to shooting. 2 Design Overview The system is partitioned into 3 functionally distinct parts, a Video Capture Unit (VCU), a Game Control Unit (GCU) and a Video Display Unit (VDU). The Video Capture Unit captures the motion of the player and processes this video to extract positional information, which is fed as input to the GCU to update the state of the game. The GCU is the game engine, which simulates the game play. It manages the tasks of creating and destroying objects, updating the position of objects, detecting collisions and maintaining score and player health information. The VDU displays the current state of the game as simulated by the GCU on a video monitor. Game play begins with a calibration stage in which the video capture unit detects the height of the player and establishes a height threshold for indicating a shoot gesture. The calibration stage consists of 2 prompt screens on the Video Display Unit. The first prompts the user to stand in the playing area with arms lowered, while the second screen prompts for a raised hand. Each screen lasts five 5 seconds during which time the Video Capture Unit determines the appropriate values for the shooting threshold. The Video Capture Unit does this calibration by examining each frame of video to find the dark pixels corresponding to objects in the playing area and averaging over all frames the first dark pixels encountered. The calibration data is transmitted to the Video Display Unit. Once the playing parameters are configured, the Game Controller proceeds to the level selec tion screen where the player can select the difficulty of the game play by moving left or right to respectively increase or decrease the difficulty of the game. The position of the player in the playing area indicates the level of difficulty. The player confirms his selection of a difficulty level with a shoot gesture. The confirmation causes actual game play to begin and it continues until the players health points decrease to zero. At this point, a game over screen is displayed on the Video Output. The player may restart the game by walking out and back into the playing area. 3 Camera input subsystem This section discusses the implementation and design of input motion input part of the system. 1 3.1 Overview The Video Capture Unit is responsible for translating the left and right motion and hand gestures of the player into positional information and a shoot signal, which are fed as inputs to the Game Controller. Capturing a monochrome NTSC video signal of the playing area and processing it to extract the relevant information achieves this function. In addition the VCU does the initial calibration to establish a height threshold to correspond to a shoot gesture. This calibration occurs at the beginning of each game and is necessitated by the need to adjust for different player heights. The Video Capture Unit consists of hardware for sampling and storing the Video Signal and control and processing logic for processing the sampled video data. The hardware consists of an NTSC camera, an Analog-to-Digital converter, a monolithic sync separator and an SRAM to store the sampled video. The control logic is partitioned into four modules: a Controller, Digitizer, Calibrator and Processor. The Digitizer captures the digitized video from the analog-to-digital converter and stores it in the Line Buffer. The calibrator processes the data in the line buffer during the calibration stage to determine the shoot threshold and communicates with the Video Display Unit to display the computed threshold. The Processor uses the Line Buffer data to determine position and shoot gestures during game play and communicates this information to the Game Controller. The controller coordinates the operation of the Calibrator, Digitizer and Processor using sync information from the monolithic sync separator. Figure 1 shows the overall system organization of the Video Capture Unit. NTSC Camera AD775 GS4981 response to VDU data / 8 shoot request from VDU Control & Processing Logic position synchronizer hsync vsync request Figure 1: Block diagram of the Video Capture Unit. 3.2 Description of hardware used for Video Capture GS4981 (Monolithic Sync Separator) The sync separator is responsible for extracting the vertical and horizontal sync signals from the NTSC signal from the video camera. 2 AD775 (Analog-to-Digital Converter) The AD775 is a flash based converter capable of sam pling rates as high as 35Mhz at a resolution of eight bits. In this project, it was operated at the system clock frequency of 10Mhz, making it possible to take at least two samples of the video signal in determining the value of each pixel. SRAM Line Buffer The Line Buffer is a 16-byte memory element used to hold pixel data corresponding to one horizontal line of the NTSC video signal. The choice of a 16-byte depth for the SRAM was dictate by our initial design decision to display the output of the game at a resolution of 128 x 96 pixels. Storing one bit of information per pixel, 0 corresponding to a value below the threshold and 1 for values above the threshold, it was sufficient to have 128 bits or 16-bytes of data per horizontal line. The 96 pixel vertical resolution also meant that it was possible to process a line of video between digitizing intervals. This eliminated the need to buffer an entire frame of video (approximately 500 lines), which would have been processed during the vertical blanking interval of the NTSC signal (approximately 22 lines) sample the video rather coarsely (roughly every fifth line) 3.3 Control and Processing Logic Controller FSM The controller is a finite state machine (FSM), which takes as inputs the horizontal (h-sync) and vertical sync (v-sync) signals from the sync separator. Based on this sync information, the controller instructs the digitizer to start sampling the video. Each frame of the NTSC signal consists of 525 horizontal lines and thus to achieve a vertical resolution of 96 pixels on the output display, it was sufficient to sample approximately every fifth line of the video signal. The Controller FSM has 8 states and transitions between them based on the h-sync and v-sync input provided by the GS4981. On a reset, the controller transitions into the INITIALIZE state for one clock cycle where various counters are set to their appropriate initial values. After initialization, the FSM transitions into the WAIT VSYNC LOW stage, where it waits to detect the active low vertical sync signal, which indicates the end of a video frame. Once the end of a frame is detected in the WAIT VSYNC HIGH state by the v-sync signal going high, the Controller FSM waits in the DELAY VBLANK state to account for the vertical blanking period of the NTSC. After the blanking period, the controller instructs the Digitizer FSM, based on the h-sync signal and the counter variable, to sample the active video on every fifth line after a horizontal blanking period of roughly 7us which is accounted for by the DELAY HBLANK state. The start signal to the Digitizer is asserted in the START SAMPLE state. The Controller remains in the WAIT sample state until it gets a done signal from the digitizer. Figure 2 depicts the state transition diagram of the Controller FSM. Digitizer FSM The Digitizer FSM after initialization, triggered by a reset signal, in the INI TIALIZE state waits in the IDLE state for a start signal from the Controller FSM. When the start signal is received, the Digitizer transitions into the SAMPLE1 followed by SAMPLE2 states where it reads in a digitized sample from the analog-to-digital converter. The average value of the two samples is compared with the external threshold input to determine the value of a corresponding pixel in the STORE BITS state. In the STORE BITS stage, the Digitizer FSM keeps track of the pixel positions in the video and assembles them into 16-bytes, with the LSB of the nth byte rep resenting the 2n horizontal pixel of each line. The Digitizer transitions between the STORE BITS 3 Figure 2: Controller of the Video Capture Unit. and SAMPLE states until all sixteen bytes are filled, at which point it transitions into the WRITE1 state. Here the done signal is asserted to inform the controller that sampling is complete. The time constraints imposed by the interval between successive h-syncs is met by asserting the done signal as soon as sampling is complete. This ensures that the line count maintained by the Controller FSM is accurate. The WRITE1, WRITE2, WRITE3 and INCR ADDR states are used to write the bytes into the Line Buffer. At the end of sixteen writes, a start proc signal is asserted to inform the calibrator and processor to start processing stored line of video. The addr sel signal is also switched to give the calibrator or processor access to the Line buffer. Calibrator FSM The Calibrator FSM establishes a shoot threshold value for a player during the calibration phase of game play. After initialization in the INITIALIZE state on a reset, the Calibrator FSM waits in the IDLE state until it the start signal, provided by the digitizer FSM, is asserted. When the start signal is asserted, the Calibrator transitions into the LOAD LINE state where it reads in sixteen bytes of data from the Line Buffer into an internal 128-bit register. It then transitions into the CALIBRATE state where it determines values for the shoot thresholds. Each of the two thresholds is initialized to 96 (corresponding to the bottom of the screen). The Calibrator FSM keeps track of the line it is currently processing and sets the threshold value to the first line number it encounters for which the 128-bit internal register is greater than 0, which indicates a blank line in the video. This process is averaged over roughly 1900 frames corresponding to 10 seconds of video to establish the final value, which is fed as input to the Processor FSM. To display the output of the calibration process, the Calibrator transitions into the WAIT VID REQ state where it waits for a video request signal to be asserted by the Video Display Unit. Once the request is received, the Calibrator transitions into the SETUP DATA state where the value of the internal register is either maintained or changed to all 1s if the line number corresponds with the threshold value. The nth to (n+8)th bits of the register are setup as the data to be transmitted to the Video Display Unit, where n is the transmission count. Once the data is setup, the Calibrator asserts it's 4 Figure 3: Digitizer FSM of the Video Capture Unit. response/ready signal and transitions into the VERIFY TRANSMIT state where it waits for the request signal to go low, confirming receipt of the data, at which point it sets the response output low and transitions back into the WAIT VID REQ state. This asynchronous transmission process is continued until all sixteen bytes are transmitted and then the Calibrator transitions back to the IDLE state to wait for the next start signal from the Digitizer. The digitizer remains in the IDLE state indefinitely once the maximum frame count is reached, indicating the end of the calibration stage. At this point memory access is handed over to the processor unit by asserting the addr sel output. Figure 4 represents the state transition diagram of the Calibrator. Processor FSM The processor FSM computes the position of the player in the playing area and determines if the shoot gesture has been asserted. The Processor FSM transitions into the INITIALIZE state on a reset where various counters are set to their initial values and transi tions into the IDLE after one clock cycle where it waits for the start signal from the Digitizer FSM. Upon receiving the start signal in the IDLE state, the Processor FSM transitions into the INIT HIGH BYTE state where it reads the first byte of data corresponding to address 0x0 from the Line Buffer after which it transitions into the SETUP LOW BYTE state where it reads the second byte corresponding to address 0x1 from the Line Buffer. Once the two bytes have been setup, the Processor computes the left and right bounds of any object using a windowing algo rithm in the COMPUTE BOUNDS state. The algorithm relies on the assumption that the player occupied at least eight pixels and hence moves an 8-bit wide sliding window over the two bytes read from memory. If the bits in the window have the value 0xff, then the left bound is set to the value of the pointer to the beginning of the window. If not such sequence is found, the pointer is incremented until it reaches address 0xf. After computing the left bound, the bytes are reversed and the same computation is done to find the right bound of the player. Once the bounds are computed for the first two bytes, the second byte read in is shifted into the high byte position and the next byte in memory is read. This process continues until all sixteen bytes are read from 5 reset start * IDLE LOAD_LINE byte_count != 16 INITIALIZE !start byte_count = 16 !request && transmit_count = 16 CALIBRATE * request VERIFY_TRANSMIT !request && transmit_count != 16 WAIT_VID_REQ !request byte_count != 16 * SETUP_DATA request Figure 4: Calibrator FSM of the Video Capture Unit. the Line Buffer. The shifting and loading operations are perfomed in the states SHIFT BYTE, LOAD ADDR LOW BYTE and LOAD DATA LOW BYTE states. The final value assigned to the left and right bounds are the minimum and maximum values respectively, computed over all lines in a fram. The COMPUTE BOUNDS state also computes if a shoot signal has been asserted by comparing lines corresponding to the first black pixel it encounters with the its shoot low and shoot high inputs, which are provided by the Calibrator FSM. If the first black pixel is encountered in a line lower than the shoot high input, the shoot output is set high and if it is lower than the shoot low input, the output is set low. This in effect implements a level signal, which is converted to a pulse by the Game Controller Unit. This design choice for the shoot signal is to avoid automatic rapid fire, caused by a player keeping their arm up during game play. Once the entire frame has been read, that is 96 lines have been processed, the Processor transitions to the TRANSMIT state where it assigns it position and shoot outputs to the values in their corresponding internal values. These output values are held until the next position update at the next of the subsequent frame. After transmission, the Processor waits in the IDLE state for the next start signal from the processor. Figure 5 shows the state transition diagram for the Processor FSM. 3.4 Testing and Debugging The entire project was simulated in the Max+Plus II development environment. Each module was individually tested by checking for correct state transitions and internal variable states on various inputs which had to be specified manually by forcing input values in the Max+Plus II simulation environment. The critical tests for the Controller FSM were with regards to certifying that delay states met their timing requirements and that other state transitions behaved according to the specifications of the h-sync and v-sync inputs. For the Digitizer FSM testing was focussed on the bit accumulation process. It was crucial that the sampled pixels were stored in the correct position 6 reset start * IDLE INIT_HIGH_BYTE INITIALIZE * !start * SETUP_LOW_BYTE TRANSMIT byte_count = 16 * INIT_LOW_BYTE byte_count != 16 LOAD_ADDR_LOW_BYTE * LOAD_ADDR_LOW_BYTE * COMPUTE_BOUNDS * SHIFT_BYTE * Figure 5: Processor FSM of the Video Capture Unit. in each byte and that the bytes were written to the Line Buffer so as to represent the order in which the data was received from the AD775. Also it was crucial that the entire operation for the Digtizer finish within 63.1 us which corresponds to one horizontal line of NTSC video. Although I had initially estimated taking the average of four samples for each pixel, the simulation revealed that it number had to be revised to two samples per pixel. Even with the reduced samples per pixel rate, the done signal to the Controller FSM had to be asserted before the process of storing the pixels in the Line Buffer began. These tight timing constraints were the result of a design choice to guarantee at least 1us delay before the next h sync signal. In retrospect, this contraint may have been overly cautious and restricting. The crucial parts of the Processor FSM was guaranteeing the level behavior of the shoot signal and the correct computation of the position as the mid-point of the leftmost and rightmost pixels in a frame. For the Calibrator FSM the tests were focussed on the asynchronous communication interface and the computation of the threshold. The latter was difficult to do in simulation, as it required manully simulating the NTSC signal over 96 lines, a rather tedious process. The alternative testing strategy was to use the Video Display Interface, but this was dependent on the hardware sampling process being functional. The hardware testing and debugging was a frustrating experience which ultimately led to the demise of the project. After setting up the AD775 according to its specifications, I noticed that the values produced by the AD775 did not correlate with the NTSC video signal. In particular, the values seemed to have a fixed pattern even when I was certain that the NTSC signal wasn't periodic. I ensured the variability of the video signal by moving my hand in front of the camera lens, varying the aperture on the lens from fully open to closed and pointing the camera in different directions, observing the signal on an oscillioscope each time. My hypothesis for this behavior was that the reference voltages on the AD775 were not properly set. To this end, I enlisted the help of the lab assistants to confirm that I had correctly setup the AD775. Once the setup had been confirmed, I proceeded to write a test controller for a digital-to-analog converter to try to reproduce the ouput of the analog-to-digital converter. This setup revealed the same results. After several 7 hours of trying to fine tune the reference voltages with potentiometers, it was suggest by one TA to amplify the video signal before feeding it to the AD775, as the signal range may be too small. Once I contructed the amplifying circuit and tested it with the video to make sure I had the correct gain and the video signal was indeed amplified, I proceeded to test the output through the Video Display Unit interface. The observed output did not resemble the camera view and showed little variability with moving objects in the scene. At this point, I had had run out of ideas and given up out of frustration. In retrospect I realize my folly in not attempting to substituting the AD775 with another one, but rather assuming the error was with the thresholds. 3.5 Conclusions and Reflections The design presented in this paper is in theory a fundamentally sound one, which is well partitioned into functionally distinct units that reflect the operation of the Video Control Unit. The one crucial limiting factor in this design, which was overlooked in my implementation, however is that the success of the entire unit depends on successfully implementing the analog-to-digital conversion circuitry. Having recently completed Lab exercise 3 which dealt with similar issues, I was confindent that I would be able to implement this phase of the project when needed, and thus focussed my efforts on design memory efficient data structures and relatively fast algorithms for processing the data, assuming it was available. The algorithm chosen in retrospect seems very susceptible to noise, but this limitation may be mitigated by adjusting the 0-1 pixel threshold by trial-and-error and ensuring a certain level of lighting and contrast in the playing area. More precise algorithms may be difficult to implement, as they will involve some form of pre-processing of the digitized video, say median filtering, to reduce the noise. Alternatively, the video may be sampled at at finer level than is needed , but this will require substantially more storage and perhaps a faster system clock rate. In conclusion, to successfully implement such an ambitious project, it is essential for any digital designer to be as familiar with analog circuitry and interfaces as he is with digital. Such knowledge will minimize the amount of time spent on debugging analog circuits and increase the time available for testing the entire system design outside of simulation, and fine tuning as necessary. 8 4 4.1 Game Controller Introduction The game controller waits for the video input to calibrate, specifies a difficulty level, and then starts the game. It takes the output of the video camera controller as the input to the game, and outputs the positions of the sprites to the video output controller. It also uses a random number generated with a random number generator to ensure that the game is different each time it is played. Figure 6: Major FSM of the game controller. The game FSM is the FSM that actually controls the game play. It specifies the general sequence of operation for the game, and it uses several minor FSMs to perform the computation. The game FSM waits for the frame request from the output, then it outputs the current state of the game in the form of the locations of the sprites. Then the game updates the state of the game by creating, moving, and destroying the sprites. Then it checks for the collisions, like bullets hitting the paratroopers, or the bombs hitting the ground, and determines which objects have to be destroyed. The checking also calculates the damage in health points the player sustains during the frame, and if the player's health reaches zero, the game ends. 4.2 Random Number Generator To make sure that the game is different each time it is played, a random number generator is used to give randomness to the game. The best way to do it would be to use the video input, but since the video input was taking too long to finish, an alternative one was created. The random number generator is run on a ten-megahertz clock, and it takes in a signal from a 1.84 megahertz clock as its input. It contains an eight-bit register, which is updated every clock cycle. Every clock cycle of the ten-megahertz clock, the input is sampled, and one of the bits of the eight-bit register is replaced by the exclusive-or of the input with the previous value. 9 Figure 7: The game FSM of the game controller. The random number generator cycles through the eight bits, and it is not reset with the rest of the system. Over time, the value contained in the register becomes fairly random, and the probability of the possible values is roughly uniformly distributed. 4.3 Shoot Register Each time the shoot signal from the input is raised, the shoot register is set. The shoot register also takes a reset signal, which is passed in from the FSMs when the request is processed. 4.4 RAM The game controller uses two registers, numheli and numobject, to specify the number of each type of objects currently on the screen. The locations of each sprite is stored in a RAM. The RAM is stored and used by the game FSM, and it is split into two sections. The first part of it stores the positions of the helicopters, and the second part stores the positions of the bombs and the paratroopers. For each part, the objects are continuously sorted, so the valid objects are stored in the lower addresses. The gun and the bullets are not stored in the RAM because the gun is always on the screen with its location being specified by the video input, and the bullets are stored in registers to facilitate faster checking. 4.5 Output FSM The output FSM interfaces with the video output, and gives it the sprites and their locations. The interface consists of a request signal, a ready signal, and an eight bit output bus. When the video output requests a new frame, it sets the request signal high. The output FSM then puts an output in the bus, and sets the ready signal high. The video output lowers the request 10 signal when it takes the data. The output FSM then lowers the ready signal, after which the video output raises the request signal again. When all the data of the current frame is transmitted, an end frame codeword is sent through the bus, and the video output waits until the next frame to request again. The output FSM follows that interface, and for each of the sprites, it sends a codeword to denote the type of the sprite, the horizontal position of the sprite, and the vertical position of the sprite. Therefore, information about each sprite takes three signals to send. The end frame codeword is designed to be different from any other possible message, so the interface takes at most a frame to synchronize the states of the game controller and the video output. 4.6 Collission detection The check FSM checks for the collisions between the sprites and the bullets, and also checks whether the bombs and paratroopers hit the ground. It modifies the RAM accordingly, and calculates the damage the player receives. When the check FSM finds that a bullet overlaps with a bomb, a paratrooper, or a helicopter, it marks both of them for removal. If the check FSM finds that a bomb or paratrooper hits the ground, it also makes it for removal, and also increments the damage calculation for the frame. Each time a paratrooper hits the ground, the player receives one point of damage, and each time a bomb hits the ground, the player is dealt two points of damage. 4.7 Updating game state The update FSM creates, moves, and destroys the sprites, and it is the most complicated of the FSMs in the game controller. The bullets are created when a shoot signal is received before the frame, and the update FSM resets the shoot register. For each frame, the update FSM determines whether to create a new helicopter by checking how far the previous helicopter going in that direction has moved. If the previous helicopter is sufficiently far away, a new one is created. Whether the previous helicopter is far enough away is dependent on a parameter calculated using the random number available at the time. When a helicopter reaches a location specified in its slot in the RAM, it drops a paratrooper or a bomb. Then the next location it will drop an object is generated using the random number input. Whether the dropped object is a bomb or a paratrooper is also randomly determined, with the probability of a bomb being three-eighths and the probability of a paratrooper being five-eighths. The update FSM moves the existing sprites by modifying the RAM. How fast the sprites move is determined by the difficulty level. The bullets, however, move at a pixel per frame regardless of the level. The bullets marked for removal are removed immediately by the update FSM. The other sprites, however, are displayed as explosions for fifteen frames before they are removed. During the fifteen frames the sprites are displayed as explosions, they do not move or affect the game-play in any way. 11 5 Video Output subsystem The Video Output subsystem acts as the interface from other two subsytems to the video monitor. This subsystem consists of the Output Generator which continuously updates an external RAM with the image to be displayed on the monitor, and the Video Display Interface which continuously reads the image from the RAM and generates the HSync, VSync, and R,G,B signals taken in by the video monitor. During game play, the Output Generator receives asynchronous signals from the Game Con troller, translates these signals into lists of objects to be displayed on the screen, and writes, onto the RAM, the image to be displayed on the monitor. The sprites for the various types of objects, such as helicopters and paratroopers, are read from an internal ROM. During calibration, the Out put Generator receives asynchronous signals from the Camera Input subsystem, translates these signals into a stream of pixels corresponding to the image captured by the camera, and writes the image onto the RAM. The Video Display Interface consists of the MC6847 video controller chip, along with some some analog circuitry, and generates the HSync, VSync, and the R,G,B signals corresponding to the image stored on the RAM. The NMS input of the MC6747 chip is asserted low by the Output Generator when the image in the RAM is being updated, so that the MC6847 will not attempt to update the display while the RAM is being written. When the Output Generator finishes updating the RAM, the NMS signal is raised, so that the MC6847 will update the display with the current image. Once the display has been updated, the MC6847 lowers the NFS signal, and at this time the Output Generator starts updating the RAM with the next image, and the cycle repeats. Figure 8 illustrates the interconnections among the various components of the Video Output subsystem. Sections 5.1 and 5.2 describe the operation of the Output Generator and the Video Display Interface respectively. Figure 8: The Video Output subsystem. 12 5.1 Output Generator FSM Figure 9 illustrates the FSM of the Output Generator. The game play and calibrate signals are inputs to the FSM through switches, and instruct the FSM to move into the game display mode or the calibration display mode respectively. Figure 9: State transition diagram for the Output Generator FSM. When in the game display mode, the FSM repeatedly requests three values from the Game Controller: the type of object, the x-coordinate, and the y-coordinate. As each triple is received, the sprite of the specified type is loaded, and is written at the specified location of the RAM. When the received signal has the value no more objects, the FSM raises the NMS signal and moves into the Display state. The FSM moves back to the Start state when the NFS signal is lowered by the MC6847. When in the calibration mode, the FSM repeatedly requests, and writes to the RAM, a pixel from the Camera Input subsystem. The end of the frame is reached when the end of frame signal is 13 received, at which point the MC6847 chip is instructed to display the image stored in the memory. The Output Generator communicates with the Game Controller and the Camera Input Subsys tem using the request/ready interface which is described in previous sections (and also illustrated in Figure 9). 5.2 Video Display Interface The MC6847 is used in the Color Graphics Three mode, which provides a resolution of 128x96 and 4 colors. The phi A, phi B, and Y outputs are converted to the R, G, B signals using the chroma decoder shown in Figure 10. Figure 10: Chroma Decoder. Taken from old 6.111 course notes. The NFS (field sync) signal is converted to the VSync (vertical sync) signal using the circuitry shown in Figure 11. The two potentiometers can be adjusted to fix flickering or moving up and down of the image on the monitor. The signals generated by the Video Display Interface are provided to the monitor cable which is illustrated in Figure 12. 5.3 Testing The Video Output Subsystem was tested independently of the other two subsystems. To test correct operation during calibration display mode, a PAL was programmed to implement the request/ready interface expected from the Camera Input subsystem, and to deliver a stream of pixels that had a particular pattern. A clock different from the one given to the FPGA was used, to ensure that conditions are equivalent to a situation of inter-kit communcation. The correct pattern was observed on the display. To test correct operation during game play mode, a game simulator module was written and synthesized onto the FPGA. This simulator implements the request/ready interface, and when requested, provides a list of helicopters, bombs, paratroopers and gun, and changes the positions of these objects in a known manner. The module was too large to fit into a PAL, but the module used a clock different from the one given to the Camera Input subsystem to ensure that conditions are equivalent to a situation of inter-kit communication. The objects were displayed and moved correctly. 14 Figure 11: Generating VSync. Taken from old 6.111 course notes. Figure 12: Monitor cable pins. Taken from old 6.111 course notes. A Selected Verilog code for Camera Input subsystem Listing 1: Calibrator module c a l i b r a t o r ( c l k , r e s e t , s t a r t , v i d e o r e q u e s t , mem data , addr , v i d e o r e s p o n s e , v i d e o d a t a , e n d o f f r a m e , s h o o t l o w , s h o o t h i g h , a d d r s e l , s t a t e // p h a s e ) ; i n p u t c l k , r e s e t , s t a r t , v i d e o r e q u e s t ; i n p u t [ 7 : 0 ] mem data ; o u t p u t [ 3 : 0 ] addr ; output v i d e o r e s p o n s e ; o u t p u t [ 7 : 0 ] v i d e o d a t a ; output e n d o f f r a m e ; o u t p u t [ 6 : 0 ] s h o o t l o w , s h o o t h i g h ; output a d d r s e l ; // b e g i n : debug output [ 3 : 0 ] s t a t e ; // o u t p u t phase ; / o u t p u t [ 6 : 0 ] l i n e n u m b e r ; / // end : debug reg reg reg [3:0] [3:0] s t a t e , next ; a d d r i n t ; a d d r s e l ; / / 1 : calibrator a c c e s s e s memory 0 : processor a c c e s s e s memory // c a l i b r a t i o n p h a s e reg phase ; // v i d e o d a t a t o Video Output Unit reg [ 1 2 7 : 0 ] l i n e b u f f e r ; reg [ 7 : 0 ] v i d e o d a t a i n t ; reg v i d e o r e s p o n s e ; reg e n d o f f r a m e ; // s h o o t l e v e l r e g i s t e r s . // l i n e number b e t w e e n 0 - 9 6 reg [ 6 : 0 ] shoot high int ; reg [ 6 : 0 ] s h o o t l o w i n t ; / / l i n e number b e t w e e n 0 - 9 6 // c o u n t e r v a r i a b l e s reg [ 1 0 : 0 ] f r a m e c o u n t , f r a m e c o u n t i n t ; / / c o u n t e r f o r f r a m e s p r o c e s s e d r e g [ 3 : 0 ] b y t e c o u n t , b y t e c o u n t i n t ; / / b y t e s r e a d f r o m memory r e g [ 6 : 0 ] l i n e n u m b e r , l i n e n u m b e r i n t ; / / l i n e number reg [ 3 : 0 ] t r a n s m i t c o u n t , t r a n s m i t c o u n t i n t ; in c a l i b r a t i o n mode 15 // c o n s t a n t s parameter parameter parameter parameter // s t a t e s parameter parameter parameter parameter parameter parameter parameter MAX ADDR = 4 ' h f ; LINES PER FRAME = 9 6 ; / / 9 6 ; / / s h o u l d be 9 6 MAX FRAME COUNT = 1 5 0 0 ; / / 1 5 0 0 ; / / s h o u l d be 1 5 0 0 f o r 5 s e c s / / i n c r e a s e t o match number o f HALF MAX FRAME COUNT = 7 5 0 ; / / s h o u l d be 7 5 0 f o r 5 s e c s o f c a l i b r a t i o n seconds during calibr INITIALIZE = 0 ; IDLE = 1 ; LOAD LINE = 2 ; CALIBRATE = 3 ; WAIT VID REQ = 4 ; SETUP DATA = 5 ; VERIFY TRANSMIT = 6 ; clk ) begin always @ ( posedge i f ( r e s e t ) n e x t = INITIALIZE ; e l s e s t a t e = n e x t ; l i n e n u m b e r = l i n e n u m b e r i n t ; b y t e c o u n t = b y t e c o u n t i n t ; f r a m e c o u n t = f r a m e c o u n t i n t ; t r a n s m i t c o u n t = t r a n s m i t c o u n t i n t ; case ( state ) INITIALIZE : b e g i n b y t e c o u n t i n t = 4 ' h0 ; f r a m e c o u n t = 0 ; l i n e n u m b e r = 0 ; s h o o t h i g h i n t = 9 6 ; s h o o t l o w i n t = 9 6 ; l i n e b u f f e r = 1 2 8 ' h0 ; p h a s e = 0 ; a d d r i n t = 0 ; n e x t = IDLE ; end IDLE : b e g i n i f ( f r a m e c o u n t == MAX FRAME COUNT) b e g i n n e x t = IDLE ; addr sel = 1; end e l s e i f ( s t a r t ) b e g i n n e x t = LOAD LINE ; a d d r s e l = 0 ; end e l s e n e x t = IDLE ; end LOAD LINE : begin i f ( b y t e c o u n t == 4 ' h f ) b e g i n // f i l l l a s t b y t e l i n e b u f f e r [ 1 2 7 : 1 2 0 ] = mem data ; // r e s e t a d d r e s s and b y t e c o u n t a d d r i n t = 0 ; b y t e c o u n t i n t = 0 ; // i n c r e a s e l i n e c o u n t l i n e n u m b e r i n t = l i n e n u m b e r + 1 ; // i n c r e m e n t frame c o u n t i f ( l i n e n u m b e r == LINES PER FRAME ) b e g i n l i n e n u m b e r i n t = 0 ; / / r e s e t l i n e count frame count int = frame count + 1; e n d o f f r a m e = 1 ; / / a s s e r t end-o f -f r a m e s i g n a l end e l s e l i n e n u m b e r i n t = l i n e n u m b e r + 1 ; // i f h a l f MAX FRAMES, go t o p h a s e 2 i f ( f r a m e c o u n t == HALF MAX FRAME COUNT) p h a s e = 1 ; e l s e p h a s e = 0 ; // s t o p c a l i b r a t i o n a f t e r MAX FRAME COUNT i s r e a c h e d // i f ( f r a m e c o u n t == MAX FRAME COUNT) n e x t = IDLE ; // e l s e n e x t = CALIBRATE; n e x t = CALIBRATE; end e l s e begin byte count // i n c r e m e n t 16 b y t e c o u n t i n t = b y t e c o u n t + 1 ; a d d r i n t = addr + 1 ; case ( byte count ) 0 : l i n e b u f f e r [ 7 : 0 ] = mem data ; 1 : l i n e b u f f e r [ 1 5 : 8 ] = mem data ; 2 : l i n e b u f f e r [ 2 3 : 1 6 ] = mem data ; 3 : l i n e b u f f e r [ 3 1 : 2 4 ] = mem data ; 4 : l i n e b u f f e r [ 3 9 : 3 2 ] = mem data ; 5 : l i n e b u f f e r [ 4 7 : 4 0 ] = mem data ; 6 : l i n e b u f f e r [ 5 5 : 4 8 ] = mem data ; 7 : l i n e b u f f e r [ 6 3 : 5 6 ] = mem data ; 8 : l i n e b u f f e r [ 7 1 : 6 4 ] = mem data ; 9 : l i n e b u f f e r [ 7 9 : 7 2 ] = mem data ; 1 0 : l i n e b u f f e r [ 8 7 : 8 0 ] = mem data ; 1 1 : l i n e b u f f e r [ 9 5 : 8 8 ] = mem data ; 1 2 : l i n e b u f f e r [ 1 0 3 : 9 6 ] = mem data ; 1 3 : l i n e b u f f e r [ 1 1 1 : 1 0 4 ] = mem data ; 1 4 : l i n e b u f f e r [ 1 1 9 : 1 1 2 ] = mem data ; e n d c a s e / / c a s e ( b y t e c o u n t ) n e x t = LOAD LINE ; end / / e l s e : ! i f ( b y t e c o u n t == 4 ' h f ) end / / c a s e : LOAD LINE CALIBRATE: begin // s e t t h r e s h o l d s i f ( l i n e b u f f e r > 0 ) b e g i n / / may n e e d t o c h a n g e f o r n o i s e t o l e r a n c e // s e t h i g h s h o o t t h r e s h o l d i f ( phase ) begin i f ( shoot high > line number ) // implement a v e r a g i n g l a t e r // s h o o t h i g h l e v e l = s h o o t h i g h l e v e l + l i n e n u m b e r ; s h o o t h i g h i n t = l i n e n u m b e r ; e l s e s h o o t h i g h i n t = s h o o t h i g h ; end e l s e b e g i n // s e t low s h o o t t h r e s h o l d i f ( s h o o t l o w > l i n e n u m b e r ) // implement a v e r a g i n g l a t e r // s h o o t l o w l e v e l = s h o o t l o w l e v e l + l i n e n u m b e r ; s h o o t l o w i n t = l i n e n u m b e r ; e l s e s h o o t l o w i n t = s h o o t l o w ; end end / / i f ( l i n e b u f f e r > 0 ) // t r a n s m i t b y t e s n e x t = WAIT VID REQ ; // r e s e t t r a n s m i s s i o n t r a n s m i t c o u n t = 0 ; end / / c a s e : CALIBRATE WAIT VID REQ : b e g i n i f ( v i d e o r e q u e s t ) b e g i n n e x t = SETUP DATA; / i f ( t r a n s m i t c o u n t = = 1 5 ) b e g i n t r a n s m i t c o u n t i n t = 0 ; n e x t = LOAD LINE ; end e l s e b e g i n t r a n s m i t c o u n t i n t = t r a n s m i t c o u n t + 1 ; n e x t = SETUP DATA; end / end e l s e n e x t = WAIT VID REQ ; end / / c a s e : WAIT VID REQ SETUP DATA : b e g i n c a s e ( t r a n s m i t c o u n t ) 0 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 1 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 2 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 3 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 4 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 5 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 6 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 7 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 8 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 9 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 ' 1 0 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 1 1 : v i d e o d a t a i n t = ( ( l i n e n u m b e r == s h o o t l o w ) | | ( l i n e n u m b e r == s h o o t h i g h ) ) ? 8 c o u n t ; hff hff hff hff hff hff hff hff hff hff ' hff ' hff : : : : : : : : : : line buffer [7:0]; line buffer [15:8]; line buffer [23:16]; line buffer [31:24]; line buffer [39:32]; line buffer [47:40]; line buffer [55:48]; line buffer [63:56]; line buffer [71:64]; line buffer [79:72]; : line buffer [87:80]; : line buffer [95:88]; 17 12: video data int = 13: video data int = 14: video data int = 15: video data int = endcase / / case ( t r a s m i t n e x t = VERIFY TRANSMIT; end / / c a s e : SETUP DATA (( line number (( line number (( line number (( line number count ) == == == == shoot shoot shoot shoot low low low low ) ) ) ) || || || || ( ( ( ( line line line line number number number number == == == == shoot shoot shoot shoot high high high high )) )) )) )) ? ? ? ? 8 8 8 8 ' ' ' ' hff hff hff hff : : : : line line line line buffer buffer buffer buffer [103:96] [111:104 [119:112 [127:120 VERIFY TRANSMIT : b e g i n i f ( v i d e o r e q u e s t ) b e g i n // a c k n o w l e d g e r e q u e s t v i d e o r e s p o n s e = 1 ; n e x t = VERIFY TRANSMIT; end e l s e b e g i n v i d e o r e s p o n s e = 0 ; e n d o f f r a m e = 0 ; i f ( t r a n s m i t c o u n t = = 1 5 ) b e g i n / i f ( l i n e n u m b e r = LINES PER FRAME ) n e x t = IDLE ; = e l s e b e g i n t r a n s m i t c o u n t i n t = 0 ; n e x t = LOAD LINE ; end / t r a n s m i t c o u n t i n t = 0 ; n e x t = IDLE ; end e l s e b e g i n t r a n s m i t c o u n t i n t = t r a n s m i t c o u n t + 1 ; n e x t = WAIT VID REQ ; end end end e n d c a s e / / c a s e ( s t a t e ) end / / a l w a y s @ ( p o s e d g e c l k ) a s s i g n a d dr = a d d r i n t ; a s s i g n s h o o t l o w = s h o o t l o w i n t ; a s s i g n s h o o t h i g h = s h o o t h i g h i n t ; a s s i g n v i d e o d a t a = v i d e o d a t a i n t ; endmodule / / c a l i b r a t o r 18 Listing 2: Processor module p r o c e s s o r ( c l k , r e s e t , s t a r t , i n d a t a , s h o o t l o w , addr , p o s i t i o n , s h o o t , // b e g i n : debug state / line number , low addr , high addr / // end : debug ) ; i n p u t c l k , r e s e t , s t a r t ; i n p u t [ 7 : 0 ] i n d a t a ; i n p u t [ 6 : 0 ] s h o o t l o w ; i n p u t [ 6 : 0 ] s h o o t h i g h ; output output output [3:0] [7:0] addr ; p o s i t i o n ; s h o o t ; shoot high , // b e g i n : debug o u t p u t [ 3 : 0 ] s t a t e ; / o u t p u t [ 6 : 0 ] l i n e n u m b e r ; o u t p u t [ 7 : 0 ] l o w a d d r , h i g h a d d r ; / // end : debug reg reg [3:0] [3:0] s t a t e , n e x t ; a d d r i n t ; // o u t p u t r e g i s t e r s reg s h o o t , s h o o t i n t ; reg [ 7 : 0 ] p o s i t i o n ; // l e f t and r i g h t c o o r d i n a t e s reg [ 7 : 0 ] l e f t , r i g h t ; reg [ 7 : 0 ] sum ; //16- p i x e l reg [ 7 : 0 ] reg [ 7 : 0 ] b u f f e r with corresponding l o w b y t e , h i g h b y t e ; l o w a d d r , h i g h a d d r ; a d d r e s s e s // l i n e number reg [ 6 : 0 ] line number , // Implement if l i n e n u m b e r i n t ; shifter buff needed to avoid using V e r i l o g s i g n . S a v e s some l o g i c time permits : : // c o n s t a n t s parameter parameter parameter parameter parameter MAX ADDR = 4 ' h f ; LINES PER FRAME = 9 6 ; / / a c t u a l WINDOW = 8 ' h f f ; MAX FRAME COUNT = 4 8 0 ; HALF MAX FRAME COUNT = 2 4 0 ; value s h o u l d be 9 6 // s t a t e s parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter INITIALIZE = 0 ; IDLE = 1 ; INIT HIGH BYTE = 2 ; SETUP LOW BYTE = 3 ; INIT LOW BYTE = 4 ; COMPUTE BOUNDS = 5 ; SHIFT BYTE = 6 ; LOAD ADDR LOW BYTE = 7 ; LOAD DATA LOW BYTE = 8 ; TRANSMIT = 9 ; clk ) begin always @ ( posedge i f ( r e s e t ) s t a t e = INITIALIZE ; e l s e s t a t e = n e x t ; line number = line number int ; case ( state ) INITIALIZE : b e g i n a d d r i n t = 4 ' h f ; l o w a d d r = 4 ' h1 ; h i g h a d d r = 4 ' h0 ; l i n e n u m b e r = 0 ; l e f t = 1 2 8 ; 19 n e x t = IDLE ; / / change when you i m p l e m e n t c a l i b r a t i o n end IDLE : b e g i n a d d r i n t = 4 ' h0 ; l o w a d d r = 4 ' h1 ; h i g h a d d r = 4 ' h0 ; i f ( s t a r t ) b e g i n l i n e n u m b e r i n t = l i n e n u m b e r + 1 ; n e x t = INIT HIGH BYTE ; end e l s e n e x t = IDLE ; end INIT HIGH BYTE : b e g i n h i g h b y t e = i n d a t a ; n e x t = SETUP LOW BYTE; end SETUP LOW BYTE : b e g i n a d d r i n t = 4 ' h1 ; n e x t = INIT LOW BYTE ; end INIT LOW BYTE : b e g i n l o w b y t e = i n d a t a ; n e x t = COMPUTE BOUNDS; end COMPUTE BOUNDS: b e g i n // d e t e c t s h o o t g e s t u r e // c h e c k i f hand i s above upper t h r e s h o l d i f ( { l o w b y t e [ 7 : 0 ] , h i g h b y t e [ 7 : 0 ] } > 0 ) b e g i n // i f l a s t frame was a s h o o t , don ' t a s s e r t s h o o t i f ( l i n e n u m b e r <= s h o o t h i g h ) s h o o t i n t = 1 ' b1 ; e l s e i f ( l i n e n u m b e r >= s h o o t l o w ) s h o o t i n t = 1 ' b0 ; e l s e s h o o t i n t = s h o o t ; end e l s e s h o o t i n t = s h o o t ; / / may c a u s e p r o b l e m s l a t e r ? ? i f ( l e f t == 128) begin // f i n d l e f t boundary o f p l a y e r i f i t hasn ' t b e e n f o u n d y e t i f ( h i g h b y t e == WINDOW) l e f t = ( h i g h a d d r 8 ) ; e l s e i f ( { h i g h b y t e [ 6 : 0 ] , l o w b y t e [ 7 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 5 : 0 ] , l o w b y t e [ 7 : 6 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 4 : 0 ] , l o w b y t e [ 7 : 5 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 3 : 0 ] , l o w b y t e [ 7 : 4 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 2 : 0 ] , l o w b y t e [ 7 : 3 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 1 : 0 ] , l o w b y t e [ 7 : 2 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( { h i g h b y t e [ 0 ] , l o w b y t e [ 7 : 1 ] } = = WINDOW) l e f t = ( h i g h a d d r e l s e i f ( l o w b y t e == WINDOW) l e f t = ( l o w a d d r 8 ) ; / / n e e d t o r e s o l v e e l s e l e f t = 1 2 8 ; end e l s e l e f t = l e f t ; / / i f ( l e f t = = 8 ' h f f ) 8 ) + 1 ; 8 ) + 2 ; 8 ) + 3 ; 8 ) + 4 ; 8 ) + 5 ; 8 ) + 6 ; 8 ) + 7 ; a d d r e s s mapping t o position // f i n d r i g h t boundary i f ( l o w b y t e == WINDOW) r i g h t = ( l o w a d d r 8 ) + 7 ; e l s e i f ( { h i g h b y t e [ 0 ] , l o w b y t e [ 7 : 1 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 6 ; e l s e i f ( { h i g h b y t e [ 1 : 0 ] , l o w b y t e [ 7 : 2 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 5 ; e l s e i f ( { h i g h b y t e [ 2 : 0 ] , l o w b y t e [ 7 : 3 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 4 ; e l s e i f ( { h i g h b y t e [ 3 : 0 ] , l o w b y t e [ 7 : 4 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 3 ; e l s e i f ( { h i g h b y t e [ 4 : 0 ] , l o w b y t e [ 7 : 5 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 2 ; e l s e i f ( { h i g h b y t e [ 5 : 0 ] , l o w b y t e [ 7 : 6 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) + 1 ; e l s e i f ( { h i g h b y t e [ 6 : 0 ] , l o w b y t e [ 7 ] } = = WINDOW) r i g h t = ( l o w a d d r 8 ) ; e l s e i f ( h i g h b y t e == WINDOW) r i g h t = ( h i g h a d d r 8 ) + 7 ; / / n e e d t o r e s o l v e a d d r e s s // e l s e r i g h t = 0 ; n e x t = SHIFT BYTE ; end SHIFT BYTE : begin mapping t o p o s i t i o n h i g h b y t e = l o w b y t e ; h i g h a d d r = l o w a d d r ; i f ( addr == MAX ADDR && l i n e n u m b e r == LINES PER FRAME ) n e x t = TRANSMIT; / / l i n e s e l s e i f ( addr = = MAX ADDR) n e x t = IDLE ; e l s e n e x t = LOAD ADDR LOW BYTE; end LOAD ADDR LOW BYTE : b e g i n a d d r i n t = addr + 1 ; n e x t = LOAD DATA LOW BYTE ; end LOAD DATA LOW BYTE : b e g i n l o w a d d r = addr ; l o w b y t e = i n d a t a ; n e x t = COMPUTE BOUNDS; per frame c o n d i t i o n not b e i n g me 20 end TRANSMIT : b e g i n // a s s i g n s h o o t s i g n a l s h o o t = s h o o t i n t ; // a s s e r t s h o o t and p o s i t i o n o u t p u t s i f ( l e f t != 8 ' hf f ) begin sum = l e f t + r i g h t ; p o s i t i o n = { 1 ' b0 , sum [ 7 : 1 ] } ; end / / e l s e send d e f a u l t v a l u e i n d i c a t i n g no p o s i t i o n // r e s e t l i n e c o u n t l i n e n u m b e r i n t = 0 ; n e x t = IDLE ; end e n d c a s e / / c a s e ( s t a t e ) end / / a l w a y s @ ( p o s e d g e c l k ) a s s i g n a d dr = a d d r i n t ; endmodule / / p r o c e s s o r data available xx 21 B Selected Verilog code for Game Controller Listing 3: Updating objects module m i n o r o u t p u t ( c l k , r e s e t , s t a r t o u t p u t , p o s i t i o n , o u t p u t d o n e , o u t r e q u e s t , o u t r e a d y , o u t b u s , o u t a d d r , q , n u m h e l i , n umobject , numbullet , b u l l e t 1 , b u l l e t 2 , b u l l e t 3 , b u l l e t 4 , i n p u t c l k ; i n p u t r e s e t ; i n p u t s t a r t o u t p u t ; i n p u t [ 6 : 0 ] p o s i t i o n ; o u t p u t o u t p u t d o n e ; i n p u t o u t r e q u e s t ; output out ready ; output [ 7 : 0 ] out bus ; output [ 4 : 0 ] out addr ; input [ 2 0 : 0 ] q ; i n p u t [ 4 : 0 ] numheli ; i n p u t [ 4 : 0 ] numobject ; input [ 2 : 0 ] numbullet ; input [ 1 3 : 0 ] bullet1 ; input [ 1 3 : 0 ] bullet2 ; input [ 1 3 : 0 ] bullet3 ; input [ 1 3 : 0 ] bullet4 ; output [ 4 : 0 ] reg reg reg reg reg reg reg reg reg reg reg reg t e s t e r ; / /TESTER tester ); [ 4 : 0 ] state ; [ 4 : 0 ] next ; [ 4 : 0 ] return state ; [ 4 : 0 ] n e x t r e t u r n s t a t e ; [ 4 : 0 ] c o u n t ; [ 4 : 0 ] n e x t c o u n t ; [ 4 : 0 ] a d dr ; [ 4 : 0 ] n e x t a d d r ; o u t r e a d y r e g ; [ 7 : 0 ] out bus reg ; next out ready ; [ 7 : 0 ] next out bus ; TROOPER CODE=8 ' b00000000 ; BOMB CODE=8 ' b00000001 ; HELI1 CODE=8 ' b00000010 ; HELI2 CODE=8 ' b00000011 ; EXPLODE1 CODE=8 ' b00000100 EXPLODE2 CODE=8 ' b00000101 GUN1 CODE=8 ' b00000110 ; GUN2 CODE=8 ' b00000111 ; HELI1REV CODE=8 ' b00001000 HELI2REV CODE=8 ' b00001001 BULLET CODE=8 ' b00001010 ; END CODE=8 ' b11000000 ; parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter ; ; ; ; HEIGHT HELI LEFT=7 ' b0000000 ; HEIGHT HELI RIGHT=7 ' b0001000 ; DROP OFFSET=7 ' b0000110 ; ORIGIN HELI LEFT=8 ' b01111111 ; ORIGIN HELI RIGHT=8 ' b11110001 ; FIRSTHELI=5 ' b00000 ; FIRSTOBJECT=5 ' b01000 ; INIT =0; IDLE=1; WAIT=2; GUN ONE1=3; GUN ONE2=4; GUN ONE3=5; GUN TWO1=6; GUN TWO2=7; GUN TWO3=8; OBJECT=9; OBJECT WAIT=10; OBJECT1=11; OBJECT2=12; OBJECT3=13; OBJECT EXPLODED1=14; OBJECT EXPLODED2=15; OBJECT EXPLODED3=16; HELI=17; HELI WAIT=18; HELI ONE1=19; HELI ONE2=20; HELI ONE3=21; HELI TWO1=22; 22 parameter parameter parameter parameter parameter parameter parameter parameter HELI TWO2=23; HELI TWO3=24; BULLET=25; BULLET1=26; BULLET2=27; BULLET3=28; END=29; END2=30; always @ ( posedge c l k ) begin i f ( reset ) begin s t a t e <=INIT ; c o u n t <=0; o u t r e a d y r e g <=0; o u t b u s r e g <=0; end else begin s t a t e <=n e x t ; c o u n t<=n e x t c o u n t ; r e t u r n s t a t e <=n e x t r e t u r n s t a t e ; o u t r e a d y r e g <=n e x t o u t r e a d y ; o u t b u s r e g <=n e x t o u t b u s ; addr<=n e x t a d d r ; end end always @ ( s t a t e ) begin n e x t a d d r=a d d r ; n e x t=s t a t e ; n e x t c o u n t=c o u n t ; n e x t o u t r e a d y=o u t r e a d y r e g ; n e x t o u t b u s=o u t b u s r e g ; n e x t r e t u r n s t a t e=r e t u r n s t a t e ; c a s e ( s t a t e ) INIT : n e x t=IDLE ; IDLE : i f ( s t a r t o u t p u t ) n e x t=GUN ONE1; WAIT : begin i f ( o u t r e q u e s t ==1) n e x t=r e t u r n s t a t e ; n e x t o u t r e a d y =0; end GUN ONE1 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=GUN ONE2 ; end n e x t o u t r e a d y =1; GUN1 CODE ; n e x t o u t b u s= end GUN ONE2 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=GUN ONE3 ; end n e x t o u t r e a d y =1; n e x t o u t b u s ={1 'b0 , p o s i t i o n }-8' b00 0 0 0 1 1 1 ; end GUN ONE3 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e= GUN TWO1; end n e x t o u t r e a d y =1; n e x t o u t b u s =8 ' b01010011 ; end GUN TWO1: begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e= GUN TWO2; end n e x t o u t r e a d y =1; n e x t o u t b u s= GUN2 CODE ; end GUN TWO2: 23 begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e= GUN TWO3; end n e x t o u t r e a d y =1; n e x t o u t b u s ={1 'b0 , p o s i t i o n }+8 ' b00 0 0 0 0 0 1 ; end GUN TWO3: begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT ; n e x t c o u n t =0; end n e x t o u t r e a d y =1; n e x t o u t b u s =8 ' b01010011 ; end OBJECT : begin i f ( c ount<numobject ) begin n e x t=OBJECT WAIT; n e x t a d d r=FIRSTOBJECT o u n t ; +c end else begin n e x t=HELI ; n e x t c o u n t =0; end end OBJECT WAIT : n e x t=OBJECT1 ; OBJECT1 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT2 ; end n e x t o u t r e a d y =1; TROOPER CODE; i f ( q [20]==0 && q [ 0 ] = = 0 ) n e x t o u t b u s= e l s e i f ( q [20]==0 && q [ 0 ] = = 1 ) n e x t o u t b u s= BOMB CODE ; e l s e n e x t o u t b u s= EXPLODE1 CODE ; end OBJECT2 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT3 ; end n e x t o u t r e a d y =1; i f ( q [ 2 0 ] = = 0 ) n e x t o u t b u s ={1 'b0 , q [ 1 9 : 1 3 ] } ; e l s e n e x t o u t b u s ={1 'b0 , q [ 1 9 : 1 3 ] } - 8 ' b 0 0 0 0 0 1 0 0 ; end OBJECT3 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t c o u n t=c o u n t +1; i f ( q [ 2 0 ] = = 0 ) n e x t r e t u r n s t a t e=OBJECT ; e l s e n e x t r e t u r n s t a t e=OBJECT EXPLODED1; end n e x t o u t r e a d y =1; n e x t o u t b u s ={1 'b0 , q [ 1 2 : 6 ] } ; end OBJECT EXPLODED1: begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT EXPLODED2; end n e x t o u t r e a d y =1; n e x t o u t b u s= EXPLODE2 CODE ; end OBJECT EXPLODED2: begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT EXPLODED3; end n e x t o u t r e a d y =1; 24 n e x t o u t b u s ={1 'b0 , q [ 1 9 : 1 3 ] } + 8 ' b00 0 0 0 1 0 0 ; end OBJECT EXPLODED3: begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=OBJECT ; end n e x t o u t r e a d y =1; n e x t o u t b u s ={1 'b0 , q [ 1 2 : 6 ] } ; end HELI : begin i f ( c ount<numheli ) b e g i n n e x t= HELI WAIT ; n e x t a d d r=FIRSTHELI+c o u n t ; end e l s e begin n e x t= BULLET ; n e x t c o u n t =0; end end HELI WAIT : n e x t=HELI ONE1 ; HELI ONE1 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI ONE2 ; end n e x t o u t r e a d y =1; HELI1 CODE ; i f ( q [20]==0 && q [ 1 9 ] = = 0 ) n e x t o u t b u s= e l s e i f ( q [20]==0 && q [ 1 9 ] = = 1 ) n e x t o u t b u s=HELI2REV CODE ; e l s e n e x t o u t b u s= EXPLODE1 CODE ; end HELI ONE2 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI ONE3 ; end n e x t o u t r e a d y =1; n e x t o u t b u s=q [ 1 8 : 1 1 ] ; end HELI ONE3 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI TWO1 ; end n e x t o u t r e a d y =1; i f ( q [ 1 9 ] = = 0 ) n e x t o u t b u s ={1 'b0 , HEIGHT HELI LEFT } ; e l s e i f ( q [ 1 9 ] = = 1 ) n e x t o u t b u s ={1 ' b0 , HEIGHT HELI RIGHT } ; end HELI TWO1 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI TWO2 ; end n e x t o u t r e a d y =1; i f ( q [20]==0 && q [ 1 9 ] = = 0 ) n e x t o u t b u s= HELI2 CODE ; e l s e i f ( q [20]==0 && q [ 1 9 ] = = 1 ) n e x t o u t b u s=HELI1REV CODE ; EXPLODE2 CODE ; e l s e n e x t o u t b u s= end HELI TWO2 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI TWO3 ; end n e x t o u t r e a d y =1; n e x t o u t b u s=q [ 1 8 : 1 1 ] + 8 ' b00001000 ; end HELI TWO3 : begin i f ( o u t r e q u e s t ==0) begin n e x t= WAIT; n e x t r e t u r n s t a t e=HELI ; 25 n e x t c o u n t=c o u n t +1; end n e x t o u t r e a d y =1; i f ( q [ 1 9 ] = = 0 ) n e x t o u t b u s ={1 'b0 , HEIGHT HELI LEFT } ; e l s e i f ( q [ 1 9 ] = = 1 ) n e x t o u t b u s ={1 ' b0 , HEIGHT HELI RIGHT } ; end BULLET : i f ( c o u n t [ 2 : 0 ] < n u m b u l l e t && c o u n t==5'b 0 0 0 0 0 && (& b u l l e t 1 [ 6 : 0 ] ) ! = 1 ) n e x t=BULLET1 ; e l s e i f ( c o u n t [ 2 : 0 ] < n u m b u l l e t && c o u n t ==5'b 0 0 0 0 1 && (& b u l l e t 2 [ 6 : 0 ] ) ! = 1 ) n e x t=BULLET1 ; e l s e i f ( c o u n t [ 2 : 0 ] < n u m b u l l e t && c o u n t ==5'b 0 0 0 1 0 && (& b u l l e t 3 [ 6 : 0 ] ) ! = 1 ) n e x t=BULLET1 ; e l s e i f ( c o u n t [ 2 : 0 ] < n u m b u l l e t && c o u n t ==5'b 0 0 0 1 1 && (& b u l l e t 4 [ 6 : 0 ] ) ! = 1 ) n e x t=BULLET1 ; e l s e i f ( count [2:0] < numbullet ) b e g i n n e x t= BULLET ; n e x t c o u n t=c o u n t +1; end e l s e n e x t= END; BULLET1 : begin i f ( o u t r e q u e s t ==0) b e g i n n e x t= WAIT; n e x t r e t u r n s t a t e=BULLET2 ; end n e x t o u t r e a d y =1; n e x t o u t b u s=BULLET CODE ; end BULLET2 : begin i f ( o u t r e q u e s t ==0) b e g i n n e x t= WAIT; n e x t r e t u r n end n e x t o u t r e a d y =1; i f ( c o u n t==5'b00000 ) i f ( c o u n t==5'b00001 ) i f ( c o u n t==5'b00010 ) i f ( c o u n t==5'b00011 ) end BULLET3 : begin i f ( o u t r e q u e s t ==0) b e g i n n e x t= WAIT; n e x t c o u n t=c o u n t +1; n e x t r e t u r n s t a t e=BULLET ; end n e x t o u t r e a d y =1; i f ( c o u n t==5'b00000 ) n e x t o u t b u s ={1 ' b0 , i f ( c o u n t==5'b00001 ) n e x t o u t b u s ={1 ' b0 , i f ( c o u n t==5'b00010 ) n e x t o u t b u s ={1 ' b0 , i f ( c o u n t==5'b00011 ) n e x t o u t b u s ={1 ' b0 , end END: begin i f ( o u t r e q u e s t ==0) n e x t=END2 ; n e x t o u t r e a d y =1; END CODE; n e x t o u t b u s= end END2 : begin n e x t=IDLE ; n e x t o u t r e a d y =0; end endcase end assign assign assign assign assign o u t r e a d y=o u t r e a d y r e g ; o u t b u s=o u t b u s r e g ; o u t a d d r=addr ; o u t p u t d o n e=( s t a t e== END2 ) ; t e s t e r [ 4 : 0 ] = numheli ; / /TESTER s t a t e=BULLET3 ; n e x t n e x t n e x t n e x t out out out out b u s ={1 ' b0 , b u s ={1 ' b0 , b u s ={1 ' b0 , b u s ={1 ' b0 , bullet1 bullet2 bullet3 bullet4 [ 1 3 : 7 ] } ; [ 1 3 : 7 ] } ; [ 1 3 : 7 ] } ; [13:7]}; bullet1 bullet2 bullet3 bullet4 [ 6 : 0 ] } ; [ 6 : 0 ] } ; [ 6 : 0 ] } ; [ 6 : 0 ] } ; endmodule 26 Listing 4: Random number generation module random ( c l k , in , rand ) ; i n p u t c l k ; i n p u t i n ; output [ 7 : 0 ] reg reg reg reg [7:0] [7:0] [2:0] [2:0] rand ; r a n d r e g ; next rand ; state ; next ; a l w a y s @ ( p o s e d g e c l k ) b e g i n s t a t e <=n e x t ; r a n d r e g <=n e x t r a n d ; end parameter parameter parameter parameter parameter parameter parameter parameter BIT0=0; BIT1=1; BIT2=2; BIT3=3; BIT4=4; BIT5=5; BIT6=6; BIT7=7; a l w a y s @ ( s t a t e ) b e g i n n e x t r a n d=r a n d r e g ; c a s e ( s t a t e ) BIT0 : b e g i n n e x t=BIT1 ; n e x t r a n d [ 0 ] = r a n d end BIT1 : begin n e x t=BIT2 ; next rand [1]= rand end BIT2 : begin n e x t=BIT3 ; next rand [2]= rand end BIT3 : begin n e x t=BIT4 ; next rand [3]= rand end BIT4 : begin n e x t=BIT5 ; next rand [4]= rand end BIT5 : begin n e x t=BIT6 ; next rand [5]= rand end BIT6 : begin n e x t=BIT7 ; next rand [6]= rand end BIT7 : begin n e x t=BIT0 ; next rand [7]= rand end endcase end assign r a n d=r a n d r e g ; reg [ 0 ] ^ in ; reg [ 1 ] ^ in ; reg [ 2 ] ^ in ; reg [ 3 ] ^ in ; reg [ 4 ] ^ in ; reg [ 5 ] ^ in ; reg [ 6 ] ^ in ; reg [ 7 ] ^ in ; endmodule 27 C Selected Verilog code for Video Output subsystem Listing 5: Top level module module v i d e o o u t p u t ( c l k , r e s e t , e x t a d d r , / / [ 1 2 : 0 ] n f s , nms , e x t d a t a , / / [ 7 : 0 ] G b , W b, calib , r e q u e s t , r e a d y , p i x e l s , / / [ 7 : 0 ] e n d f r ame , game , d o g ame sim ) ; i n p u t c l k ; i n p u t r e s e t ; i n o u t [ 1 2 : 0 ] e x t a d d r ; i n p u t n f s ; o u t p u t nms ; r e g nms ; i n o u t [ 7 : 0 ] e x t d a t a ; o u t p u t G b ; o u t p u t W b ; i n p u t c a l i b ; o u t p u t r e q u e s t ; r e g r e q u e s t ; i n p u t r e a d y ; r e g r e a d y s y n c ; i n p u t [ 7 : 0 ] p i x e l s ; r e g [ 7 : 0 ] p i x e l s s y n c ; i n p u t endframe ; r e g e n d f r a m e s y n c ; i n p u t game ; i n p u t do game sim ; r e g read , w r i t e ; w i r e [ 2 : 0 ] c n t r s t a t e ; w i r e d a t a o e n , a d d r e s s l o a d , d a t a s a m p l e ; r e g [ 1 2 : 0 ] r a m a d d r e s s ; r e g [ 7 : 0 ] d a t a w r i t e ; r e g [ 7 : 0 ] d a t a r e a d ; r e g a d d r e s s o e n ; c o n t r o l l e r m y c o n t r o l l e r ( c l k , 1 , G b , W b , r a m a d d r e s s , e x t a d d r , d a t a w r i t e , d a t a r e a d , e x t d a t a , read , write , c n t r s t a t e , data oen , a d d r e s s l o a d , data sample , address oen ); r e g [ 6 : 0 ] i m a g e a d d r e s s ; w i r e [ 1 5 : 0 ] i m a g e q ; i m a g e rom image rom1 ( i m a g e a d d r e s s , i m a g e q ) ; r e g [ 6 : 0 ] g u n a d d r e s s ; w i r e [ 1 5 : 0 ] gun q ; gun rom2 gun rom21 ( g u n a d d r e s s [ 4 : 0 ] , g u n q ) ; r e g [ 6 : 0 ] d i g i t s a d d r e s s ; w i r e [ 7 : 0 ] d i g i t s q ; d i g i t s r o m d i g i t s r o m 1 ( d i g i t s a d d r e s s , w i r e s i m r e a d y ; w i r e [ 7 : 0 ] s i m p i x e l s ; gamesim mygamesim ( c l k , r e s e t , do game sim , r e q u e s t , s i m r e a d y , s i m p i x e l s ) ; digits q ); r e g [ 5 : 0 ] s t a t e ; p a r a m e t e r DISPLAY = 0 ; p a r a m e t e r START WRITING = 1 ; p a r a m e t e r WRITE CALIB = 2 ; 28 parameter parameter parameter parameter parameter parameter parameter p a r a m e t e r p a r a m e t e r parameter parameter parameter parameter parameter parameter parameter parameter parameter parameter WAIT READY = 3 ; GRAB DATA = 4 ; GRAB DATA OTHER = 5 ; WRITE 2 = 6 ; WRITE 3 = 7 ; WRITE 4 = 8 ; BLANK GAME = BLANK GAME 2 BLANK GAME 3 BLANK GAME 4 1 9 ; = 2 0 ; = 21; = 22; WRITE GAME = 9 ; WAIT GAME READY = 1 0 ; GRAB GAME DATA = 1 1 ; WRITE GAME 2 = 1 2 ; WRITE GAME 3 = 1 3 ; WRITE GAME 4 = 1 4 ; WRITE GAME 5 = 1 5 ; WRITE GAME 6 = 1 6 ; WRITE GAME 7 = 1 7 ; reg [ 7 : 0 ] h a l f l i n e ; reg [ 7 : 0 ] write byte1 ; reg [ 7 : 0 ] write byte2 ; reg which byte ; p a r a m e t e r REVERSE = 2 7 ; p a r a m e t e r SMOOTH WRITE = 2 3 ; p a r a m e t e r SMOOTH READ = 2 4 ; p a r a m e t e r SMOOTH READ 2 = 2 5 ; p a r a m e t e r SMOOTH WRITE 2= 2 6 ; reg [ 1 : 0 ] text count ; p a r a m e t e r WRITE TEXT = p a r a m e t e r WRITE TEXT 2 p a r a m e t e r WRITE TEXT 3 p a r a m e t e r WRITE TEXT 4 p a r a m e t e r WRITE TEXT 5 p a r a m e t e r WRITE TEXT 6 p a r a m e t e r WRITE TEXT 7 28; = 29; = 30; = 31; = 32; = 33; = 34; p a r a m e t e r DONE WRITING = 1 8 ; reg [ 7 : 0 ] grabbed pixels ; reg grabbed other ; reg reg reg reg reg [7:0] [7:0] [7:0] [1:0] [3:0] type ; xpos ; ypos ; game grabbed count ; digit ; r e g [ 3 : 0 ] row ; r e g w h i c h h a l f ; w i r e [ 5 : 0 ] t h i n g ; a s s i g n t h i n g = ( xpos [ 7 : 2 ] + w h i c h h a l f + 1 ) ; a l w a y s @( p o s e d g e c l k ) b e g i n i f ( do game sim ) b e g i n r e a d y s y n c <= s i m r e a d y ; p i x e l s s y n c <= s i m p i x e l s ; end e l s e b e g i n r e a d y s y n c <= r e a d y ; p i x e l s s y n c <= p i x e l s ; end e n d f r a m e s y n c <= endframe ; if ( r e s e t ) b e g i n nms <= 0; a d d r e s s o e n <= 1; r e a d <= 0; w r i t e <= 0; r a m a d d r e s s <= 13 ' d 0 ; r e q u e s t <= 0; s t a t e <= START WRITING ; if ( s t a t e ! = DISPLAY ) b e g i n // w r i t e t h e d i s p l a y ram case ( state ) START WRITING : b e g i n nms <= 0; a d d r e s s o e n <= 1; r e a d <= 0; w r i t e <= 0; end else 29 r a m a d d r e s s <= 13 ' d 0 ; r e q u e s t <= 0; i f ( c a l i b ) s t a t e <= WRITE CALIB ; e l s e i f ( game ) b e g i n g a m e g r a b b e d c o u n t <= 2 ' d 0 ; s t a t e <= BLANK GAME; end end // c a l i b r a t i o n WRITE CALIB : b e g i n i f ( ! ready sync ) begin r e q u e s t <= 1; s t a t e <= WAIT READY; end end WAIT READY : b e g i n i f ( r e a d y s y n c ) b e g i n s t a t e <= GRAB DATA; end end GRAB DATA : b e g i n g r a b b e d p i x e l s <= p i x e l s ; d a t a w r i t e [ 7 ] < = p i x e l s [ 7 ] ; d a t a w r i t e [ 6 ] < = p i x e l s [ 7 ] ; d a t a w r i t e [ 5 ] < = p i x e l s [ 6 ] ; d a t a w r i t e [ 4 ] < = p i x e l s [ 6 ] ; d a t a w r i t e [ 3 ] < = p i x e l s [ 5 ] ; d a t a w r i t e [ 2 ] < = p i x e l s [ 5 ] ; d a t a w r i t e [ 1 ] < = p i x e l s [ 4 ] ; d a t a w r i t e [ 0 ] < = p i x e l s [ 4 ] ; g r a b b e d o t h e r <= 0; r e q u e s t <= 0; i f ( e n d f r a m e s y n c ) s t a t e < = DONE WRITING; else s t a t e < = WRITE 2 ; end GRAB DATA OTHER: b e g i n d a t a w r i t e [ 7 ] < = d a t a w r i t e [ 6 ] < = d a t a w r i t e [ 5 ] < = d a t a w r i t e [ 4 ] < = d a t a w r i t e [ 3 ] < = d a t a w r i t e [ 2 ] < = d a t a w r i t e [ 1 ] < = d a t a w r i t e [ 0 ] < = g r a b b e d o t h e r <= s t a t e <= WRITE 2 ; end WRITE 2 : end WRITE 3 : end WRITE 4 : b e g i n w r i t e <= 1; s t a t e <= WRITE 3 ; b e g i n w r i t e <= 0; s t a t e <= WRITE 4 ; begin i f ( c n t r s t a t e == 3 'b 0 ) b e g i n i f ( ram address < 13 'd 3 0 7 1 ) begin r a m a d d r e s s <= r a m a d d r e s s + 1 3 ' d 1 ; i f ( grabbed other ) s t a t e < = WRITE CALIB ; else s t a t e < = GRAB DATA OTHER; end else s t a t e <= DONE WRITING; end c a l i b r a t i o n grabbed grabbed grabbed grabbed grabbed grabbed grabbed grabbed 1; pixels pixels pixels pixels pixels pixels pixels pixels [ 3 ] ; [ 3 ] ; [ 2 ] ; [ 2 ] ; [ 1 ] ; [ 1 ] ; [ 0 ] ; [ 0 ] ; end / / end o f / / game p l a y BLANK GAME : b e g i n i f ( ( ram address < 13 'd 3 2 ) | | 30 else else ( r a m a d d r e s s >= 13 ' d 3 0 4 0 ) ) d a t a w r i t e <= 8 ' b 1 1 1 1 1 1 1 1 ; i f ( r a m a d d r e s s [ 4 : 0 ] = = 5 ' b 0 0 0 0 0 ) d a t a w r i t e <= 8 ' b 1 1 0 0 0 0 0 0 ; i f ( r a m a d d r e s s [ 4 : 0 ] = = 5 ' b 1 1 1 1 1 ) d a t a w r i t e <= 8 ' b 0 0 0 0 0 0 1 1 ; e l s e d a t a w r i t e <= 8 ' b 0 0 0 0 0 0 0 0 ; s t a t e <= BLANK GAME 2 ; end BLANK GAME 2 : b e g i n w r i t e <= 1; s t a t e <= BLANK GAME 3 ; end BLANK GAME 3 : b e g i n w r i t e <= 0; s t a t e <= BLANK GAME 4 ; end BLANK GAME 4 : b e g i n i f ( c n t r s t a t e == 3 'b 0 ) b e g i n i f ( ram address < 13 'd 3 0 7 1 ) begin r a m a d d r e s s <= r a m a d d r e s s + 1 3 ' d 1 ; s t a t e <= BLANK GAME; end e ls e begin s t a t e <= WRITE GAME; end end end WRITE GAME : b e g i n i f ( ! r e a d y s y n c ) b e g i n r e q u e s t <= 1; s t a t e <= WAIT GAME READY ; end end WAIT GAME READY : b e g i n i f ( r e a d y s y n c ) b e g i n s t a t e <= GRAB GAME DATA; end end GRAB GAME DATA : b e g i n i f ( g a m e g r a b b e d c o u n t = = 2 ' d 0 ) t y p e <= p i x e l s s y n c ; e l s e i f ( g a m e g r a b b e d c o u n t = = 2 ' d 1 ) x p o s <= p i x e l s s y n c ; e l s e i f ( g a m e g r a b b e d c o u n t = = 2 ' d 2 ) y p o s <= p i x e l s s y n c ; g a m e g r a b b e d c o u n t <= g a m e g r a b b e d c o u n t + 2 ' d 1 ; r e q u e s t <= 0; if ( p i x e l s s y n c == 8 'b 1 1 0 0 0 0 0 0 ) s t a t e <= DONE WRITING; ( game grabbed count < 2 'd 2 ) s t a t e < = WRITE GAME; else s t a t e < = WRITE GAME 2 ; if end WRITE GAME 2 : b e g i n r a m a d d r e s s <= { y p o s [ 7 : 0 ] , 5 ' b 0 0 0 0 0 } + x p o s [ 7 : 2 ] ; // i m a g e a d d r e s s <= t y p e [ 6 : 0 ] 7 ' d // g u n a d d r e s s <= ( t y p e [ 6 : 0 ] - 7 ' d 6 ) i f ( t y p e < 8 ' d 6 ) i m a g e a d d r e s s <= t y p e [ 6 : 0 ] e l s e i f ( t y p e = = 8 ' d 8 ) i m a g e a d d r e s s <= 7 ' d 2 4 ; e l s e i f ( t y p e = = 8 ' d 9 ) i m a g e a d d r e s s <= 7 ' d 3 6 ; g u n a d d r e s s <= ( t y p e [ 6 : 0 ] - 7 ' d 6 ) if 12; 7 'd 12; 7 'd 12; else 7 'd 12; ( ( type == 8 'd 1 1 | | type == 8 'd 1 2 ) ) b e g i n s t a t e <= WRITE TEXT ; end e l s e b e g i n row <= 0; s t a t e <= WRITE GAME 3 ; end end WRITE GAME 3 : begin 31 w h i c h h a l f <= 0; s t a t e <= WRITE GAME 4 ; end WRITE GAME 4 : if (! b e g i n w h i c h h a l f ) b e g i n i f ( type < 8 'd 6 ) h a l f l i n e <= i m a g e q [ 1 5 : 8 ] ; e l s e i f ( type == 8 'd 6 | | type == 8 'd 7 ) h a l f l i n e <= g u n q [ 1 5 : 8 ] ; e l s e i f ( type == 8 'd 8 | | type == 8 'd 9 ) h a l f l i n e <= i m a g e q [ 7 : 0 ] ; e l s e i f ( type == 8 'd 1 0 ) i f ( row = = 4 ' d 0 ) h a l f l i n e <= 8 ' b 1 1 0 0 0 0 0 0 ; else h a l f l i n e <= 8 ' b 0 0 0 0 0 0 0 0 ; begin i f ( type < 8 'd 6 ) h a l f l i n e <= i m a g e q [ 7 : 0 ] ; e l s e i f ( type == 8 'd 6 | | type == 8 'd 7 ) h a l f l i n e <= g u n q [ 7 : 0 ] ; e l s e i f ( type == 8 'd 8 | | type == 8 'd 9 ) h a l f l i n e <= i m a g e q [ 1 5 : 8 ] ; e l s e i f ( type == 8 'd 1 0 ) h a l f l i n e <= 8 ' b 0 0 0 0 0 0 0 0 ; end else end s t a t e <= REVERSE; end REVERSE: begin i f ( t y p e = = 8 ' d 8 | | t y p e = = 8 ' d 9 ) b e g i n h a l f l i n e [ 0 ] < = h a l f l i n e [ 7 ] ; h a l f l i n e [ 1 ] < = h a l f l i n e [ 6 ] ; h a l f l i n e [ 2 ] < = h a l f l i n e [ 5 ] ; h a l f l i n e [ 3 ] < = h a l f l i n e [ 4 ] ; h a l f l i n e [ 4 ] < = h a l f l i n e [ 3 ] ; h a l f l i n e [ 5 ] < = h a l f l i n e [ 2 ] ; h a l f l i n e [ 6 ] < = h a l f l i n e [ 1 ] ; h a l f l i n e [ 7 ] < = h a l f l i n e [ 0 ] ; end s t a t e <= SMOOTH WRITE ; end SMOOTH WRITE : b e g i n c a s e ( x p o s [ 1 : 0 ] ) 2 ' d 0 : b e g i n w r i t e write end 2 'd 1 : begin write write end 2 'd 2 : begin write write end 2 'd 3 : begin write write end e n d c a s e w h i c h b y t e <= 0; s t a t e <= SMOOTH READ; end b y t e 1 <= h a l f l i n e [ 7 : 0 ] ; b y t e 2 <= 8 ' b 0 0 0 0 0 0 0 0 ; b y t e 1 <= {2 ' b 0 0 , h a l f l i n e [ 7 : 2 ] } ; b y t e 2 <= { h a l f l i n e [ 1 : 0 ] , 6 ' b 0 0 0 0 0 0 } ; b y t e 1 <= {4 ' b 0 0 0 0 , h a l f l i n e [ 7 : 4 ] } ; b y t e 2 <= { h a l f l i n e [ 3 : 0 ] , 4 ' b 0 0 0 0 } ; b y t e 1 <= {6 ' b 0 0 0 0 0 0 , h a l f l i n e [ 7 : 6 ] } ; b y t e 2 <= { h a l f l i n e [ 5 : 0 ] , 2 ' b 0 0 } ; SMOOTH READ: b e g i n r e a d <= 1; s t a t e <= SMOOTH READ 2 ; end SMOOTH READ 2 : b e g i n r e a d <= 0; s t a t e <= SMOOTH WRITE 2 ; end SMOOTH WRITE 2 : b e g i n i f ( c n t r s t a t e = = 3 ' b 0 ) b e g i n i f ( ! which byte ) d a t a w r i t e <= w r i t e b y t e 1 else d a t a w r i t e <= w r i t e b y t e 2 | | data read ; data read ; // don ' t d i s p l a y p a r t s t h a t a r e o u t o f bounds i f ( ( r a m a d d r e s s [ 1 2 : 5 ] = = ( y p o s+row ) ) ) 32 s t a t e < = WRITE GAME 5 ; e l s e s t a t e < = WRITE GAME 7 ; end end WRITE GAME 5 : b e g i n w r i t e <= 1; s t a t e <= WRITE GAME 6 ; end WRITE GAME 6 : b e g i n w r i t e <= 0; s t a t e <= WRITE GAME 7 ; end WRITE GAME 7 : b e g i n i f ( c n t r s t a t e = = 3 ' b 0 ) b e g i n i f ( ! w h i c h b y t e ) b e g i n // r a m a d d r e s s <= r a m a d d r e s s + 1 3 ' d 1 ; r a m a d d r e s s <= { y p o s [ 7 : 0 ] , 5 ' b 0 0 0 0 0 } + t h i n g + ( 1 3 ' d 3 2 row ) ; w h i c h b y t e <= 1; s t a t e <= SMOOTH READ; end e l s e b e g i n i f ( ! which half ) begin // r a m a d d r e s s <= r a m a d d r e s s + 1 3 ' d 1 ; w h i c h h a l f <= 1; s t a t e <= WRITE GAME 4 ; end e l s e b e g i n i f ( row < 1 1 ) b e g i n r a m a d d r e s s <= r a m a d d r e s s + 1 3 ' d 3 0 ; i m a g e a d d r e s s <= i m a g e a d d r e s s + 7 ' d 1 ; g u n a d d r e s s <= g u n a d d r e s s + 7 ' d 1 ; row <= row + 4 ' d 1 ; s t a t e <= WRITE GAME 3 ; end e l s e begin g a m e g r a b b e d c o u n t <= 2 ' d 0 ; s t a t e <= WRITE GAME ; end end end end end WRITE TEXT : b e g i n i f ( t y p e = = 8 ' d 1 1 ) r a m a d d r e s s <= 13 ' d 2 8 5 1 ; e l s e r a m a d d r e s s <= 13 ' d 2 8 7 9 ; d i g i t <= x p o s - ( x p o s / 8 ' d 1 0 ) 8 ' d 1 0 ; xp o s <= x p o s / 8 ' d 1 0 ; t e x t c o u n t <= 2 ' d 0 ; s t a t e <= WRITE TEXT 2 ; end WRITE TEXT 2 : b e g i n d i g i t s a d d r e s s <= d i g i t 7 ' d 7 ; s t a t e <= WRITE TEXT 3 ; end WRITE TEXT 3 : b e g i n s t a t e <= WRITE TEXT 4 ; end WRITE TEXT 4 : b e g i n d a t a w r i t e <= d i g i t s q ; s t a t e <= WRITE TEXT 5 ; end WRITE TEXT 5 : b e g i n w r i t e <= 1; s t a t e <= WRITE TEXT 6 ; end WRITE TEXT 6 : b e g i n w r i t e <= 0; s t a t e <= WRITE TEXT 7 ; end WRITE TEXT 7 : b e g i n i f ( c n t r s t a t e = = 3 ' b 0 ) b e g i n i f ( t e x t c o u n t < 2 ' d 2 ) b e g i n r a m a d d r e s s <= r a m a d d r e s s - 1 3 ' d 1 ; 33 d i g i t <= x p o s - ( x p o s / 8 ' d 1 0 ) 8 ' d 1 0 ; x p o s <= x p o s / 8 ' d 1 0 ; t e x t c o u n t <= t e x t c o u n t + 2 ' d 1 ; s t a t e <= WRITE TEXT 2 ; end else end end end / / end o f game p l a y begin s t a t e <= WRITE GAME; DONE WRITING : b e g i n nms <= 1; a d d r e s s o e n <= 0; r e a d <= 1; s t a t e <= DISPLAY ; end default : begin s t a t e <= START WRITING ; end endcase end else begin // l e t t h e d i s p l a y c h i p r e a d f r o m t h e ram i f ( ! nfs ) begin s t a t e <= START WRITING ; end e ls e begin end end end endmodule 34 ...
View Full Document

This note was uploaded on 07/21/2009 for the course EECS 6.111 taught by Professor Prof.ananthachandrakasan during the Spring '04 term at MIT.

Ask a homework question - tutors are online