Close
0%
0%

FPGA Bootcamp #2

Take the next step with FPGAs: Sequential logic!

Similar projects worth following
In bootcamp #1 you learned how to use some simulation tools and build combinatorial logic -- that is, logic that doesn't depend on the previous state of the system. That's fine for some things, but a lot of practical systems need to remember their previous state or even states. In this bootcamp, you'll add flip flops to your design arsenal. You'll learn how flip flops are described in Verilog and the problems they solve -- and create. We are building up to configuring a Lattie IceStick, but once again, this bootcamp won't get to the hardware (that's bootcamp #3) so even if you don't have an IceStick, you can follow along and use a simulator in your browser.

In bootcamp #1 you learned how to use some simulation tools and build combinatorial logic -- that is, logic that doesn't depend on the previous state of the system. That's fine for some things, but a lot of practical systems need to remember their previous state or even states. 

To do that, you'll usually use a design that incorporates flip flops. A logic gate that has two states and can be in one state or the other. You might think, "Well, an AND gate has two states: 1 and 0." That's true, but that state depends completely on the inputs so it is a combinatorial gate. A flip flop will maintain its state even when its inputs change -- unless they change in the specific way that tells the flip flop to change state. This is the basis of many kinds of computer memory, for example.

There are several reasons this is exciting. Obviously, if we need to remember a state (the traffic light is currently red) this is the answer. But the way flip flops work also solves an important timing issue that we talked about in Bootcamp #1 -- how to make sure different processing times (propagation delays) don't cause glitches in outputs.

We'll talk more about that during this bootcamp, but here's the quick explanation:

Remember this diagram from Bootcamp #1?

In this case, the AND gate will possibly get "bad" inputs for about 50pS when the top input register a change before the bottom one comes in. Now assume that there are lots of other inputs to the AND gate with different times. Keeping track of this could be a real problem and even if you know the longest path is, say, 500pS, that doesn't help you stop the glitches. For the sake of this example, suppose the longest is 500pS and the AND gate itself adds another 400pS.

That means the longest path from Input to Out is 900pS. When the input changes, the output could be wrong--and even change incorrectly--during that 900pS window. But what if we put a flip flop between the AND gate and Out?

Each flip flop has a clock and the outputs can only change on a clock edge -- usually the positive edge. As long as the clock is not at an edge, the output of the flip flop won't change. So if you arrange for the clock edge to be at, say 1,000pS (1nS or 1 GHz) or longer, then it won't matter if the AND gate glitches or not. The glitches won't get past the flip flop (sometimes just called a flop by designers) and then once stable the flip flop will change states.

That sounds great, but of course there are pesky details. For example, that assumes the input is changing in sync with the clock. If it isn't you are opening up to metastability -- something we'll talk about in a future bootcamp. The reason is the signal into the flip flop has to be stable a little bit before the clock edge (set up time) and a little bit after the clock edge (hold time) or you'll have problems.

Another problem is what happens when your delays are not very tiny but are, instead, very large. If the delay is 1mS, your clock would have to be less than 1 kHz! There are several possible answers to that problem, including pipelining, which we'll talk about in the future.

For now, though, we are going to focus on developing simple systems with flip flops and leave the complex details until after we've figured that out. The demo design will keep the adder from last time but also include a latch that remembers if the adder ever generated a carry and a few counters to get the onboard 12 MHz clock down to a 2 Hz rate to drive blinking LEDs.

This bootcamp is part of a series:

Bootcamp 0Covers basic digital logic concepts with simulations
Bootcamp 1Introduction to FPGA coding and simulation with combinatorial logic 
Bootcamp 2More FPGA coding and simulation with flip flops (sequential logic) (this bootcamp)
Bootcamp 3Working with actual FPGA hardware

When you are ready, move on to the steps and continue on your FPGA adventure! You'll also...

Read more »

design.v

Main design file (same as on EDAPlayground)

x-verilog - 2.38 kB - 06/23/2018 at 01:46

Download

testbench.v

Test bench (same as on EDAPlayground)

x-verilog - 710.00 bytes - 06/23/2018 at 01:46

