logo-mobile

ROHM

ROHM
Menu
  • Arduino –
  • Raspberry Pi –
  • Trending –
  • Others –
  • About –
  • Contact –

Arduino

Intro to FPGAs with the Mojo – Part 2

Rahul Iyer
Published by Rahul Iyer at July 14, 2017
Categories
  • Arduino
Tags
  • fpga
  • mojo
  • pulse-width modulation
  • pwm
fpga mojo
  • Intro & Pulse-Width Modulation (PWM)
  • Hardware PWM on the Mojo FPGA
  • Hardware PWM on the Mojo FPGA (Continued) & Appendix

Hardware PWM on the Mojo FPGA

In this tutorial, we’ll explore how to describe hardware PWM in Verilog, and will see how the modularity of Verilog code allows us to configure as many hardware PWM circuits in the Mojo as we want.

Here are all the parts you’ll need to follow along:

  • Mojo V3 Development Board

We’re going to build our Verilog code for this project on top of the Mojo Base Project provided by Embedded Micro.  It is helpful to build off the base project, because the device specification and other initialization in ISE has already been set up for us!  If you’d like, you can rename the project by renaming the .xise project file in the project directory.  I named mine “MojoPWM.xise”.  

Usually, we’d first declare names and pin numbers in the UCF for the different connections we are making to I/O pins on the Mojo.  However for this project, we will use the onboard LEDs for which signal names and pin connections have already been specified.  Thus, no additional declarations are necessary.  We’ll start by creating a new Verilog module that specifies our hardware PWM behavior.  Instead of placing the code directly in the mojo_top module, we’ll create a separate module to make use of modularity.  If we want to create different hardware PWM circuits to run different LEDs, we’ll merely have to create new instances of this separate PWM module instead of copying and pasting large chunks of code.  This will become more apparent shortly.  

Right-click anywhere in the left-hand side “Hierarchy” window, and click on the option named “New Source…”  Under the options list for “Source Type,” select “Verilog Module,” and name the file “PWM.v”  This will create a new Verilog file with a skeleton for the PWM module.  

Before we actually beginning writing code, let’s discuss our PWM implementation.  As described before, the signal we’ll be generating with this hardware is periodic in nature, which means that its value is time-dependent.  We’ll therefore have to specify its behavior with respect to a constantly ticking clock signal.  This clock signal is already provided to us in the mojo_top module as a system input, and is a square wave that looks something like this:

fpga mojo

Our hardware’s operation can be summarized as follows:

  • Every clock cycle (the start of which is denoted by the rising edge of the signal), we will increment the value of an internal counter, which has a value in the range 0 – 255.
  • The duty cycle will be provided as an input to our module in the range 0 – 255 (just like in an Arduino’s hardware PWM).  If our counter value is less than the duty cycle value, our output signal will be high.  Otherwise, our output signal will be low.
  • Upon receiving a high value on a reset line, the hardware will reset the counter.  

We choose the value 255 as our maximum counter value because this is the maximum integer number that can be stored in 8 bits (11111111).  When incremented by 1 from this value, the counter will wrap back around to 00000000, as it would have overflown.  To learn more about binary arithmetic and the binary representation of integers, check out the links in the appendix below!

Here’s a timing diagram that represents our hardware’s operation with respect to the internal clock signal:

fpga mojo

Figure 2. Timing Diagram for an 8-bit Hardware PWM module with duty cycle 3/255.  The max duty cycle value in binary is the same as the max counter value: 11111111

We’ll start our Verilog description of the PWM module with the input and output signals list:

input clk,

input rst,

input[7:0] duty,

output sig_drv

As you may guess from their names, these four signals are the clock, reset, duty cycle value, and PWM output signals respectively.  

Next, we have to qualify the data type for our output signal, sig_drv.  Verilog has two data types, wires (wire) and registers (reg).  The differences between these two types are subtle for our application, however the main difference to note would be that when using always blocks as we will be in this project, one can only write to regs and not wires.  We will discuss always blocks and their operation shortly.  If signals from the signal list are left unqualified by the words wire or reg, Verilog implicitly declares them as wire type.  In this case, we need to describe sig_drv as a reg, which we can do through the following line right after the module’s signal list:

reg sig_drv;

We will also be using an 8-bit counter as described above, which we’ll also have to set through an always block.  Thus, we need to declare an 8 bit-wide counter as follows:

reg[7:0] counter;  

You may have noticed that like many other programming languages, Verilog is zero-indexed, which means that counting always begins at the number 0.  Thus, the indices of bits in an 8 bit-wide counter would have numbers 0 through 7.  

Next, we must describe logic for counting up with the 8-bit counter and for driving the output signal.  We can do that with always blocks!  An always block is a Verilog structure that allows users to specify operations that will occur only when the triggering condition(s) for the always block is/are met.  The basic structure for an always block is as follows:

always @ (…)

  begin

     …

  end

Inside the parentheses following the “@” symbol, the user must specify the triggering conditions that decide when the logic inside the block executes.  For our project, we need two always blocks:

always @(*)

  begin

 

  end

 

always @(posedge clk or posedge rst)

  begin

 

  end

