{"id":3293,"date":"2021-06-10T11:35:41","date_gmt":"2021-06-10T11:35:41","guid":{"rendered":"https:\/\/imperix.com\/doc\/?p=3293"},"modified":"2025-05-07T12:55:51","modified_gmt":"2025-05-07T12:55:51","slug":"fpga-pwm-modulator","status":"publish","type":"post","link":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator","title":{"rendered":"Custom PWM modulator implementation in FPGA"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 ez-toc-wrap-right-text counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Design-choices-for-the-FPGA-based-PWM-modulator\" >Design choices for the FPGA-based PWM modulator<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#How-to-implement-pulse-width-modulation-in-FPGA\" >How to implement pulse-width modulation in FPGA?<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#1-FPGA-PWM-using-Xilinx-System-Generator\" >1) FPGA PWM using Xilinx System Generator<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#2-FPGA-PWM-using-HDL-Coder\" >2) FPGA PWM using HDL Coder<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#3-FPGA-PWM-using-VHDL\" >3) FPGA PWM using VHDL<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Testing-the-FPGA-based-PWM-module-in-simulation\" >Testing the FPGA-based PWM module in simulation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Integrating-the-PWM-modulator-into-the-Xilinx-FPGA\" >Integrating the PWM modulator into the Xilinx FPGA<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Description-of-the-FPGA-based-PWM-modulator-example\" >Description of the FPGA-based PWM modulator example<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#CPU-side-implementation\" >CPU-side implementation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#FPGA-side-implementation-using-Vivado\" >FPGA-side implementation using Vivado<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Experimental-validation\" >Experimental validation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\/#Going-further\" >Going further<\/a><\/li><\/ul><\/nav><\/div>\n\n<p>To implement power converter control algorithms in an FPGA, it is often required to develop an FPGA-based pulse-width modulation (PWM) module. Therefore, this note presents how to implement a <strong>custom PWM modulator<\/strong> in the Xilinx <strong>FPGA <\/strong>of the imperix controller (<a href=\"https:\/\/imperix.com\/products\/control\/rapid-prototyping-controller\/\">B-Box RCP<\/a> or <a href=\"https:\/\/imperix.com\/products\/control\/inverter-control-board\/\">B-Board PRO<\/a>). <\/p>\n\n\n\n<p>The presented modulator uses FPGA pulse-width modulation with a triangular carrier. The sources of this example can be re-used in an FPGA-based power converter control design. Alternatively, it can be used as a starting point to develop more complex custom PWM modulators.<\/p>\n\n\n\n<p>The first section of this page explains how the PWM module fits into an FPGA-based control design as well as the FPGA design of the pulse-width modulation. Next, the actual implementation of the FPGA modulator is presented using 3 different tools:<\/p>\n\n\n\n<ol class=\"wp-block-list\" id=\"block-8057071f-9481-4198-82b4-816b1700a7e3\"><li>the Xilinx blockset for Simulink <a href=\"https:\/\/imperix.com\/doc\/help\/xilinx-system-generator\">System Generator<\/a><\/li><li>the Simulink add-on <a href=\"https:\/\/imperix.com\/doc\/help\/matlab-hdl-coder\">MATLAB HDL Coder<\/a><\/li><li>hand-written VHDL coding<\/li><\/ol>\n\n\n\n<p>Then, a Simulink testbench is built to test the FPGA design in simulation. Finally, the modulator is integrated into the imperix controller FPGA to be validated.<\/p>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-info\" role=\"alert\">This page addresses advanced content for users who require implementing converter control algorithms with FPGA logic or implementing non-standard modulation techniques. <br>For most use-cases, using CPU-based control and the pre-implemented <a href=\"https:\/\/imperix.com\/doc\/software\/carrier-based-pwm\">carrier-based PWM modulators<\/a> of the imperix library is widely sufficient and should be preferred.<\/div>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-dark\" role=\"alert\">To find all FPGA-related notes, you can visit\u00a0<a href=\"https:\/\/imperix.com\/doc\/help\/fpga-development-on-imperix-controllers\">FPGA development homepage<\/a>.<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-design-choices-for-the-fpga-based-pwm-modulator\"><span class=\"ez-toc-section\" id=\"Design-choices-for-the-FPGA-based-PWM-modulator\"><\/span>Design choices for the FPGA-based PWM modulator<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The Pulse Width Modulator (PWM) is intended to be used in a larger design such as the FPGA-based buck converter control example shown in the image below. The <strong>imperix firmware IP<\/strong> and <strong>ix axis interface<\/strong> are explained in the <a href=\"https:\/\/imperix.com\/doc\/help\/getting-started-with-fpga-control-development\">getting started with FPGA control<\/a> page and the <strong>current control<\/strong> module is presented in the <a href=\"https:\/\/imperix.com\/doc\/implementation\/high-level-synthesis-for-fpga\">high level synthesis for FPGA<\/a> tutorial.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"499\" height=\"346\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/Block_diagram_FPGA_CPU_overall.png\" alt=\"Power converter control FPGA\" class=\"wp-image-10456\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/Block_diagram_FPGA_CPU_overall.png 499w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/Block_diagram_FPGA_CPU_overall-300x208.png 300w\" sizes=\"auto, (max-width: 499px) 100vw, 499px\" \/><figcaption>Power converter control in an imperix controller<\/figcaption><\/figure><\/div>\n\n\n\n<p>The FPGA-based PWM modulator must be connected to one of the 4 clock generators (<a href=\"https:\/\/imperix.com\/doc\/software\/clock-generators\">CLK<\/a>). In this example, the CLK allows synchronizing the CPU control task with the PWM carrier. For further details on the CLK FPGA signals, please refer to the &#8220;CLOCK interface&#8221; section of <a href=\"https:\/\/imperix.com\/doc\/help\/imperix-ip-user-guide\">imperix firmware IP<\/a> user guide.<\/p>\n\n\n\n<p>The Sandbox PWM (<a href=\"https:\/\/imperix.com\/doc\/software\/sandbox-pwm\">SB-PWM<\/a>) block makes it possible to drive the same PWM output chain as that used by other modulators (CB-PWM, PP-PWM, DO-PWM, and SS-PWM). This allows the user to generate complementary signals with dead-time, use the standard activate and deactivate functions and rely on the protection mechanism that blocks PWM outputs when a fault is detected.<\/p>\n\n\n\n<p>The figure below shows how the FPGA modulator operates. The pulse-width modulation is obtained by comparing a duty cycle value with the triangular carrier wave.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/04\/image-212-1024x557.png\" alt=\"Carrier and modulation waveforms for the PWM module.\" width=\"581\" height=\"316\"\/><figcaption>PWM modulator based on a triangular carrier<\/figcaption><\/figure><\/div>\n\n\n\n<p>The duty cycle can be updated using a <strong>single rate<\/strong> or <strong>double rate<\/strong>. When using the&nbsp;single-rate&nbsp;update, the duty cycle value is applied when the triangular carrier reaches its minimum. With the&nbsp;double-rate&nbsp;update, the duty cycle is updated twice per period: when the carrier reaches its maximum and when it reaches its minimum.<\/p>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-info\" role=\"alert\">In summary, this FPGA PWM modulator behaves as a carrier-based PWM (<a href=\"https:\/\/imperix.com\/doc\/software\/carrier-based-pwm\">CB-PWM<\/a>) modulator that is configured with a triangular carrier, and a phase of 0.<\/div>\n\n\n\n<p>The FPGA-based PWM module is shown below. The screenshot shows the IP generated with <a href=\"https:\/\/imperix.com\/doc\/help\/xilinx-system-generator\">System Generator<\/a>, but the input and output ports are identical when using MATLAB <a href=\"https:\/\/imperix.com\/doc\/help\/matlab-hdl-coder\">HDL Coder<\/a> or VHDL. The ports are the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>CLOCK<\/code>: the clock interface that is meant to be connected to the <em>CLOCK<\/em> output of <a href=\"https:\/\/imperix.com\/doc\/help\/imperix-ip-user-guide\"><em>imperix firmware<\/em> IP<\/a>. It contains:<ul><li><code>CLOCK_prescaler<\/code>, the CLK_timer ticking rate, <strong>1 tick = (4 ns\/CLK_prescaler)<\/strong><\/li><li><code>CLOCK_clk_en<\/code>, asserted to indicate a new tick.<\/li><li><code>CLOCK_period<\/code>, the PWM period in ticks<\/li><li><code>CLOCK_timer<\/code>, a counter that goes from 0 to CLK_period-1<\/li><\/ul><\/li><li><code>next_dutycycle<\/code>: the next <em>duty cycle<\/em> to be updated. This signal is a 16-bit unsigned integer with a unit of ticks.<\/li><li><code>update_rate<\/code>: controls the update rate. &#8216;0&#8217; is single-rate and &#8216;1&#8217; is double-rate.<\/li><li><code>pwm<\/code><span style=\"color: var(--global-palette4);\">: the pulse-width modulation output signal<\/span><\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1.png\" alt=\"PWM modulator intended for FPGA implementation using Xilinx System Generator\" class=\"wp-image-3790\" width=\"268\" height=\"175\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1.png 426w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1-300x196.png 300w\" sizes=\"auto, (max-width: 268px) 100vw, 268px\" \/><figcaption>FPGA-based PWM module developed using Xilinx System Generator<\/figcaption><\/figure><\/div>\n\n\n\n<p>Below is shown the high-level schematic of the FPGA-implemented PWM modulator. The <em>duty cycle<\/em> is stored in a register, whose enable port is controlled by the <em>update rate<\/em>. The triangular carrier is generated from the <em>CLOCK <\/em>input using an up\/down counter that behaves as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>it resets each time CLOCK_timer is equal to zero<\/li><li>after a reset, it counts UP until CLOCK_timer reaches CLOCK_period\/2<\/li><li>then, it counts down until it reaches zero.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"607\" height=\"164\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/High-level_schematic_modulator-3.png\" alt=\"High-level schematic of the FPGA PWM block\" class=\"wp-image-3877\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/High-level_schematic_modulator-3.png 607w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/High-level_schematic_modulator-3-300x81.png 300w\" sizes=\"auto, (max-width: 607px) 100vw, 607px\" \/><figcaption>High-level schematic of the PWM block<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-how-to-implement-pulse-width-modulation-in-fpga\"><span class=\"ez-toc-section\" id=\"How-to-implement-pulse-width-modulation-in-FPGA\"><\/span>How to implement pulse-width modulation in FPGA?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This section provides 3 possible approaches for implementing the FPGA PWM modulator, using Xilinx System Generator, MATLAB Simulink HDL Coder, or hand-written VHDL.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-1-fpga-pwm-using-xilinx-system-generator\"><span class=\"ez-toc-section\" id=\"1-FPGA-PWM-using-Xilinx-System-Generator\"><\/span>1) FPGA PWM using Xilinx System Generator<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The implementation of the FPGA PWM modulator using <strong>Xilinx System Generator<\/strong> is given below. The sources are available on the <a href=\"https:\/\/imperix.com\/doc\/help\/xilinx-system-generator\">System Generator introduction<\/a> page.<\/p>\n\n\n\n<p>Please note the following important points:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The input and output ports are represented with <em>Gateway in<\/em> and <em>Gateway out<\/em> blocks. The sample time is set to <strong>4ns<\/strong> to ensure that the model represents the real behavior of the FPGA.<\/li><li>All the input signals are registered to improve performance.<\/li><li>In System Generator, users can configure the latency for each block. If there is a timing violation in the generated IP, try to increase the latency or insert registers between operations.<\/li><li>The carrier is generated using a free-running counter and a state machine that controls the counter. System Generator provides <em>MCode<\/em> block where users can convert MATLAB code to VHDL. The MATLAB code for the state machine is given below.<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"403\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm-1024x403.png\" alt=\"Custom-designed PWM module for implementation on FPGA.\" class=\"wp-image-3642\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm-1024x403.png 1024w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm-300x118.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm-768x302.png 768w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm-1536x605.png 1536w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_pwm.png 1682w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>FPGA-based modulator designed using Xilinx System Generator<\/figcaption><\/figure>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Matlab\" data-shcb-language-slug=\"matlab\"><span><code class=\"hljs language-matlab\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">&#91;up,rst]<\/span> = <span class=\"hljs-title\">state_machine<\/span><span class=\"hljs-params\">(reg_HalfPeriodMinusOne, reg_Timer)<\/span><\/span>\n<span class=\"hljs-keyword\">persistent<\/span> state, state = xl_state(<span class=\"hljs-number\">0<\/span>,{xlUnsigned, <span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">0<\/span>});\n\n<span class=\"hljs-comment\">% default value<\/span>\nup = <span class=\"hljs-number\">1<\/span>;\nrst = <span class=\"hljs-number\">0<\/span>;\n\n<span class=\"hljs-keyword\">switch<\/span> state\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-comment\">% counting up<\/span>\n    up = <span class=\"hljs-number\">1<\/span>;\n    rst = <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> reg_Timer &gt; reg_HalfPeriodMinusOne\n      state = <span class=\"hljs-number\">1<\/span>;\n    <span class=\"hljs-keyword\">end<\/span>\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">1<\/span> <span class=\"hljs-comment\">% counting down<\/span>\n    up = <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> reg_Timer == <span class=\"hljs-number\">0<\/span>\n      state = <span class=\"hljs-number\">0<\/span>;\n      rst = <span class=\"hljs-number\">1<\/span>;\n    <span class=\"hljs-keyword\">else<\/span>\n      rst = <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-keyword\">end<\/span>\n<span class=\"hljs-keyword\">end<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Matlab<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">matlab<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id=\"h-2-fpga-pwm-using-hdl-coder\"><span class=\"ez-toc-section\" id=\"2-FPGA-PWM-using-HDL-Coder\"><\/span>2) FPGA PWM using HDL Coder<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The implementation of the FPGA PWM modulator using <strong>HDL Coder<\/strong> is given above. The sources are available on the <a href=\"https:\/\/imperix.com\/doc\/help\/matlab-hdl-coder\">MATLAB HDL Coder introduction<\/a> page.<\/p>\n\n\n\n<p>Please note the following important points:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The input and output ports are represented with Simulink input and output ports. The sample time is set to <strong>4ns<\/strong> to ensure the model represents the real behavior in FPGA.<\/li><li>The <em>delay<\/em> block can be used to represent the register in FPGA.<\/li><li>The carrier is generated using a free-running counter and a state machine that controls the counter. Here, the state machine is implemented using a <em>MATLAB Function <\/em>block. The MATLAB code for the state machine is given below.<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"583\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/hdlcoder_pwm-1024x583.png\" alt=\"FPGA-based PWM module designed using MATLAB HDL Coder\" class=\"wp-image-3804\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/hdlcoder_pwm-1024x583.png 1024w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/hdlcoder_pwm-300x171.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/hdlcoder_pwm-768x438.png 768w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/hdlcoder_pwm.png 1055w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>FPGA-based PWM module designed using MATLAB HDL Coder<\/figcaption><\/figure>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Matlab\" data-shcb-language-slug=\"matlab\"><span><code class=\"hljs language-matlab\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">&#91;rst, up]<\/span> = <span class=\"hljs-title\">state_machine<\/span><span class=\"hljs-params\">(reg_HalfPeriodMinusOne, reg_Timer)<\/span><\/span>\n\n<span class=\"hljs-comment\">% define states<\/span>\nstate_up = uint8(<span class=\"hljs-number\">0<\/span>);\nstate_down = uint8(<span class=\"hljs-number\">1<\/span>);\n<span class=\"hljs-keyword\">persistent<\/span> state\n<span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-built_in\">isempty<\/span>(state)\n  state = state_up;   \n<span class=\"hljs-keyword\">end<\/span>\n\n<span class=\"hljs-comment\">% default value<\/span>\nup = <span class=\"hljs-built_in\">true<\/span>;\nrst = <span class=\"hljs-built_in\">false<\/span>;\n\n<span class=\"hljs-keyword\">switch<\/span> state\n    \n  <span class=\"hljs-keyword\">case<\/span> state_up <span class=\"hljs-comment\">% counting up<\/span>\n    up = <span class=\"hljs-built_in\">true<\/span>;\n    rst = <span class=\"hljs-built_in\">false<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> reg_Timer &gt; reg_HalfPeriodMinusOne\n      state = state_down;\n    <span class=\"hljs-keyword\">end<\/span>\n    \n  <span class=\"hljs-keyword\">case<\/span> state_down <span class=\"hljs-comment\">% counting down<\/span>\n    up = <span class=\"hljs-built_in\">false<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> reg_Timer == <span class=\"hljs-number\">0<\/span>\n      state = state_up;\n      rst = <span class=\"hljs-built_in\">true<\/span>;\n    <span class=\"hljs-keyword\">else<\/span>\n      rst = <span class=\"hljs-built_in\">false<\/span>;\n    <span class=\"hljs-keyword\">end<\/span>\n<span class=\"hljs-keyword\">end<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Matlab<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">matlab<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id=\"h-3-fpga-pwm-using-vhdl\"><span class=\"ez-toc-section\" id=\"3-FPGA-PWM-using-VHDL\"><\/span>3) FPGA PWM using VHDL<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The following VHDL code implements the FPGA pulse-width modulation design but in hand-written VHDL.<\/p>\n\n\n<style>.kt-accordion-id_ee8734-1c .kt-accordion-inner-wrap{column-gap:var(--global-kb-gap-md, 2rem);row-gap:1px;}.kt-accordion-id_ee8734-1c .kt-accordion-panel-inner{border-top-width:2px;border-right-width:2px;border-bottom-width:2px;border-left-width:2px;border-top-left-radius:2px;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:2px;background:#ffffff;padding-top:20px;padding-right:20px;padding-bottom:20px;padding-left:20px;}.kt-accordion-id_ee8734-1c > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap > .kt-blocks-accordion-header{border-top-color:#f2f2f2;border-right-color:#f2f2f2;border-bottom-color:#f2f2f2;border-left-color:#f2f2f2;border-top-width:2px;border-right-width:2px;border-bottom-width:2px;border-left-width:2px;border-top-left-radius:2px;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:2px;background:#ffffff;font-size:16px;line-height:24px;letter-spacing:0px;font-weight:bold;text-transform:none;color:var(--global-palette3, #1A202C);padding-top:12px;padding-right:10px;padding-bottom:8px;padding-left:16px;}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle )  > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle )  > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap .kt-blocks-accordion-icon-trigger:before{background:var(--global-palette3, #1A202C);}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-icon-trigger{background:var(--global-palette3, #1A202C);}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-icon-trigger:before{background:#ffffff;}.kt-accordion-id_ee8734-1c > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap > .kt-blocks-accordion-header:hover, \n\t\t\t\tbody:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c .kt-blocks-accordion-header:focus-visible{color:#444444;background:#ffffff;border-top-color:#eeeeee;border-right-color:#eeeeee;border-bottom-color:#eeeeee;border-left-color:#eeeeee;}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle ) .kt-accordion-header-wrap .kt-blocks-accordion-header:hover .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle ) .kt-accordion-header-wrap .kt-blocks-accordion-header:hover .kt-blocks-accordion-icon-trigger:before, body:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle ) .kt-blocks-accordion--visible .kt-blocks-accordion-icon-trigger:after, body:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle ) .kt-blocks-accordion-header:focus-visible .kt-blocks-accordion-icon-trigger:before{background:#444444;}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:hover .kt-blocks-accordion-icon-trigger, body:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:focus-visible .kt-blocks-accordion-icon-trigger{background:#444444;}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:hover .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:hover .kt-blocks-accordion-icon-trigger:before, body:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:focus-visible .kt-blocks-accordion-icon-trigger:after, body:not(.hide-focus-outline) .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-accordion-header-wrap .kt-blocks-accordion-header:focus-visible .kt-blocks-accordion-icon-trigger:before{background:#ffffff;}.kt-accordion-id_ee8734-1c .kt-accordion-header-wrap .kt-blocks-accordion-header:focus-visible,\n\t\t\t\t.kt-accordion-id_ee8734-1c > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap > .kt-blocks-accordion-header.kt-accordion-panel-active{color:var(--global-palette3, #1A202C);background:var(--global-palette9, #ffffff);border-top-color:var(--global-palette6, #718096);border-right-color:var(--global-palette6, #718096);border-bottom-color:var(--global-palette6, #718096);border-left-color:var(--global-palette6, #718096);}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle )  > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap > .kt-blocks-accordion-header.kt-accordion-panel-active .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basiccircle ):not( .kt-accodion-icon-style-xclosecircle ):not( .kt-accodion-icon-style-arrowcircle )  > .kt-accordion-inner-wrap > .wp-block-kadence-pane > .kt-accordion-header-wrap > .kt-blocks-accordion-header.kt-accordion-panel-active .kt-blocks-accordion-icon-trigger:before{background:var(--global-palette3, #1A202C);}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-header.kt-accordion-panel-active .kt-blocks-accordion-icon-trigger{background:var(--global-palette3, #1A202C);}.kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-header.kt-accordion-panel-active .kt-blocks-accordion-icon-trigger:after, .kt-accordion-id_ee8734-1c:not( .kt-accodion-icon-style-basic ):not( .kt-accodion-icon-style-xclose ):not( .kt-accodion-icon-style-arrow ) .kt-blocks-accordion-header.kt-accordion-panel-active .kt-blocks-accordion-icon-trigger:before{background:var(--global-palette9, #ffffff);}@media all and (max-width: 767px){.kt-accordion-id_ee8734-1c .kt-accordion-inner-wrap{display:block;}.kt-accordion-id_ee8734-1c .kt-accordion-inner-wrap .kt-accordion-pane:not(:first-child){margin-top:1px;}}<\/style>\n<div class=\"wp-block-kadence-accordion alignnone\"><div class=\"kt-accordion-wrap kt-accordion-wrap kt-accordion-id_ee8734-1c kt-accordion-has-3-panes kt-active-pane-0 kt-accordion-block kt-pane-header-alignment-left kt-accodion-icon-style-arrow kt-accodion-icon-side-left\" style=\"max-width:none\"><div class=\"kt-accordion-inner-wrap\" data-allow-multiple-open=\"false\" data-start-open=\"none\">\n<div class=\"wp-block-kadence-pane kt-accordion-pane kt-accordion-pane-1 kt-pane_34829c-1e\"><div class=\"kt-accordion-header-wrap\"><button class=\"kt-blocks-accordion-header kt-acccordion-button-label-show\"><span class=\"kt-blocks-accordion-title-wrap\"><span class=\"kt-blocks-accordion-title\"><strong>VHDL implementation of the carrier-based PWM<\/strong> modulator<\/span><\/span><span class=\"kt-blocks-accordion-icon-trigger\"><\/span><\/button><\/div><div class=\"kt-accordion-panel kt-accordion-panel-hidden\"><div class=\"kt-accordion-panel-inner\"><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"VHDL\" data-shcb-language-slug=\"vhdl\"><span><code class=\"hljs language-vhdl\"><span class=\"hljs-comment\">----------------------------------------------------------------------------------<\/span>\n<span class=\"hljs-comment\">-- Create Date: 10\/02\/2021<\/span>\n<span class=\"hljs-comment\">----------------------------------------------------------------------------------<\/span>\n<span class=\"hljs-keyword\">library<\/span> IEEE;\n<span class=\"hljs-keyword\">use<\/span> IEEE.STD_LOGIC_1164.<span class=\"hljs-keyword\">ALL<\/span>;\n<span class=\"hljs-keyword\">use<\/span> IEEE.NUMERIC_STD.<span class=\"hljs-keyword\">ALL<\/span>;\n\n<span class=\"hljs-keyword\">entity<\/span> UserCbPwm <span class=\"hljs-keyword\">is<\/span>\n\n  <span class=\"hljs-keyword\">Port<\/span> (\n    CLOCK_period : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic_vector<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n    CLOCK_timer : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic_vector<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n    CLOCK_prescaler : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic_vector<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n    CLOCK_clk_en : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic<\/span>;\n\n    <span class=\"hljs-comment\">-- must be between 0 and CLOCK_period<\/span>\n    <span class=\"hljs-comment\">-- loaded when the carrier reaches zero<\/span>\n    i_nextDutyCycle : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic_vector<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n    i_enableDoubleRate : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic<\/span>;\n\n    o_carrier : <span class=\"hljs-keyword\">out<\/span> <span class=\"hljs-built_in\">std_logic_vector<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n    o_pwm : <span class=\"hljs-keyword\">out<\/span> <span class=\"hljs-built_in\">std_logic<\/span>;\n\n    clk_250_mhz : <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-built_in\">std_logic<\/span>\n  );\n<span class=\"hljs-keyword\">end<\/span> UserCbPwm;\n\n<span class=\"hljs-keyword\">architecture<\/span> impl <span class=\"hljs-keyword\">of<\/span> UserCbPwm <span class=\"hljs-keyword\">is<\/span>\n\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO : <span class=\"hljs-built_in\">STRING<\/span>;\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO <span class=\"hljs-keyword\">of<\/span> clk_250_mhz: <span class=\"hljs-keyword\">SIGNAL<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"xilinx.com:signal:clock:1.0 clk_250_mhz CLK\"<\/span>;\n\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO <span class=\"hljs-keyword\">of<\/span> CLOCK_period:    <span class=\"hljs-keyword\">SIGNAL<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"imperix.ch:ix:clock_gen_rtl:1.0 CLOCK period\"<\/span>;\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO <span class=\"hljs-keyword\">of<\/span> CLOCK_timer:     <span class=\"hljs-keyword\">SIGNAL<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"imperix.ch:ix:clock_gen_rtl:1.0 CLOCK timer\"<\/span>;\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO <span class=\"hljs-keyword\">of<\/span> CLOCK_prescaler: <span class=\"hljs-keyword\">SIGNAL<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"imperix.ch:ix:clock_gen_rtl:1.0 CLOCK prescaler\"<\/span>;\n  <span class=\"hljs-keyword\">ATTRIBUTE<\/span> X_INTERFACE_INFO <span class=\"hljs-keyword\">of<\/span> CLOCK_clk_en:    <span class=\"hljs-keyword\">SIGNAL<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"imperix.ch:ix:clock_gen_rtl:1.0 CLOCK clk_en\"<\/span>;\n\n  <span class=\"hljs-keyword\">attribute<\/span> X_INTERFACE_MODE : <span class=\"hljs-built_in\">string<\/span>;\n  <span class=\"hljs-keyword\">attribute<\/span> X_INTERFACE_MODE <span class=\"hljs-keyword\">of<\/span> CLOCK_timer : <span class=\"hljs-keyword\">signal<\/span> <span class=\"hljs-keyword\">is<\/span> <span class=\"hljs-string\">\"monitor\"<\/span>;\n\n  <span class=\"hljs-keyword\">signal<\/span> reg_Pwm : <span class=\"hljs-built_in\">std_logic<\/span>;\n  <span class=\"hljs-keyword\">signal<\/span> reg_Carrier : <span class=\"hljs-built_in\">unsigned<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n\n  <span class=\"hljs-keyword\">signal<\/span> reg_ClkEnable : <span class=\"hljs-built_in\">std_logic<\/span>;\n  <span class=\"hljs-keyword\">signal<\/span> reg_HalfPeriodMinusOne : <span class=\"hljs-built_in\">unsigned<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n  <span class=\"hljs-keyword\">signal<\/span> reg_DutyCycle : <span class=\"hljs-built_in\">unsigned<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n  <span class=\"hljs-keyword\">signal<\/span> reg_DutyCyclePlusOne : <span class=\"hljs-built_in\">unsigned<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n\n  <span class=\"hljs-keyword\">signal<\/span> reg_Timer : <span class=\"hljs-built_in\">unsigned<\/span>(<span class=\"hljs-number\">15<\/span> <span class=\"hljs-keyword\">downto<\/span> <span class=\"hljs-number\">0<\/span>);\n\n  <span class=\"hljs-keyword\">type<\/span> t_CarrierStates <span class=\"hljs-keyword\">is<\/span> (COUNTING_UP, COUNTING_DOWN);\n  <span class=\"hljs-keyword\">signal<\/span> reg_CarrierState: t_CarrierStates;\n\n<span class=\"hljs-keyword\">begin<\/span>\n\n  o_carrier &lt;= <span class=\"hljs-built_in\">std_logic_vector<\/span>(reg_Carrier);\n  o_pwm &lt;= reg_Pwm;\n\n  P_INPUT_SAMPLING : <span class=\"hljs-keyword\">process<\/span>(clk_250_mhz)\n  <span class=\"hljs-keyword\">begin<\/span>\n    <span class=\"hljs-keyword\">if<\/span> rising_edge(clk_250_mhz) <span class=\"hljs-keyword\">then<\/span>\n      reg_Timer &lt;= <span class=\"hljs-built_in\">unsigned<\/span>(CLOCK_timer);\n      reg_ClkEnable &lt;= CLOCK_clk_en;\n      reg_HalfPeriodMinusOne &lt;= shift_right(<span class=\"hljs-built_in\">unsigned<\/span>(CLOCK_period), <span class=\"hljs-number\">1<\/span>) - <span class=\"hljs-number\">1<\/span>;\n      <span class=\"hljs-comment\">-- update the duty-cycle when the carrier hits zero<\/span>\n      <span class=\"hljs-keyword\">if<\/span> reg_Carrier = <span class=\"hljs-number\">0<\/span> <span class=\"hljs-keyword\">or<\/span> (i_enableDoubleRate = <span class=\"hljs-string\">'1'<\/span> <span class=\"hljs-keyword\">and<\/span> reg_Carrier = <span class=\"hljs-built_in\">unsigned<\/span>(CLOCK_period)) <span class=\"hljs-keyword\">then<\/span>\n        reg_DutyCycle &lt;= <span class=\"hljs-built_in\">unsigned<\/span>(i_nextDutyCycle);\n        reg_DutyCyclePlusOne &lt;= <span class=\"hljs-built_in\">unsigned<\/span>(i_nextDutyCycle) + <span class=\"hljs-number\">1<\/span>;\n      <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n    <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n  <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">process<\/span> P_INPUT_SAMPLING;\n\n  P_TRIANGLE_CARRIER: <span class=\"hljs-keyword\">process<\/span>(clk_250_mhz)\n  <span class=\"hljs-keyword\">begin<\/span>\n    <span class=\"hljs-keyword\">if<\/span> rising_edge(clk_250_mhz) <span class=\"hljs-keyword\">then<\/span>\n      <span class=\"hljs-comment\">-- reg_ClkEnable serves to slow down the logic if the CLOCK_prescaler is used<\/span>\n      <span class=\"hljs-comment\">-- it is used only if the frequency is lower than 3.8 kHz<\/span>\n      <span class=\"hljs-keyword\">if<\/span> reg_ClkEnable = <span class=\"hljs-string\">'1'<\/span> <span class=\"hljs-keyword\">then<\/span>\n        <span class=\"hljs-keyword\">if<\/span> reg_CarrierState = COUNTING_UP <span class=\"hljs-keyword\">then<\/span>\n          reg_Carrier &lt;= reg_Carrier + <span class=\"hljs-number\">2<\/span>;\n          <span class=\"hljs-keyword\">if<\/span> reg_Timer &gt;= reg_HalfPeriodMinusOne <span class=\"hljs-keyword\">then<\/span> <span class=\"hljs-comment\">-- minus one because well go in counting down in next clock cycle<\/span>\n            reg_CarrierState &lt;= COUNTING_DOWN;\n          <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n        <span class=\"hljs-keyword\">else<\/span> <span class=\"hljs-comment\">-- reg_CarrierState = COUNTING_DOWN<\/span>\n          <span class=\"hljs-keyword\">if<\/span> reg_Carrier &gt;= <span class=\"hljs-number\">2<\/span> <span class=\"hljs-keyword\">then<\/span>\n            reg_Carrier &lt;= reg_Carrier - <span class=\"hljs-number\">2<\/span>;\n          <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n          <span class=\"hljs-keyword\">if<\/span> reg_Timer = <span class=\"hljs-number\">0<\/span> <span class=\"hljs-keyword\">then<\/span>\n            reg_CarrierState &lt;= COUNTING_UP;\n            reg_Carrier &lt;= (<span class=\"hljs-keyword\">others<\/span> =&gt; <span class=\"hljs-string\">'0'<\/span>);\n          <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n        <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n      <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n    <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n  <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">process<\/span> P_TRIANGLE_CARRIER;\n\n  P_OUTPUT: <span class=\"hljs-keyword\">process<\/span>(clk_250_mhz)\n  <span class=\"hljs-keyword\">begin<\/span>\n    <span class=\"hljs-keyword\">if<\/span> rising_edge(clk_250_mhz) <span class=\"hljs-keyword\">then<\/span>\n      <span class=\"hljs-keyword\">if<\/span> (reg_DutyCycle \/= <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">AND<\/span> (reg_DutyCyclePlusOne &gt; reg_Carrier) <span class=\"hljs-keyword\">then<\/span>\n        reg_Pwm &lt;= <span class=\"hljs-string\">'1'<\/span>;\n      <span class=\"hljs-keyword\">else<\/span>\n        reg_Pwm &lt;= <span class=\"hljs-string\">'0'<\/span>;\n      <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n    <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">if<\/span>;\n  <span class=\"hljs-keyword\">end<\/span> <span class=\"hljs-keyword\">process<\/span> P_OUTPUT;\n\n<span class=\"hljs-keyword\">end<\/span> impl;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">VHDL<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">vhdl<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div><\/div><\/div>\n<\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-testing-the-fpga-based-pwm-module-in-simulation\"><span class=\"ez-toc-section\" id=\"Testing-the-FPGA-based-PWM-module-in-simulation\"><\/span>Testing the FPGA-based PWM module in simulation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The following test bench is used to validate the proper functioning of the FPGA pulse-width modulation with a Simulink simulation. The screenshots below show the test of PWM using the Xilinx System Generator implementation, but the testbench is identical for testing the MATLAB HDL Coder implementation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"360\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181-1024x360.png\" alt=\"Simulation test bench for the FPGA-based PWM block\" class=\"wp-image-3641\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181-1024x360.png 1024w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181-300x105.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181-768x270.png 768w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181-1536x539.png 1536w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-181.png 1683w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Simulation test bench for the FPGA-based PWM block<\/figcaption><\/figure>\n\n\n\n<p>The testbench generates CLOCK signals that are identical to the interface of the <em>imperix firmware<\/em> IP. The CLOCK frequency is set to 200 kHz. A sinusoidal signal ranging from 0 to <code>CLOCK_period<\/code> (in ticks) is connected to the <em>dutycycle<\/em> input. The following plot validates that the resulting PWM has a frequency of 200 kHz and that its duty cycle varies from 0 to 1 following the sinusoid.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"604\" height=\"409\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-5.png\" alt=\"\" class=\"wp-image-4330\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-5.png 604w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-5-300x203.png 300w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/figure><\/div>\n\n\n\n<p><br>As shown below, the behavior of internal signals of the PWM module can also be inspected by adding scopes inside the Xilinx System Generator design. System Generator will complain and show red (!). It does not cause any problem during simulation but it is important to remove any scope before generating the FPGA IP.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"415\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8-1024x415.png\" alt=\"\" class=\"wp-image-4333\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8-1024x415.png 1024w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8-300x122.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8-768x311.png 768w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8-1536x622.png 1536w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-8.png 1674w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p>The internal signal <code>UpdatedDutyCycle<\/code> is the actual value compared to the triangular carrier to generate the PWM signal. Changing the constant signal applied to the <code>update_rate<\/code> input allows selecting between <em>single-rate<\/em> update (0) and <em>double-rate <\/em>update (1). These two modes are documented in the standard <a href=\"https:\/\/imperix.com\/doc\/software\/carrier-based-pwm\">carrier-based PWM block help<\/a>. Observing internal signals allows checking that the <code>UpdatedDutyCycle<\/code> behaves according to the selected update rate mode.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-6.png\" alt=\"\" class=\"wp-image-4331\" width=\"559\" height=\"395\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-6.png 559w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-6-300x212.png 300w\" sizes=\"auto, (max-width: 559px) 100vw, 559px\" \/><figcaption>Duty cycle update in single-rate update mode<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"560\" height=\"394\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-7.png\" alt=\"\" class=\"wp-image-4332\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-7.png 560w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-7-300x211.png 300w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><figcaption>Duty cycle update in double-rate update mode<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-integrating-the-pwm-modulator-into-the-xilinx-fpga\"><span class=\"ez-toc-section\" id=\"Integrating-the-PWM-modulator-into-the-Xilinx-FPGA\"><\/span>Integrating the PWM modulator into the Xilinx FPGA<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-description-of-the-fpga-based-pwm-modulator-example\"><span class=\"ez-toc-section\" id=\"Description-of-the-FPGA-based-PWM-modulator-example\"><\/span>Description of the FPGA-based PWM modulator example<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The FPGA design illustrated below is used to test the generated FPGA PWM modulator. Its purpose is to manually select the duty cycle of the modulator from a PC by using <a href=\"https:\/\/imperix.com\/software\/cockpit\/\">Imperix Cockpit<\/a>. To do so, a <a href=\"https:\/\/imperix.com\/doc\/software\/tunable-parameter\">tunable parameter<\/a> block is used on the CPU. It is configured with the name <strong>duty_cycle<\/strong> and the data type <strong>single<\/strong>. This value is transferred from the CPU to the FPGA using the&nbsp;<strong>CPU2FPGA_00&nbsp;<\/strong>interface (SBO_00 and SBO_01) as explained in the <a href=\"https:\/\/imperix.com\/doc\/help\/getting-started-with-fpga-control-development\">getting started with FPGA control<\/a> page.&nbsp;In the FPGA, this single-precision duty-cycle is transformed into an integer value in ticks as follow:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The 32-bit single-precision floating-point value is transformed into a 16-bit fixed-point value with an integer width of 1-bit and a fraction width of 15-bit (fix16_15). This repartition has been chosen because the duty cycle is expected to range between 0.0 and 1.0 so only 1-bit is required on the integer part.<\/li><li>To obtain a value in <em>ticks<\/em>, the result of the previous step is multiplied by CLOCK_period. The result of the multiplication of a fix16_15 with a uint16 is a fix32_15 (32-bit, 17-bit integer part, and 15-bit fractional part).<\/li><li>Finally, only the 16 first bits of this result are used as the duty cycle input of the FPGA PWM modulator IP.<\/li><\/ul>\n\n\n\n<p>The CLOCK_0 will be used as a clock reference for the FPGA pulse-width modulation, which means that the PWM modulator will run at the same frequency as the CPU control task and that both will stay synchronized. (That is because the CPU interrupt rate is always defined by CLOCK_0.)<\/p>\n\n\n\n<p>On the imperix firmware IP, the&nbsp;<code>sb_pwm[31:0]<\/code>&nbsp;port provides access to the same PWM output chain as that used by other modulators (CB-PWM, PP-PWM, DO-PWM and SS-PWM). This allows the user to generate complementary signals with dead-time, use the standard activate and deactivate functions and rely on the protection mechanism that blocks PWM outputs when a fault is detected.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/Block_diagram_CPU_FPGA-1.png\" alt=\"FPGA PWM modulator block diagram\" class=\"wp-image-7137\" width=\"799\" height=\"247\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/Block_diagram_CPU_FPGA-1.png 799w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/Block_diagram_CPU_FPGA-1-300x93.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/Block_diagram_CPU_FPGA-1-768x237.png 768w\" sizes=\"auto, (max-width: 799px) 100vw, 799px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-info\" role=\"alert\">When driving a PWM channel (two pseudo-complementary signals with dead time), the user only needs to generate the HIGH signal, which must be connected to the appropriate\u00a0<code>sb_pwm<\/code>\u00a0input (<code>sb_pwm[0]<\/code>,\u00a0<code>sb_pwm[2]<\/code>,\u00a0<code>sb_pwm[4]<\/code>, etc.). Another example of such a configuration is available in the <a href=\"https:\/\/imperix.com\/doc\/implementation\/hysteresis-current-control\">FPGA-based hysteresis current control<\/a> example<\/div>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-danger\" role=\"alert\">Imperix\u00a0<strong>strongly discourages<\/strong>\u00a0the user from directly driving the top-level\u00a0<code>pwm<\/code>\u00a0port, as this would bypass the enable\/disable mechanism! Instead, the SB-PWM driver is meant to provide proper access to PWM outputs, which should be used in all cases. This is critical since this mechanism also handles <strong>fault management<\/strong>!<\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-cpu-side-implementation\"><span class=\"ez-toc-section\" id=\"CPU-side-implementation\"><\/span>CPU-side implementation<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>As with any FPGA-based implementation, a CPU code is still required to configure the imperix IP and define real-time variables accessible from the various <a href=\"https:\/\/imperix.com\/doc\/help\/cockpit-user-guide#h-using-modules-to-interact-with-the-controller\">Cockpit modules<\/a>. In the current example, the CPU code<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>configures the frequency of CLOCK_0,<\/li><li>configures the Sandbox PWM driver,<\/li><li>declares the <code>duty_cycle<\/code> variable and transmits it to the FPGA through the SBO interface. <\/li><\/ul>\n\n\n\n<p id=\"h-using-acg-sdk-on-simulink\"><strong>Using ACG SDK on Simulink<\/strong><\/p>\n\n\n\n<p>The frequency of CLOCK_0 is defined in the <a href=\"https:\/\/imperix.com\/doc\/software\/config-control-task-configuration\">Configuration block<\/a>, and the <code>duty_cycle<\/code> (float) variable is created using a <a href=\"https:\/\/imperix.com\/doc\/software\/tunable-parameter\">tunable parameter<\/a> block. It is then mapped to <strong>M_AXIS_CPU2_FPGA_00<\/strong> using the the MATLAB Function block <em>single2sbo<\/em> (as introduced in <a href=\"https:\/\/imperix.com\/doc\/help\/getting-started-with-fpga-control-development\">Getting started with FPGA control development<\/a>).<\/p>\n\n\n\n<p>The <a href=\"https:\/\/imperix.com\/doc\/software\/sandbox-pwm\">SB-PWM block<\/a> is used to configure and activate\/deactivate the output PWM <strong>channel 0 (CH0)<\/strong> (lane #0 and lane #1). The output is configured as <strong>Dual (PWM_H + PWM_L)<\/strong> with a <strong>deadtime <\/strong>of 1 \u00b5s. This configuration expects a PWM signal coming to <strong>sb_pwm[0]<\/strong> input of the <em>imperix firmware<\/em> IP and will automatically generate the complementary signals with the configured deadtime.<\/p>\n\n\n\n<div class=\"wp-block-file aligncenter\"><a href=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2022\/12\/TN141_FPGA_PWM_CPU_side.slx\" class=\"wp-block-file__button\" download>Click to download the Simulink model<\/a><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"866\" height=\"352\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-9.png\" alt=\"\" class=\"wp-image-4336\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-9.png 866w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-9-300x122.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/07\/image-9-768x312.png 768w\" sizes=\"auto, (max-width: 866px) 100vw, 866px\" \/><\/figure>\n\n\n\n<p id=\"h-using-cpp-sdk\"><strong>Using CPP SDK<\/strong><\/p>\n\n\n\n<p>The equivalent functionalities can also be implemented in C code, using <a href=\"https:\/\/imperix.com\/software\/cpp-sdk\/\">CPP SDK<\/a>. The corresponding code is available for download below.<\/p>\n\n\n\n<div class=\"wp-block-file aligncenter\"><a href=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/TN141_CPU_code_CPP.zip\" class=\"wp-block-file__button\" download>Click to download the C code example<\/a><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-fpga-side-implementation-using-vivado\"><span class=\"ez-toc-section\" id=\"FPGA-side-implementation-using-Vivado\"><\/span>FPGA-side implementation using Vivado<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The <strong>TN141_vivado_design.pdf<\/strong> file below shows the full Vivado FPGA design. Here are the step-by-step instructions to reproduce it.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"375\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103-1024x375.png\" alt=\"\" class=\"wp-image-6879\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103-1024x375.png 1024w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103-300x110.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103-768x281.png 768w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103-1536x563.png 1536w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/08\/image-103.png 1974w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-file aligncenter\"><a href=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/TN141_vivado_design.pdf\" class=\"wp-block-file__button\" download>Click to download <strong>TN141_vivado_design<\/strong>.pdf<\/a><\/div>\n\n\n\n<ol class=\"wp-block-list\"><li>Create an FPGA control implementation starter template by following the <a href=\"https:\/\/imperix.com\/doc\/help\/getting-started-with-fpga-control-development\">Getting started with FPGA control implementation<\/a>.<\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1019\" height=\"990\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/template_screenshot.png\" alt=\"\" class=\"wp-image-3695\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/template_screenshot.png 1019w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/template_screenshot-300x291.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/template_screenshot-768x746.png 768w\" sizes=\"auto, (max-width: 1019px) 100vw, 1019px\" \/><\/figure><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\"><li>Add the <em>FPGA PWM<\/em> IP into your Vivado project. System Generator is taken as an example but the steps are identical for a VHDL or an HDL Coder module.<\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/cdn.imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1.png\" alt=\"\" class=\"wp-image-3790\" width=\"360\" height=\"236\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1.png 426w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/sysgen_ip_vivado-1-300x196.png 300w\" sizes=\"auto, (max-width: 360px) 100vw, 360px\" \/><\/figure><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\"><li>Add a <em>Floating-point <\/em>IP and select the <strong>Float-to-fixed<\/strong> operation. Select <strong>Single<\/strong> precision for input and <strong>Integer Width 1, Fraction Width 15<\/strong> (fix16_15) for output. This module will convert the <em>duty cycle<\/em> sent by CPU from single to fix16_15.<\/li><\/ol>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"373\" height=\"328\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_fix_to_float-1.png\" alt=\"\" class=\"wp-image-3795\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_fix_to_float-1.png 373w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_fix_to_float-1-300x264.png 300w\" sizes=\"auto, (max-width: 373px) 100vw, 373px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_ip_fix_to_float.png\" alt=\"\" class=\"wp-image-3794\" width=\"270\" height=\"126\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_ip_fix_to_float.png 321w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_ip_fix_to_float-300x140.png 300w\" sizes=\"auto, (max-width: 270px) 100vw, 270px\" \/><\/figure><\/div>\n<\/div>\n<\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"4\"><li>Add a <strong>Multiplier IP<\/strong> and set the configuration as shown below.<ul><li>The input A is connected to the <code>CLOCK_period <\/code>so it is set to 16-bit unsigned<\/li><li>The input B is connected to the fixed-point duty cycle so it is set to 16-bit signed<\/li><li>The output range is set to return only the 16 first bits of the integer part of the result<\/li><li>The clock enable (CE) input is enabled and will be connected to the <em>tvalid <\/em>output of the <em>single_to_fix16_15 <\/em>IP output. This way, the multiplication is performed synchronously with the data coming from the AXI4-Stream.<\/li><\/ul><\/li><\/ol>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"418\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_1-2.png\" alt=\"\" class=\"wp-image-3812\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_1-2.png 694w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_1-2-300x181.png 300w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"418\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_2.png\" alt=\"\" class=\"wp-image-3809\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_2.png 694w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/vivado_config_mul_2-300x181.png 300w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"189\" height=\"192\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-164.png\" alt=\"\" class=\"wp-image-3600\"\/><\/figure><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"5\"><li>Add a <strong>Constant<\/strong> IP to set all the 31 unused <code>sb_pwm <\/code>outputs to &#8216;0&#8217;. Set its <em>Const Width<\/em> to 31 and its <em>Const Val <\/em>to 0.<\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"149\" height=\"122\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-230.png\" alt=\"\" class=\"wp-image-3813\"\/><\/figure><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"6\"><li>Add a <strong>Concat<\/strong> IP. It will serve to concat the pwm output of the PWM IP with the zeros of the Constant IP.<\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"191\" height=\"144\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/image-231.png\" alt=\"\" class=\"wp-image-3814\"\/><\/figure><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"7\"><li>Connect the pins as follows:<ul><li>all the <strong>CLOCK_0 <\/strong>signals of the <em>imperix firmware IP<\/em> signals to the PWM block<\/li><li><strong>M_AXIS_CPU2FPGA_00 <\/strong>to <strong>S_AXIS_A <\/strong>of <em>single_to_fix16_15<\/em><\/li><li><strong>CLOCK_0_period <\/strong>to <strong>A<\/strong> of the <em>Multiplier<\/em><\/li><li><strong>tdata <\/strong>of <strong>M_AXIS_RESULT <\/strong>of <em>single_to_fix16_15<\/em> to <strong>B <\/strong>of the <em>Multiplier<\/em><\/li><li><strong>tvalid <\/strong>of <strong>M_AXIS_RESULT <\/strong>of <em>single_to_fix16_15<\/em> to <strong>CE <\/strong>of the <em>Multiplier<\/em><\/li><li><strong>P<\/strong> of the <em>Multiplier<\/em> to <strong>i_nextdutycycle<\/strong><\/li><li><strong>o_pwm<\/strong> of the <em>PWM<\/em> IP to <strong>In0 <\/strong>of the <em>Concat<\/em> IP<\/li><li><strong>dout<\/strong> of the <em>31-bit to zero Constant<\/em> IP to In1 of the <em>Concat <\/em>IP<\/li><li><strong>dout <\/strong>of the <em>Concat<\/em> IP to the <strong>sb_pwm <\/strong>input of the <em>imperix firmware <\/em>IP<\/li><li>all the IP clocks to <strong>clk_250_mhz<\/strong><\/li><\/ul><\/li><\/ol>\n\n\n\n<p>And finally, the design can be synthesized and the bitstream generated:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Click&nbsp;<strong>Generate bitstream<\/strong>. It will launch the synthesis, implementation and bitstream generation<\/li><li>Once the bitstream generation is completed, click on&nbsp;<strong>File&nbsp;<\/strong>\u2192&nbsp;<strong>Export&nbsp;<\/strong>\u2192&nbsp;<strong>Export Bitstream File\u2026<\/strong>&nbsp;to save the bitstream somewhere on your computer.<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-experimental-validation\"><span class=\"ez-toc-section\" id=\"Experimental-validation\"><\/span>Experimental validation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The bitstream can be generated and loaded into the device using <a href=\"https:\/\/imperix.com\/software\/cockpit\/\">Cockpit<\/a>, as explained in the <a href=\"https:\/\/imperix.com\/doc\/help\/getting-started-with-fpga-control-development\">Getting started with FPGA control implementation<\/a> page. Then, the Simulink model&nbsp;<em>TN141_CPU_side.slx<\/em> can be built and launched as explained in&nbsp;the <a href=\"https:\/\/imperix.com\/doc\/help\/programming-imperix-controllers\">Programming and operating imperix controllers<\/a> getting started page.<\/p>\n\n\n\n<p>Using the <a href=\"https:\/\/imperix.com\/doc\/help\/cockpit-user-guide#h-variables-module\">Variables module<\/a> of Cockpit, the&nbsp;<em>duty_cycle<\/em>&nbsp;variable can be changed in real-time. After enabling the PWM outputs, the PWM signals at the output CH0 (lanes 0 &amp; 1) can be observed using an oscilloscope or a logic analyzer.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"947\" height=\"615\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2023\/03\/Cockpit.png\" alt=\"\" class=\"wp-image-14716\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2023\/03\/Cockpit.png 947w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2023\/03\/Cockpit-300x195.png 300w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2023\/03\/Cockpit-768x499.png 768w\" sizes=\"auto, (max-width: 947px) 100vw, 947px\" \/><figcaption>imperix Cockpit user interface<\/figcaption><\/figure>\n\n\n\n<p>The screenshot below shows the measured PWM signals using a logic analyzer, as expected the measured signals are complementary 50 kHz PWM signal with a duty cycle of 30% and a dead time of 1 \u00b5s.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/dsview2.png\" alt=\"\" class=\"wp-image-3823\" width=\"687\" height=\"224\" srcset=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/dsview2.png 614w, https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/dsview2-300x98.png 300w\" sizes=\"auto, (max-width: 687px) 100vw, 687px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-going-further\"><span class=\"ez-toc-section\" id=\"Going-further\"><\/span>Going further<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The <a href=\"https:\/\/imperix.com\/doc\/implementation\/high-level-synthesis-for-fpga\">high-level synthesis for FPGA developments<\/a> page re-uses this FPGA PWM modulator in a <strong>PI-based current control<\/strong>&nbsp;of a <strong>buck converter<\/strong> scenario. It shows how to integrate and connect&nbsp;<strong>HLS-generated IPs<\/strong>&nbsp;in a realistic FPGA power converter control implementation.<\/p>\n\n\n\n<div class=\"wp-block-simple-alerts-for-gutenberg-alert-boxes sab-alert sab-alert-dark\" role=\"alert\">Back to\u00a0<a href=\"https:\/\/imperix.com\/doc\/help\/fpga-development-on-imperix-controllers\">FPGA development homepage<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>To implement power converter control algorithms in an FPGA, it is often required to develop an FPGA-based pulse-width modulation (PWM) module. Therefore, this note presents&#8230;<\/p>\n","protected":false},"author":4,"featured_media":7139,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[4],"tags":[17],"software-environments":[106,103],"provided-results":[108,107],"related-products":[31,32,92,166,110],"guidedreadings":[],"tutorials":[179,130,129],"user-manuals":[],"coauthors":[70],"class_list":["post-3293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-implementation","tag-fpga-programming","software-environments-fpga","software-environments-matlab","provided-results-experimental","provided-results-simulation","related-products-b-board-pro","related-products-b-box-rcp","related-products-b-box-micro","related-products-b-box-rcp-3-0","related-products-tpi","tutorials-automated-tools-for-fpga-developments","tutorials-custom-fpga-pwm-modulator-implementation","tutorials-fpga-based-control-of-a-grid-tied-inverter"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>FPGA-based PWM modulator for power converter control<\/title>\n<meta name=\"description\" content=\"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"FPGA-based PWM modulator for power converter control\" \/>\n<meta property=\"og:description\" content=\"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator\" \/>\n<meta property=\"og:site_name\" content=\"imperix\" \/>\n<meta property=\"article:published_time\" content=\"2021-06-10T11:35:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-07T12:55:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png\" \/>\n\t<meta property=\"og:image:width\" content=\"450\" \/>\n\t<meta property=\"og:image:height\" content=\"300\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Beno\u00eet Steinmann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Beno\u00eet Steinmann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator\"},\"author\":{\"name\":\"Beno\u00eet Steinmann\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#\\\/schema\\\/person\\\/a69a3bda75b05d0923cc76d7268cc94f\"},\"headline\":\"Custom PWM modulator implementation in FPGA\",\"datePublished\":\"2021-06-10T11:35:41+00:00\",\"dateModified\":\"2025-05-07T12:55:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator\"},\"wordCount\":2556,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/3_2_ratio_TN141.png\",\"keywords\":[\"FPGA programming\"],\"articleSection\":[\"Technical notes\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator\",\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator\",\"name\":\"FPGA-based PWM modulator for power converter control\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/3_2_ratio_TN141.png\",\"datePublished\":\"2021-06-10T11:35:41+00:00\",\"dateModified\":\"2025-05-07T12:55:51+00:00\",\"description\":\"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#primaryimage\",\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/3_2_ratio_TN141.png\",\"contentUrl\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/06\\\/3_2_ratio_TN141.png\",\"width\":450,\"height\":300,\"caption\":\"FPGA PWM modulator block diagram\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/implementation\\\/fpga-pwm-modulator#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Knowledge base\",\"item\":\"https:\\\/\\\/imperix.com\\\/doc\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Technical notes\",\"item\":\"https:\\\/\\\/imperix.com\\\/doc\\\/category\\\/implementation\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Custom PWM modulator implementation in FPGA\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#website\",\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/\",\"name\":\"imperix\",\"description\":\"power electronics\",\"publisher\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/imperix.com\\\/doc\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#organization\",\"name\":\"imperix\",\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/imperix_logo.png\",\"contentUrl\":\"https:\\\/\\\/imperix.com\\\/doc\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/imperix_logo.png\",\"width\":350,\"height\":120,\"caption\":\"imperix\"},\"image\":{\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/imperix.com\\\/doc\\\/#\\\/schema\\\/person\\\/a69a3bda75b05d0923cc76d7268cc94f\",\"name\":\"Beno\u00eet Steinmann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g3b3f3d8e66019ebcb2848094940b98c0\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g\",\"caption\":\"Beno\u00eet Steinmann\"},\"description\":\"Benoit is an embedded systems expert and the leader of software and firmware developments at imperix. On the knowledge base, he is the author of numerous software reference documents.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/benoit-steinmann\\\/\"],\"url\":\"https:\\\/\\\/imperix.com\\\/doc\\\/author\\\/steinmann\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"FPGA-based PWM modulator for power converter control","description":"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator","og_locale":"en_US","og_type":"article","og_title":"FPGA-based PWM modulator for power converter control","og_description":"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.","og_url":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator","og_site_name":"imperix","article_published_time":"2021-06-10T11:35:41+00:00","article_modified_time":"2025-05-07T12:55:51+00:00","og_image":[{"width":450,"height":300,"url":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png","type":"image\/png"}],"author":"Beno\u00eet Steinmann","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Beno\u00eet Steinmann","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#article","isPartOf":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator"},"author":{"name":"Beno\u00eet Steinmann","@id":"https:\/\/imperix.com\/doc\/#\/schema\/person\/a69a3bda75b05d0923cc76d7268cc94f"},"headline":"Custom PWM modulator implementation in FPGA","datePublished":"2021-06-10T11:35:41+00:00","dateModified":"2025-05-07T12:55:51+00:00","mainEntityOfPage":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator"},"wordCount":2556,"commentCount":0,"publisher":{"@id":"https:\/\/imperix.com\/doc\/#organization"},"image":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#primaryimage"},"thumbnailUrl":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png","keywords":["FPGA programming"],"articleSection":["Technical notes"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#respond"]}]},{"@type":"WebPage","@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator","url":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator","name":"FPGA-based PWM modulator for power converter control","isPartOf":{"@id":"https:\/\/imperix.com\/doc\/#website"},"primaryImageOfPage":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#primaryimage"},"image":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#primaryimage"},"thumbnailUrl":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png","datePublished":"2021-06-10T11:35:41+00:00","dateModified":"2025-05-07T12:55:51+00:00","description":"This note presents a custom Xilinx FPGA pulse-width modulation (PWM) modulator that can be used for FPGA-based power converter control.","breadcrumb":{"@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#primaryimage","url":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png","contentUrl":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/06\/3_2_ratio_TN141.png","width":450,"height":300,"caption":"FPGA PWM modulator block diagram"},{"@type":"BreadcrumbList","@id":"https:\/\/imperix.com\/doc\/implementation\/fpga-pwm-modulator#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Knowledge base","item":"https:\/\/imperix.com\/doc\/"},{"@type":"ListItem","position":2,"name":"Technical notes","item":"https:\/\/imperix.com\/doc\/category\/implementation"},{"@type":"ListItem","position":3,"name":"Custom PWM modulator implementation in FPGA"}]},{"@type":"WebSite","@id":"https:\/\/imperix.com\/doc\/#website","url":"https:\/\/imperix.com\/doc\/","name":"imperix","description":"power electronics","publisher":{"@id":"https:\/\/imperix.com\/doc\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/imperix.com\/doc\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/imperix.com\/doc\/#organization","name":"imperix","url":"https:\/\/imperix.com\/doc\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/imperix.com\/doc\/#\/schema\/logo\/image\/","url":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/03\/imperix_logo.png","contentUrl":"https:\/\/imperix.com\/doc\/wp-content\/uploads\/2021\/03\/imperix_logo.png","width":350,"height":120,"caption":"imperix"},"image":{"@id":"https:\/\/imperix.com\/doc\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/imperix.com\/doc\/#\/schema\/person\/a69a3bda75b05d0923cc76d7268cc94f","name":"Beno\u00eet Steinmann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g3b3f3d8e66019ebcb2848094940b98c0","url":"https:\/\/secure.gravatar.com\/avatar\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/22a9252907f853f91d07b143dfcc84f6ec0cc31f6b72408b503a7026eed5b109?s=96&d=mm&r=g","caption":"Beno\u00eet Steinmann"},"description":"Benoit is an embedded systems expert and the leader of software and firmware developments at imperix. On the knowledge base, he is the author of numerous software reference documents.","sameAs":["https:\/\/www.linkedin.com\/in\/benoit-steinmann\/"],"url":"https:\/\/imperix.com\/doc\/author\/steinmann"}]}},"_links":{"self":[{"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/posts\/3293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/comments?post=3293"}],"version-history":[{"count":128,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/posts\/3293\/revisions"}],"predecessor-version":[{"id":28031,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/posts\/3293\/revisions\/28031"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/media\/7139"}],"wp:attachment":[{"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/media?parent=3293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/categories?post=3293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/tags?post=3293"},{"taxonomy":"software-environments","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/software-environments?post=3293"},{"taxonomy":"provided-results","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/provided-results?post=3293"},{"taxonomy":"related-products","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/related-products?post=3293"},{"taxonomy":"guidedreadings","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/guidedreadings?post=3293"},{"taxonomy":"tutorials","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/tutorials?post=3293"},{"taxonomy":"user-manuals","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/user-manuals?post=3293"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/imperix.com\/doc\/wp-json\/wp\/v2\/coauthors?post=3293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}