547 WokwiPWM

547 : WokwiPWM

Design render

Wokwi 4-Channel PWM

As it says, this is a 4-channel PWM coded in Wokwi. Each channel has 3 8-bit values to control their frequency, duty cycle and relative (starting) phase to each other. Values are loaded by setting 8-bit data in on ui_in[7:0] and loading to the current address which auto-increments.

Block diagram

How it works

After reset, there is an 4-bit counter that is the address where the next 8-bit input data at in[7:0] will be loaded. The 'load' signal loads the 8-bit input to the register at that current counter address and then increments the counter.

The 'skip' input will skip an address without loading it. And the 'zero' input will reset the counter back to zero.

None of the 'load', 'skip', 'zero' or 'disp' inputs are debounced, but they are riging edge detected (at least the load and skip are).

The current count (register address) is displayed on the 7-segment display via a 4-to-7 decoder. Each of 4 PWM channels use two 8-bit control registers to set frequency and duty cycle. The first (lowest address) register controls the duty cycle and the second (highest address) controls the period of that channel. Only channels with non-zero period value will operate (the counter does not count when period_val is zero). For PWM channels 2-4, there is an additional 8-bit register (address 8-10) to control the starting phase of that channel relative to channel 1. This means that if channels 2-4 are to be used, channel 1 must also be used.

Program PWM channel control registers to create independent PWMs:

Address Meaning 0x0 PWM1 duty 0x1 PWM1 period 0x2 PWM2 duty 0x3 PWM2 period 0x4 PWM3 duty 0x5 PWM3 period 0x5 PWM4 duty 0x7 PWM4 period 0x8 PWM2 phase 0x9 PWM3 phase 0xa PWM4 phase 0xb Control BIT0: BIT1: BIT2: BIT3: Write '1' to clear and synchronize all PWM channels. Self clearing.

How to test

  1. Start the clock and reset the circuit.
  2. Set the DIP switches so only switch 7 is on (8'h40)
  3. Press 'load'. The display should now show '1'.
  4. Set the DIP switches so only switch 8 is on (8'h80).
  5. Press 'load'. The display should show '2' and the first LED should start blinking at about 50% rate.
  6. Continue programming values for the other 3 PWMs by setting DIP switch value and pressing 'load' even values (duty cycle) must be less that the associated odd address value (period).
  7. When the 7-segment display shows "8", this is the phase offset value for PWM channel 2 relative to channel 1. Loading a value here will force a known phase for channel 2 WHEN THE CHANNELS ARE SYNCHRONIZED.
  8. Load additional relative phase values for PWM channels 3 and 4 at the next two addresses (9 and A).
  9. To synchronize the PWM channels, write a value of 4 to address B.

External hardware

LEDs should be connected to the PWM channel outputs. The 7-Segement display shows the current register address to be written.

IO

#InputOutputBidirectional
0D0seg_aload
1D1seg_bskip
2D2seg_czero
3D3seg_ddisp
4D4seg_epwm_0
5D5seg_fpwm_1
6D6seg_gpwm_2
7D7seg_dppwm_3

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_htfab_asicle2 (Asicle v2) tt_um_urish_simon (Simon Says memory game) tt_um_dlmiles_ringosc_5inv (Ring Oscillator (5 inverter)) tt_um_rejunity_vga_logo (VGA Tiny Logo) tt_um_rejunity_sn76489 (Classic 8-bit era Programmable Sound Generator SN76489) tt_um_wokwi_392873974467527681 (PILIPINAS_IC) tt_um_wokwi_442081253563458561 (PRISM 8 with TinySnake) tt_um_waferspace_vga_screensaver (Wafer.space Logo VGA Screensaver) tt_um_rejunity_z80 (Zilog Z80) tt_um_MichaelBell_tinyQV (TinyQV Risc-V SoC) tt_um_calonso88_spi_i2c_reg_bank (Register bank accessible through SPI and I2C) tt_um_htfab_caterpillar (Simon's Caterpillar) tt_um_gf0p2_faust_top (Silly-Faust) tt_um_htfab_cells (Cell mux) tt_um_zedtc1_top (Zedulo TestChip1) tt_um_essen (2x2 MAC Systolic array with DFT) tt_um_BLE_RX (SCµM-BLE-RX) tt_um_kianV_rv32ima_uLinux_SoC (KianV uLinux SoC) tt_um_schoeberl_wildcat (Wildcat RISC-V) tt_um_vga_clock (VGA clock) tt_um_digital_clock_example (7-Segment Digital Desk Clock) tt_um_rejunity_vga_test01 (VGA Drop (audio/visual demo)) tt_um_a1k0n_nyancat (VGA Nyan Cat) tt_um_proppy_megabytebeat (megabytebeat) tt_um_javibajocero_top (MarcoPolo) tt_um_kercrafter_leds_racer (LEDs Racer) tt_um_noritsuna_CAN_CTRL (CAN Controller for Rocket) tt_um_algofoogle_raybox_zero (raybox-zero TTGF0p2 edition) tt_um_flummer_ltc (Linear Timecode (LTC) generator) tt_um_dlmiles_bad_synchronizer (Example of Bad Synchronizer) tt_um_multi_bit_puf_wrapper (One Bit PUF) tt_um_algofoogle_vgaringosc (Ring osc on VGA) tt_um_lisa (LISA 8-Bit Microcontroller) tt_um_mmorri22_lockpick_game (Notre Dame - Lockpick Game TT Example) tt_um_simple_riscv (Simple RISC-V) tt_um_mmorri22_cse_30342 (Notre Dame - CSE 30342 - DIC - Advanced FSM Final Project Example) tt_um_zacky1972_PVTMonitorSuite (PVTMonitorSuite) tt_um_SophusAndreassen_dogbattle (Dog Battle Game) tt_um_frequency_counter (Frequency Counter SSD1306 OLED) tt_um_wokwi_445338187869298689 (WokwiPWM) tt_um_kbeckmann_flame (Flame demo) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_spi_cpu_top (Super-Simple-SPI-CPU) tt_um_urish_usb_cdc (USB CDC (Serial) Device) tt_um_htfab_vga_tester (Video mode tester) tt_um_dlmiles_ddr_throughput_test (DDR throughput and flop aperature test) tt_um_dlmiles_loopback (GF180MCU loopback tile with input skew measurement) tt_um_thezoq2_quickscope (Quickscope) tt_um_MATTHIAS_M_PAL_TOP_WRAPPER (easy PAL) tt_um_htfab_rotfpga2 (ROTFPGA v2)