98 Tiny Breakout

98 : Tiny Breakout

  • Author: Robbert-Jan de Jager
  • Description: This is a small breakout game implemented in HDL. It uses a VGA connector to output the video signal. The game is controlled by 3 buttons. The left button moves the paddle to the left, the right button moves the paddle to the right and the action button starts the game. The game is over when all blocks are destroyed or when the ball hits the bottom of the screen.
  • GitHub repository
  • Clock: 25175000 Hz

How it works

Basic operation

The core of the design is the vga_timing module. This module generates all the required timing signals. Some of these signals like hsync and vsync are used to generate the video signal, while others like the horizontal and vertical position are used to generate the graphics. The horizontal and vertical sync signals are also used for the game logic.

Before outputting the video signal the video mux selects the correct input color to display. It does so based on the highest priority component that wants to output a color.

We have multiple painter modules. These generate from the current game state and the current horizontal and vertical position the correct color to display. Ideally the painters would not contribute to the game logic, but for optimization reasons they do.

While drawing a frame the game logic keeps track of collisions. It does so by checking if multiple painters want to draw at the same position. If so it will latch a collision, which will be processed after drawing the frame.

At the end of each frame the game logic will calculate the next ball position, taking collisions into account. The collision with the paddle is special. To have an entertaining game that does not play the same every time the ball will bounce off the paddle at a different angle depending on where it hits. This is done by splitting the paddle into multiple segments and checking for collisions with these segments. The game logic will look at the segment when a paddle collision was registered. An exception to the end of frame gamestate update is the breaking of blocks. It would require too much memory to keep the updated state for the next frame. Instead we will update the row of blocks that was just finished drawing.

We can display a grid of 13x16 blocks. This requires 208 bits of memory. This is a lot of memory for such a small design and takes up a lot of space. To reduce the number of connections the state has been put into a shift register that outputs one row at a time. This shift register is rotated 13 bits when we reach the end of drawing a row of blocks. Also we can write to the shift register the new block state if a block has been broken. This is done one clock cycle before shifting to the next row. 1 clock cycle after shifting to the next row we load the current row into a buffer which will be used to update the state.

How to test

This is a small breakout game implemented in HDL. It uses a VGA connector to output the video signal. The game is controlled by 3 buttons. The left button moves the paddle to the left, the right button moves the paddle to the right and the action button starts the game. The game is over when all blocks are destroyed or when the ball hits the bottom of the screen.

Required hardware

This project requires a VGA monitor and a VGA DAC. An easy way to create the VGA DAC is to use 3 2-bit R2R DACs. The 2-bit R2R DACs can be created using 2 resistors per bit. The resistors should be 200Ohm and 390Ohm. For the 3.3V power supply.

What has not been verified is the current sourcing capability of the ASIC, If it can not at least source 10mA through each pin and 30mA through the power supply pins you should add a buffer before the DAC.

The VGA DAC should be connected as follows:

           ___       ___
Bit 0 ----|___|--+--|___|-- GND
           390   |   390
                .-.
                | |
            200 | |
                '-'
          ____   |  
Bit 1 ---|____|--+---- Out
          390

Every color should have an identical copy of this DAC. The red DAC should be connected to the red VGA pin, the green DAC to the green VGA pin and the blue DAC to the blue VGA pin. The outputs of the DACs should be connected to the VGA connector. The HSync and VSync pins should also be connected to the VGA connector. The following connections need to be made to the VGA connector:

  • Red DAC output to VGA connector pin 1
  • Green DAC output to VGA connector pin 2
  • Blue DAC output to VGA connector pin 3
  • HSync to VGA connector pin 13
  • VSync to VGA connector pin 14
  • GND to VGA connector pin 5, 6, 7, 8

SPI interface

For changing the game state externally you can use the SPI interface. The SPI interface returns the current game state when reading and accepts a few commands when writing. The SPI interface uses 16 bit words.

The returned state is as follows:

  • bit 0-12: The block state of the current row. Use HBlank and VBlank to determine which row is currently being drawn.
  • bit 13: right button state
  • bit 14: left button state
  • bit 15: action button state
  • bit 16: collision state. This bit is set when a collision has been detected.
  • bit 17: ball out of bounds. This bit is set when the ball is off screen.
  • bit 18: game state: 0 = game idle, 1 = game running
  • bit 19-20: remaining lives

When writing the first word is the command word, the following words are the data words for the command. Command words:

  • 0x0000: Do nothing. Usefull when you want to read the state.
  • 0x0001: Write a row state. This will shift the state to the next row. Be sure to only use this during the VBlank and call this with 15 words to completely draw the screen.
  • 0x0002: Send control word. The next word is the control word. The control word is as follows:
    • bit[0]: Send the stop game command.

Board configuration

The ASIC requires an input clock of 25.175MHz. The 7-Segment display is not used.

External hardware

3x 2bit DAC for the red, green and blue video signals. VGA connector. 3 buttons.

Picture

IO