Download

  • 1 × Lattice IceStick FPGA board Not actually needed for Bootcamp #1 and #2 but you will need it by the end of the series
  • 1 × An account on http://www.edaplayground.com You don't actually need an account, but it will make things nicer. The account is free and if you don't like to hand our your e-mail, use a disposable one
  • 1 × Icarus Verilog Optional. If you don't want to use edaplayground, you can use Icarus or another simulator on your local PC
  • 1 × GTKWave Optional. If you want to use your own simulator you will need this program or another similar program to view the output

  • A Quick FPGA Glossary

    Al Williams07/12/2018 at 18:29 0 comments

    • Adder - See Full Adder and Half Adder.
    • AND Gate - A gate who's output is 1 only when all inputs are 1.
    • Blocking assignment - In Verilog, when an assignment occurs before any subsequent assignments (that is, it does not occur in parallel).
    • Combinatorial Logic - Logic that does not rely on the previous state of the system to set the current output state.
    • Exclusive OR Gate - See XOR Gate.
    • Flip Flop - A circuit element that can take one of two states (1 or 0) and remember it until changed. Somewhat like a one-bit memory device.
    • Full Adder - A circuit for adding two binary numbers and a carry bit (so three bits overall). It will produce a sum and a carry.
    • FPGA - Field Programmable Gate Array.
    • Half Adder - A circuit for adding two binary numbers. It will produce a sum and a carry
    • Inverter - See NOT Gate.
    • IP - Intellectual Property. Typically a third party module that does a particular function that you can integrate into your FPGA designs if you wish.
    • Logic Diagram - See Schematic.
    • Non-blocking Assignment - In Verilog, when an assignment occurs in parallel with other assignments in the same block.
    • NOT Gate - A gate that takes a single input and inverts it. That is, a 1 becomes a 0 and a 0 becomes a 1.
    • OR Gate - A gate who's output is a 1 if any inputs are 1.
    • Schematic - A diagram of a logic circuit  made up, usually, of logic symbols for fundamental gates.
    • Sequential Logic - Logic that typically uses flip flops and the current output state influences future output states.
    • Testbench - Verilog (or similar) code that exists only to send stimulus to a simulated device and record or test the results.
    • Truth Table - A table showing a logic circuit's possible inputs and the outputs that will result.
    • Workflow - The process of taking design inputs and producing a working FPGA configuration.
    • Verilog - A description language used to describe logic you wish to place on an FPGA.
    • VHDL - A description language (not used in this bootcamp) to describe logic you wish to place on an FPGA.
    • XOR Gate - Exclusive OR gate. A two-input gate that sets its output to 1 if either input is a 1, but not when both inputs are a 1.

    Logic Truth Tables for Two-Input Gates

    ABANDORXOR
    00000
    01011
    10011
    11110

  • A Brief Introduction to Sequential Logic Design

    Al Williams07/10/2018 at 22:26 0 comments

    Combinatorial design is easy to understand with AND, OR, and NOT gates doing most of the work. These designs are great for things where the previous state of the system doesn't matter. For example, imagine a car with an interior dome light. You want the light to come on if any of the doors are open (D1-D4) or the dashboard switch for interior light is on (S1). You can express that with an OR gate (or the | sign which is typically used for OR) Z=D1|D2|D3|D4|S1. Or perhaps you want all those conditions but only if a sensor says it is dark (X1). Then you could do an AND (&): Z=X1&(D1|D2|D3|D4|S1).

    However, consider the car's alarm. It might also look at D1, D2, D3, and D4. But what it does will depend on if the system is armed or not. Let's take the simplest case. The system should arm if it gets a pulse from the keyfob receiver K1. Another pulse will disarm it. While the system is armed, any input from D1, D2, D3, or D4 should set off the alarm. There's a problem with this, but let's look at it first before we work on the problem.

    The arming/disarming can be done with a T flip flop. This is the kind of flip flop that toggles its output with each clock pulse. So for example, if you forced the T input high you could connect K1 to the clock and the Q output would tell you if the system is armed or not (try it on Falstad).

    Now it would be simple to use a 4 input OR gate and an AND gate

    That works (try it on Falstad). 

    However, there is a slight problem. When you open a door and the system is armed, the alarm goes off as it should, but once you close the door, the alarm goes off again. Not ideal.

    To fix that you need another flip flop that remembers the alarm is on until the alarm is disarmed. You can try that on Falstad too:

    This is a bit odd because of the way it is clocked. In this case, the K1 signal is the clock for the T flip flop. The D flip flop uses a little delay (two inverters) to ensure the D line is stable by the time the clock edge rises. The R pin on the D flip flop is a reset and any time the system is not armed, it forces the output of the D flip flop to be low.

    In most FPGA systems, you will have one (or sometimes a few) master clocks. For example, consider this circuit

    This is essentially the same as the last circuit, but the D flip flop now has a clock that runs all the time. If a door managed to open and close faster than the clock period, the alarm would not trigger! Of course, if the clock were, say, 10 MHz, there would not be much chance of that really happening. The OR gate in front of the D flip flop makes it "stick" on. That is, once Q goes high, it will stay high until the reset forcibly turns it off.

    So what do flip flops do for you? 

    1) They give your circuit memory, like in the above example.

    2) They provide a fixed time for inputs to stabilize before producing an output. This is discussed more in the main portion of the tutorial.

    Flip flop "memory" allows you to create things like counters, registers, and state machines -- topics for future bootcamps.

  • Connecting I/O

    Al Williams06/23/2018 at 03:04 0 comments

    In the last bootcamp and this one, we've connected to things like LEDs and clocks. But how does Verilog know where those things are? The answer is right now, it doesn't. If you don't do anything, the tools will assign the pins anywhere it wants and since we already have a PCB with clocks on some pin and LEDs on some pins, that just won't do.

    The Verilog right now isn't being configured to go to the chip. So whatever names we decide on match up in the design and the testbench and that's fine. But in the next bootcamp that won't be good.

    Each tool has a slightly different way of handling things, and we'll talk about the tool we will use in the next bootcamp. But, in general, all tools will have some way to create constraints. Most tools can take lots of different kinds of constraints and one of them can be used to define I/O mappings.

    What's a constraint? Remember once your Verilog is processed, the tools will map what you have asked for into blocks the FPGA has and then figure out how to connect them together. A constraint tells the system something it must do during that process. Of interest to us now is to say "Hey, the signal called clk needs to be in an I/O buffer that connects to pin X." The router will be sure that happens as it juggles around trying to find the best way to lay out the design.

    There are other kinds of constraints. For example, you might tell the system that the timing between two points has to be no more than 20 nS, for example. Or that two blocks need to be put next to each other. That's pretty rare, but sometimes you need it. In particular, you will usually provide a clock constraint that will tell the tool the clock frequency you intend to use and it will tell you if you have delays that would cause problems. This is known as "not meeting timing" and we'll talk about it a lot in a future bootcamp.

    How do you set these constraints? That depends on the tools. Common tools will let you put special comments in the Verilog file or provide a text file with constraints in it. Some tools will have a GUI that can build or edit that text file, too -- some will have a few choices of GUIs.

    Again, we'll look at exactly how this works for the IceStick in the next bootcamp, but I wanted you to be aware of the necessity and importance of this no matter which tools you are using.

