357 Three Channel RGB PWM Controller

357 : Three Channel RGB PWM Controller

Design render
  • Author: Aiden Koch
  • Description: Red Green Blue compatable Pulse Width Modulator to control effective voltages at an LED to control the color output. User defiend clock divider included to increase range of application usage.
  • GitHub repository
  • Open in 3D viewer
  • Clock: 0 Hz

How it works

This project is a three-channel RGB Pulse Width Modulation (PWM) controller designed for TinyTapeout.

The design stores independent brightness values for red, green, and blue LED channels and continuously generates PWM waveforms on the outputs. The PWM duty cycle determines the effective brightness of each color channel.

The 8-bit input bus is divided into:

Bits Purpose
ui_in[7:6] Mode selection
ui_in[5:0] Value data

The mode bits determine which internal register is updated.

Mode Function
00 Set RED brightness
01 Set GREEN brightness
10 Set BLUE brightness
11 Set PWM clock divider

The PWM engine operates using:

  • a programmable clock divider
  • a 6-bit PWM counter
  • comparator-based PWM generation

Each output compares the PWM counter against its stored duty-cycle register:

PWM output HIGH when:
counter < duty_cycle

This creates variable duty-cycle square waves suitable for LED brightness control.

Internal Architecture

                ui_in[7:0]
                     │
                     ▼
              ┌────────────┐
              │   Decoder  │
              └─────┬──────┘
                    │
      ┌─────────────┼─────────────┐
      ▼             ▼             ▼
   RED REG      GREEN REG      BLUE REG
      │             │             │
      └─────────────┼─────────────┘
                    ▼
              PWM Comparators
                    │
                    ▼
                RGB Outputs

PWM Generation

A programmable clock divider slows the incoming TinyTapeout clock to generate a visible PWM frequency.

A 6-bit counter continuously ramps:

0 → 1 → 2 → ... → 63 → repeat

The RGB outputs turn on whenever the counter value is below the stored duty-cycle value.

Example:

Duty = 32

counter < 32 → HIGH
counter ≥ 32 → LOW

This creates a 50% duty cycle.


How to test

The design is tested using cocotb and Icarus Verilog simulation.

Simulation Inputs

The user controls the design through the ui_in[7:0] bus.

Example Commands

Set RED brightness to maximum
mode  = 00
value = 63

ui_in = 00111111
Set GREEN brightness to medium brightness
mode  = 01
value = 32

ui_in = 01100000
Set BLUE brightness to low brightness
mode  = 10
value = 8

ui_in = 10001000
Change PWM speed
mode  = 11
value = 4

ui_in = 11000100

Running Simulation

Simulation is performed using:

cd test
make

Waveforms can then be viewed using GTKWave or Surfer.

Verification Goals

The testbench verifies:

  • register updates
  • PWM activity
  • RGB output generation
  • clock divider operation
  • reset behavior

External hardware

The outputs are intended to drive:

  • RGB LEDs
  • transistor driver stages
  • logic-level PWM-compatible devices

For direct LED use:

  • connect current-limiting resistors in series with each LED channel
  • connect PWM outputs to the LED control pins
  • ensure current limits are respected

Typical usage:

uo_out[0] → Red LED
uo_out[1] → Green LED
uo_out[2] → Blue LED

The design may also interface with:

  • MOSFET drivers
  • LED strips
  • external power stages
  • digital lighting systems

IO

#InputOutputBidirectional
0value bit 0PWM Red
1value bit 1PWM Green
2value bit 2PWM Blue
3value bit 3
4value bit 4
5value bit 5
6mode bit 0
7mode bit 1

Chip location