#InputOutputBidirectional
0MOSIHSyncMISO
1SCKVSyncHBlank
2slave selectRed output bit 0VBlank
3Red output bit 1sound output. Connect to a speaker with amplifier.
4Green output bit 0
5Button leftGreen output bit 1
6Button rightBlue output bit 0
7Button actionBlue output bit 1

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (TinyTapeout 04 Factory Test) tt_um_vga_clock (VGA clock) tt_um_seven_segment_seconds (7 segment seconds) tt_um_marno_factorize (Number Factorizer) tt_um_sorter (Odd even sorter) tt_um_bulls_and_cows (The Bulls and Cows game) tt_um_loopback (TinyTapeout 04 Loopback Test Module) tt_um_devinatkin_arduino_vga (VGA Output for Arduino) tt_um_wokwi_371604537887211521 (Digital Cipher & Interlock System) tt_um_urish_simon (Simon Says game) tt_um_wokwi_372184284115580929 (YKM 7-seg driver) tt_um_currymottled (Configurable PID Block) tt_um_yeokm1_pwm_audio (PWM audio) tt_um_dcb277_ALU (4-bit ALU) tt_um_rgb_mixer (RGB Mixer) tt_um_loopback (TinyTapeout 04 Loopback Test Module) tt_um_algofoogle_raybox_zero (raybox-zero) tt_um_morningjava_top (ChipTune) tt_um_loopback (TinyTapeout 04 Loopback Test Module) tt_um_eldritch_pwm_peripheral (OpenSource PWM Peripheral) tt_um_phansel_laplace_lut (Experiment Number Six: Laplace LUT) tt_um_ks_pyamnihc (Karplus-Strong String Synthesis) tt_um_dlmiles_tt04_poc_usbdev (USB Device) tt_um_thorkn_pwmaudio (Audio-PWM-Synth) tt_um_wokwi_374029622762967041 (German Traffic Light) tt_um_dandy_dance (Dandy VGA) tt_um_robojan_top (Tiny Breakout) tt_um_vc_cpu (VC 16-bit CPU) tt_um_MichaelBell_nanoV (Risc-V Nano V) tt_um_urish_usb_cdc (USB CDC (Serial)) tt_um_tiny_processor (Tiny processor) tt_um_f_hal_fft (fft-4-tt) tt_um_tomkeddie_a (LED Panel Driver) tt_um_wokwi_370722051572189185 (OSU Counter) tt_um_wokwi_370796071922577409 (Even digits) tt_um_wokwi_370709383347782657 (Traffic light) tt_um_wokwi_371425977920989185 (Tutorial4) tt_um_riceshelley_tinyFPGA (Grain-Flex-FPGA) tt_um_mgyenik_bfcpu (BFCPU) tt_um_machinaut_systolic (AI Decelerator) tt_um_wokwi_374140166551523329 (Tiny (3-bit) LFSR) tt_um_jk2102 (Pulsed Plasma Thruster (PPT) Controller) tt_um_jayraj4021_SAP1_cpu (SAP-1 CPU) tt_um_wokwi_370533670565165057 (Impulse counter) tt_um_ashleyjr_delay_line (Delay Line) tt_um_simplepiano (Simple Piano) tt_um_wokwi_374292646686728193 (Ripple-Carry Adder) tt_um_led_multiplexer_display (Led Multiplexer Display) tt_um_mjbella_led_matrix_driver (LED Matrix Driver) tt_um_fifo_stevej (8-bit FIFO with depth 16.) tt_um_robojan_pong_top (Pong) tt_um_wokwi_374962052813090817 (8 panel display"") tt_um_wokwi_370690644715216897 (Traffic Light) tt_um_wokwi_374494377414857729 (Model Railway turntable polarity controller) tt_um_wokwi_347144898258928211 (Customizable UART string tx) tt_um_wokwi_347497504164545108 (7-Seg 'Tiny Tapeout' Display) tt_um_wokwi_347140425276981843 (UART character tx) tt_um_wokwi_347417602591556180 (Padlock) tt_um_noritsuna_8bitcounter_AI (8bits Counter by AI) tt_um_fm_transmitter (FM Transmitter) tt_um_wokwi_369864099838656513 (Test 4x4 memory) tt_um_htfab_rotfpga2 (ROTFPGA v2) tt_um_losaias (Arithmetic logic unit of four operations between two 8-bit numbers) tt_um_fir_top (FIR Filter) tt_um_santacrc_tamagotchi (Tamagotchi) tt_um_4_LUT_Baungarten (LFMPDM (Lightning Fast Matrix Programmable Design Module)) tt_um_RELOG_10M_Juan_Garcial (7 SEGMENTS CLOCK) tt_um_MultiPatternLEDSequencer_RSYO3000 (Multi Pattern LED Sequencer) tt_um_pwm (Generador de PWM) tt_um_chip_SP_measure_delay (Multi stage path for delay measurements.) tt_um_chip_SP_Soy_de_Zacapa (ASCII Text Printer Circuit) tt_um_fing_synchronizer_hga (Clock synchronizer) tt_um_db_PWM (Simple PWM Generator) tt_um_RS_Vfreq (CLK Frequency Divider) tt_um_ja_TrafficLight (UIS Traffic Light) tt_um_adder_NestorMatajira (4 bit adder ) tt_um_ALU_NicolasOrcasitas (8-bit ALU) tt_um_ccollatz_SergioOliveros (Collatz Conjecture) tt_um_wokwi_370011087462055937 (8 bit 4 data sorting network) tt_um_wokwi_374968111036708865 (BCD to 7 segments) tt_um_wokwi_374967675785369601 (4 bit full adder) tt_um_wokwi_374974793636964353 (Circuito Religioso) tt_um_wokwi_374815911155542017 (Demultiplexor NAND) tt_um_wokwi_374903567624066049 (Sumador/Sustractor de 3 bit con acarreo y prestamo) tt_um_wokwi_374515580784897025 (Hardware Lock) tt_um_wokwi_374909346558831617 (Custom falling and rising edge detection) tt_um_alu (4-bit-alu) tt_um_pong_neopixel (Angardo's pong) tt_um_LEOGLM_hamming_code_top ((11,7) hamming code encoder and decoder with UART) tt_um_adriannovosel_top (Impulse counter) tt_um_wokwi_374969806854695937 (State machine of an impulse counter) tt_um_wokwi_375061599421794305 (Logic Circuit 1) tt_um_biased_trng (Variable Duty-Cycle TRNG) tt_um_top (Modem Multimodo) tt_um_wokwi_372347167704674305 (SAR ADC Backend) tt_um_wokwi_375176944142127105 (FCFM 7-segment display) tt_um_rodrigomunoz1_rotempsensor_top (another ring oscillator based temperature sensor) tt_um_USM_temp_sens_hyst (RO-based temperature sensor with hysteresis) tt_um_FSM (Microrobotics FSM) tt_um_wokwi_375042398768251905 (MINI ALU) tt_um_wokwi_374778387606763521 (PWM Quisquilloso) tt_um_CPU (CPU 8 bit) tt_um_simple_processor_pablopabota (A Risc-V Instruction memory i2c programmer) tt_um_wokwi_375246321309880321 (IFSC 6-bit Locker) tt_um_wokwi_375217288209912833 (Randomizer and status checker) tt_um_wokwi_375245713375900673 (Simulador de cruzamento de semáforo) tt_um_wokwi_374636462642973697 (Full_adder_carry_juang_garzons) tt_um_ternaryPC_radixconvert (4-trit balanced ternary program counter and convertor) tt_um_darkfsegura_collatz (uDATAPATH_Collatz) tt_um_wokwi_375174630101280769 (Adder) tt_um_wokwi_375163050120587265 (Binary to 7 segment) tt_um_wokwi_375165100039571457 (Neuron) tt_um_silva (Later) tt_um_shift (serializer) tt_um_alu4_alonso59 (4-bits 1-channel PWM and ALU 4 bits) tt_um_mod_u_cnt_BCD (up-down counter with parallel load and BCD output) tt_um_ciro (Later) tt_um_control (Contador con carga) tt_um_onehot (onehot_decoder) tt_um_santiago (CDMA Transmitter/Receiver) tt_um_divider_urielcho (clock divider) tt_um_pwl_RaulprTech (reciprocal) tt_um_fabian (Later) tt_um_thezoq2_tmng (Time Multiplexed Nand-gate) tt_um_uninorte (Octal classifier) tt_um_dlmiles_muldiv4 (MULDIV unit (4-bit signed/unsigned)) tt_um_rs_write_decodifier_fjrn_cinvestav (RS Write Decodifier) tt_um_BounceFSM_RSX92 (Password FSM) tt_um_priority_decoder_Juan_Garcial (Priority e) tt_um_FreqMeter_Juan_Garcial (frecuencimeter) tt_um_sahrdayalfsr (lfsr random number generator) tt_um_i2c (i2c_6 bits) tt_um_wokwi_375227079413963777 (Fastest Finger) tt_um_wokwi_375300958229329921 (Fastest Finger (Clocked)) tt_um_zeptobars (Oscillators II) tt_um_rebot449_lingret_ALU_Top (Simple ALU) tt_um_loopback (TinyTapeout 04 Loopback Test Module) tt_um_wokwi_375288605206694913 (Adjustable Frequency LED Chaser) tt_um_wokwi_375310871188385793 (Simple QSPI DAC) tt_um_quardinlyttle_top (AQALU) tt_um_wokwi_375326293008530433 (Simple TMR) tt_um_chiplet_jtag (Poor Person's Boundary Scan) tt_um_wokwi_375248885704300545 (Probador de lógica básico) tt_um_rejunity_telluride2023_neuron (LIF Neuron, Telluride 2023) tt_um_kpwebb_adder (rusty_adder) Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available