View all 3 project logs

  • 1
    ▇▇▇▇ Understand Synchronous Logic ▇▇▇▇

    Clocks are an important part of practical digital design. Suppose you have a two input AND gate. Then imagine both inputs go from zero to one, which should take the output from zero to one, also. On paper, that seems reasonable, but in real life, the two signals might not arrive at the same time. So there’s some small period of time where the output is “wrong.” For a single gate, this probably isn’t a big deal since the delay is probably minuscule. But the errors will add up and in a more complex circuit it would be easy to get glitches while the inputs to combinatorial gates change with different delays.

    The most common solution to this is to only “look” at the signals (and store them in a flip flop) on a clock edge (usually, just the rising edge). Now the circuit will work fine if the longest delay from one flip flop’s output to the next flip flop’s input is less than the period of the clock. This makes things much simpler to design.

    If you need a refresher on flip flops, they are elements that remember a single bit. A D flip flop will remember its input (named D) at the clock edge and hold that output until the next clock edge. There are other kinds of flip flops, like the T flip flop (which toggles state) or the JK flip flop which can perform several functions. With Verilog, you generally won’t create flip flops directly, but will let the compiler infer them from your code.

    Let’s jump right in with some examples. I’ll explain these each in more details as we go. Consider this code:

    reg myoutput;
    wire myinput;
    always @(posedge clk)
       myoutput<=myinput;

    This would infer a D type flip flop. 

    When the clock (the wedge-shaped symbol on the schematic) rises, the D input will appear on the Q output. The lower Q has a bar above it and will always be the inverse of the Q output.

    The compiler will recognize other types, too. For instance:

    reg myoutput;
    wire myinput;
    always @(posedge clk)
       myoutput<=myinput?~myoutput:myoutput;

    This would infer a T flip flop. Where Q toggles -- that is goes from 1 to 0 or 0 to 1 -- on each rising clock.  If you know C or a similar language, you probably know the ? operator and the ~ operator. If not, the ~ inverts all the bits. The ? operator is a bit trickier. You can think of it as an "if-then-else" construct. If the first part is true, the result is the expression between the question mark and the colon. Otherwise, the result is the part behind the colon. For example, the value of 4>3?2:1 would be 2 because 4 is greater than 3. If we had used 4<3?2:1 the value would be 1.

    Usually, though, the inference of a flip flop is not this direct. The input might be a logic expression. The compiler can also infer counters which are lots of flip flops:

    reg [3:0] ctr;
    always @(posedge clk)
    begin
      if (ctr_reset) ctr<=4'b0; else ctr<=ctr+1;
    end

    This code creates a 4 bit counter. On each clock edge it computes ctr+1 as the new count value unless ctr_reset is true.

    Just as using the plus operator allowed the Verilog compiler to do the best thing for an adder, the expression above will let it build an efficient counter without you having to worry about the details. You can build a counter out of individual modules that infer flip flops (or modules that your tool provides for you) but it is better to leave the details to the compiler.

  • 2
    ▇▇▇▇ Build a Flip Flop ▇▇▇▇

    The demo circuit has three distinct parts: the binary adder circuit from last time is already done. Another part of the example design is to provide an output that latches when a carry is generated. Here’s the part of the code that does that:

    reg carrylatch;
    // latch carry result
    always @(posedge clk)
    begin
       if (reset==1'b1) carrylatch<=1'b0;
       else begin
         if (carry) carrylatch<=1'b1;
       end
    end

    In English, this says that when the clock has a rising edge, check to see if the reset line is high. If it is, clear the carry latch. Otherwise, check to see if the carry is set and if so, set the carry latch. It will remain set until a reset clears it.

    The Verilog tool will recognize this is a flip flop with synchronous reset. If you get really concerned about performance, you may want to investigate if your FPGA does better with an asynchronous reset and learn how your tool can be told to do that instead. But for now, this is sufficient. The realization will probably be a D type flip flop with a rising edge-sensitive clock input and a clock enable tied to the carry line. The D input will be tied to a logic 1.

  • 3
    ▇▇▇▇ Key Point #2: Assignments ▇▇▇▇

    (By the way, if you are wondering where Key Point #1 is, it is in Bootcamp #1.)

    Did you notice that some assignments use = and some use <=? This is an important Verilog feature. When you are using assignments, you always use the equal sign. If you are writing a sequential block, you almost never want to use the single equal sign, even though Verilog will allow this. Here’s why:

    always @(posedge clk)
    begin
      a<=1’b1;
      b<=a;
    end

    Because the nonblocking assignment (<=) appears, the value of b will become whatever a was at the moment the clock edge occurred. That is, all the assignments in the block happen all at one time. In simulation, that means they happen at the end statement since simulations have to pretend everything happens in parallel. In an FPGA, parallel execution is just how the hardware works. 

    <=

    The problem occurs if you do not use a non-blocking assignment. Suppose we had:

    always @(posedge clk)
    begin
      a=1’b1;
      b=a;
    end

    The Verilog compiler is smart enough to know that b should equal 1 in this case and has to generate extra circuitry (a latch) to make sure b isn’t set at the same time as a. This can cause lots of timing issues and unless you are sure you need to do it and understand the ramifications, you should avoid it at all costs.

View all 8 instructions

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates