Pulse Width Modulation IP

A PWM IP core written in Verilog, along with firmware (designed for the Xilinx Zynq-7000 SoC)

Source Code Link: https://github.com/andrade824/Pulse-Width-Modulation-IP

This IP Core contains both the HDL and firmware driver needed to realize a pulse width modulation module that's controllable from software. This IP uses the AXI bus to interface between the hardware and software components

HDL

In the HDL folder you'll find three files:

  • pwm_gen.v - The actual logic needed to create a PWM generator
  • PWM_Generator_v1_0_S_AXI.v - The auto-generated AXI wrapper for the PWM generator (at line 106 you can see the four registers used to control the PWM generator). At the bottom of that file you'll find where I hook up the registers to the PWM generator. This is needed because the Zynq-7000 chip lets the Processing system interact with the Programmable Logic system through an AXI interface. So, the AXI registers created in this file are mapped into the processor system's memory map for manipulation in software.
  • PWM_Generator_v1_0.v - The top level module instantiating and wiring up the PWM_Generator_v1_0_S_AXI (which in turn instantiates pwm_gen).

There are three registers that control the operation of the PWM module:

  • load - The value at which the counter will reset to zero and set the output
  • compare - The value at which the counter will clear the output
  • control - Bit 0: PWM Enable - Output is enabled if this bit is high, disabled otherwise

The PWM module will continuously count up to the "load" value and once it reaches the load value, will loop back to zero. When the counter is at zero, the output is set high. When the PWM module reaches the "compare" value, it clears the output. So the "high" width of the output signal is exactly "compare" clock ticks long (the clock is whatever clock you connect to the IP in your block design, but it will most likely be generated by the Zynq Processing System). The "low" width of the output signal is exactly "load" - "compare" clock ticks long. If you disable the PWM module (by setting bit zero of the control register to zero) then the output will always be low.

In other words, the "load" register determines your period, while the "compare" register determines your duty cycle.

Driver

The "PWM_Generator.h" header file contains helpful macros for manipulating the PWM registers while "main.c" gives an example of using those macros. This code would be used in a Xilinx SDK project created for a Zynq design that utilizes the PWM IP.