In the first block, the triggering condition is “ * ”, which means that the logic inside that block will execute whenever any of the signals in the project change.  Hardware engineers might refer to this block as combinational logic, logic that always defines output values as some function of input values.  In this block, we will place the logic for our project that must function at all time instants, not just once every clock cycle: the driving of the output signal.  

As described earlier, the output signal is driven either high or low based on whether the counter is greater than or less than the duty cycle.  This functionality can be accomplished with the following lines of code within the always @ (*) block:

if (duty > counter)

  begin

     sig_drv = 1’b1;

  end

else

  begin

     sig_drv = 1’b0;

  end

The sig_drv signal is 1 bit wide (it only has the value 0 or 1…a single bit), so we preface the value we’re assigning to it with the characters “1’b”.  From the code above, we can see that when the duty cycle is greater than the counter, the sig_drv line is driven to 1 (high), and otherwise, it is driven to 0 (low).  

In the second block, the triggering condition is posedge clk or posedge rst.  This means that the logic inside this block will only be executed once every clock cycle when the clock signal goes from low to high, or when the reset line goes from low to high.  We’re going to use this always block to specify the counter increment that will occur once every clock cycle.  This can be done with the following lines of code within this block:

if (rst)

  begin

     counter <= 8’b0;

  end

else

  begin

     counter <= counter + 1;

  end

The first segment of the if statement specifies that when the reset line goes high, the 8 bit-wide counter must be reset to all zeros.  The second segment, the else condition, specifies that if the reset line is not high, the counter’s value must be incremented.  

We can see that the value that is assigned to counter is dependent on its previous value.  Hardware engineers refer to this type of logic as sequential, because outputs are functions of both inputs and past states.  

The final aspect of this code to clarify is the “<=” operator, the non-blocking assignment operator, that was used to assign values to the counter variable.  When we use the “=” operator, the blocking assignment operator, to assign values to signals as we have in the past, we actually tell Verilog implicitly that we want the code we’ve written to execute top-down.  In other words, if we wrote two subsequent “=” assignment statements, the first assignment operation would have to finish executing before the second one began.  This is fine and actually necessary in some logic, as we might use values that we assign in this manner to do subsequent computations.  

However, in sequential logic that depends on a fast clock signal, we actually want all of our value assignments to occur somewhat in parallel (if they did not depend on each other), so that we do not delay the program enough to conflict with the next clock edge.  In this program, we do not have multiple assignments that occur on each clock edge.  However, if we did, using the non-blocking assignment operator would accomplish this.  

The complete PWM module should look like this:

fpga mojo

1 2 3
Rahul Iyer
Rahul Iyer
Studying Electrical Engineering at UCLA, Rahul loves to work on electronics and robotics projects as a hobby. He is especially enthusiastic about electric vehicle technology and assistive robotics.

Check us out on Social Media

  • Facebook
  • Twitter

Recommended Posts

  • FPGA Tutorial: Intro to FPGAs with the Mojo – Part 1FPGA Tutorial: Intro to FPGAs with the Mojo – Part 1
  • Servo Motor Controlled Wireless Light SwitchServo Motor Controlled Wireless Light Switch
  • Arduino Robot RF Explorer – Part 2 – Putting Everything TogetherArduino Robot RF Explorer – Part 2 – Putting Everything Together
  • How To Make Your Own RobotHow To Make Your Own Robot
  • Intro to CMUcam5 Pixy Vision Camera Sensor Part 2 – Creating a Ball Balance BeamIntro to CMUcam5 Pixy Vision Camera Sensor Part 2 – Creating a Ball Balance Beam
  • Make a Smart Automatic Pet Feeder with Arduino Uno (Cont.)Make a Smart Automatic Pet Feeder with Arduino Uno (Cont.)
Receive update on new postsPrivacy Policy

Recommended Tutorials

  • How to integrate an RFID module with Raspberry Pi How to integrate an RFID module with Raspberry Pi
  • How to Use the NRF24l01+ Module with Arduino How to Use the NRF24l01+ Module with Arduino
  • How to Run Arduino Sketches on Raspberry Pi How to Run Arduino Sketches on Raspberry Pi
  • Setting Up Raspberry Pi as a Home Media Server Setting Up Raspberry Pi as a Home Media Server

Recommended Trends

  • SewBot Is Revolutionizing the Clothing Manufacturing Industry SewBot Is Revolutionizing the Clothing Manufacturing Industry
  • All About The Sumo Robot Competition And Technology All About The Sumo Robot Competition And Technology
  • 5 Interesting Tips to Calculating the Forward Kinematics of a Robot 5 Interesting Tips to Calculating the Forward Kinematics of a Robot
  • Go Inside the Drones That Are Changing Food Delivery Go Inside the Drones That Are Changing Food Delivery
Menu
  • Arduino –
    Arduino Beginner’s Guide
  • Raspberry Pi –
    Raspberry Pi Beginner's Guide
  • Trending –
    Updates on New Technologies
  • Others –
    Interviews / Events / Others

Check us out on Social Media

  • Facebook
  • Twitter
  • About
  • Company
  • Privacy Policy
  • Terms of Service
  • Contact
  • Japanese
  • 简体中文
  • 繁體中文
Don’t Forget to Follow Us!
© Copyright 2016-2023. Device Plus - Powered by ROHM
© 2023 Device Plus. All Rights Reserved. Muffin group

istanbul escort istanbul escort istanbul escort