Controller 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 (Tiny Tapeout Factory Test) tt_um_Vincent2405_adder_tree (BSD Convolution Adder Tree) tt_um_BastiBudde_i2c_slave_sensor (I2C Slave Template with Emulated Sensor) tt_um_60hz_load (60 Hz Grid-Forming ASIC with Dump-Load Control) tt_um_spi_config_reg (Simple SPI configuration for analog designs) tt_um_ex_drosen766 (Project) tt_um_spi_cpu_top (SPI-CPU) tt_um_d5smith_mfa (Music for ASICs) tt_um_i2c_master (I2C Master Controller) tt_um_aswarby_mac (Aswarby INT8 MAC) tt_um_arrakeen_spsram_direct (TT-Arrakeen-SPSRAM-direct) tt_um_alu (8-bit Interactive ALU) tt_um_JCT_PoC (ttgf jct PoC) tt_um_jct_lea (LEA-128) tt_um_cwru_cpu (CWRU CPU) tt_um_teapot (100Mbps Ethernet Accelerator Wrapper) tt_um_jte_cordic (CORDIC sin/cos generator) tt_um_aidenkoch4 (Three Channel RGB PWM Controller) tt_um_pschuetz_tremolo (Tremolo guitar pedal ASIC) tt_um_jsabree11_fibonacci_checker (fibbonaci_tt) tt_um_connerdaehler_boop (Procedural ASIC) tt_um_Kieckenwama_Traffic_LIGHT_FSM (Traffic Light FSM) tt_um_KimLuu02_WashingMachine_FSM (WashingMachine_FSM) tt_um_PaulineKreis_PWM_Analyser (PWM-Analyser) tt_um_PWM (PWM Generator) tt_um_wokwi_466666882406199297 (Simple Sprinkler) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_spi_master (SPI Master Slave Communication) tt_um_likitha_trng (Secure TRNG Entropy Generator) tt_um_wnn (8-bit WNN Pattern Recognizer) tt_um_raksha (Raksha) tt_um_uart_soc (UART_SOC) tt_um_ecdsa_verify (ECDSA Verification) tt_um_ecc_processor (ECC Processor) tt_um_fast_auth (Fast Authentication Accelerator) tt_um_karthik_trng (TRNG using Ring Oscillator) tt_um_push (Secure V2X Mini Demonstrator) tt_um_santosh_aes_sbox (AES S-Box Accelerator) tt_um_hardware_anomaly_detection (Hardware Anomaly Detection) tt_um_multi_protocol (Multi-Protocol Communication Controller) tt_um_pqc_ntt_butterfly (PQC NTT Butterfly Core) tt_um_cambridge_nlfsr (Programmable Chaotic NLFSR) tt_um_4b_accumulator_cpu (4 bit Accumulator CPU) tt_um_spi_slave (SPI Slave with 8-Register File) tt_um_geeta_doddamani_lfsr (4-bit Maximum-Length LFSR) tt_um_ecc_accelerator (ECC Scalar Accelerator) tt_um_egurapha_chacha20 (ChaCha20) tt_um_configurable_pwm (Configurable PWM Generator) tt_um_Arctic0 (Arctic0 16-bit CPU) tt_um_comp8 (8-bit Comparator) tt_um_pwm_cit (Configurable 8-bit PWM Generator) tt_um_rameshwar_door_lock (Digital Door Lock) tt_um_sandy_venky (8-bit LFSR Circuit) tt_um_ljhahne_pong (Pong) tt_um_v2x_warning (V2X Collision Warning) tt_um_ecc_scalar_mult (ECC Scalar Multiplication) tt_um_fhw_appel_spiPWMio (spiPWMio) tt_um_arrakeen_spsram_direct_sramrules (TT-Arrakeen-SPSRAM-direct-sramrules) tt_um_arrakeen_spsram_direct_5v (TT-Arrakeen-SPSRAM-direct-5V) tt_um_LukeSilva_cartrip (Car Trip) tt_um_coffeepot (100Mpbs 3 port Ethernet switch) tt_um_emiliopeju_lightscan (Lightscan) tt_um_Alanduan21_triad01_top (triad01) tt_um_lif_snn (4-Neuron LIF Spiking Neural Network) tt_um_smerity_mandelbrot (Smerity-Mandelbrot) tt_um_elvtide01_7SegmentDice (7SegmentDice) tt_um_elemental_harmony (Elemental Harmony Game) tt_um_pattern_gen (Programmable Waveform and PWM Generator) tt_um_antimatter15_pdm_vad (PDM Voice Activity Detector) tt_um_layla_spike_detector (Neural Spike Detector) tt_um_detronyx_arith_lab (Detronyx Arithmetic Lab Tile) tt_um_hasheddan_nni (Nearest Neighbor Interpolation) tt_um_brisq (BRISQ) tt_um_santhosh_spike_codec_gf (Neuromorphic Spike Codec (GF180)) tt_um_santhosh_aer_router_gf (Asynchronous-AER Spike Router (4-phase REQ/ACK, 16-entry routing table, GF180)) tt_um_santhosh_snn_wta_gf (Spiking Neural Network WTA Inference Engine (GF180)) tt_um_santhosh_cim_bist_gf (CIM Controller with BIST and Fault Map (GF180)) tt_um_santhosh_neuro_puf_gf (Neuromorphic PUF (distinct-tap LFSR arbiter + memristor XOR, GF180)) tt_um_detronyx_uart_trace_exerciser (Detronyx UART Trace Exerciser) tt_um_ro_puf (Tiny RIng Oscillator PUF) tt_um_franretfie_top (Quadrature sine generator) tt_um_cherny_xor_8bi (XORing given bits) tt_um_mealycpp_ascon_sdmc_uart (ASCON Integrated Crypto Processor) tt_um_reflex_s4 (AER Reflex Chip - MCP2515 CAN gateway) tt_um_polytrig_core (PolyTrig Digital Waveform Synthesis Core) tt_um_waferspace_vga_screensaver (Wafer.space Logo VGA Screensaver) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_urish_simon (Simon Says memory game) Available