Introduction to FPGA Part 4 - Clocks and Procedural Assignments | Digi-Key Electronics

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
previously we saw how to create continuous assignment blocks in verilog this time we'll explore how the d flip flop in the fpgas logic cells can be used to create procedural code that executes sequentially let's get started [Music] if we look at the ice 40 data sheet for the lx and hx models we can see that there's another part of the logic cell that we have not discussed yet and that is the d flip flop this is a basic digital logic element made up of some transistors and probably some resistors it allows us to store one bit of information at a time between clock pulses as you can see in this diagram we can get our one bit input from the lookup table in each cell our clock signal can come from any number of sources we also have a reset pin as well as an enable pin that we can use to control the output the output of the cell can come from the d flip flop or you can bypass the flip flop using this multiplexer here's a simplified look at the d flip flop the idea is that we have a clock signal as one of our inputs whenever the d flip flop sees a rising edge on the clock also known as a positive edge it will sample the value on the input line if in is low then the output line will go low if in is high then the output line will go high the output line will stay that way until the next rising clock edge i left off the enable line as we won't use it in this episode the enable line is used to allow or prevent sampling on the clock edges if the enable line is high the flip-flop works the way i've shown here if the enable line is low the flip-flop will keep whatever value is on the output line regardless of what the input line does finally we have the reset line if reset ever goes high the output line will be driven low this can happen asynchronously meaning it does not need to happen on a clock edge the output line will stay low as long as reset is high even if there is a rising clock edge since the output line might be randomly high or low whenever the fpga is first initialized we can use the reset line to set an initial state for our flip-flops because of this you'll often see the same reset line connected to many different flip-flops we can combine the flip-flops and combinational logic to create any number of digital circuits for example we're going to create this 4-bit counter in verilog and test it on our fpga the full adder should look very similar if you did the challenge in the last episode note that we don't actually need to implement the adder as verilog supports some basic math symbols such as addition the synthesis tool will figure out the best logic needed to accomplish the goal of adding bits together which could be our full adder or it might be some other combinational logic we add flip flops to this logic so that on every positive clock edge one is added to our four bit number if we need to increment the next bit the carry outline is used to notify the next stage of the counter that it needs to increase its value by 1. you might notice that there's no initial value set on our output or q bus to do that we need to pulse the reset line in order to set the output to 0 which will start the counter over from the beginning here is the timing diagram for our 4-bit counter while the fpga will probably start the q0 through q3 lines as low whenever it first boots it's probably a good idea to not assume that they'll be low so we'll say that the lines are unknown until we give a reset pulse i'll put an x and draw the lines as both high and low as we don't know the actual state as soon as the reset line goes high the entire bus is set to 0. the q value is then incremented by 1 on each rising clock edge this allows us to create a counter from 0 to 15 using 4 lines and some digital logic when the output is 15 or binary 1 1 1 1 the next positive clock edge will cause the counter to reset or roll over back to zero counters are incredibly useful pieces of circuitry as they're used to time events or form the basis of pulse width modulation signals if you've worked with microcontrollers you've probably come across counters which can also be called timers they're pieces of hardware logic that operate almost exactly like this and they allow us to set up timed events that can occur at specific intervals without wasting cpu cycles we can also generate hardware interrupt signals that occur whenever the timer reaches a certain value or whenever that rollover event occurs let's see how to implement a 4-bit counter in verilog just like we've done before we want to go into the folder that contains our projects i'm going to create a new folder for our particular project that we're going to create i'm going to call it button counter let's go in here we're going to create our physical constraints file which i will call buttoncounter.pcf let's open that with notepad plus plus this pcf file should look just like the ones we created in the previous episode we're going to create a vector of led pins that are connected to the leds or in this case it's a bus it's a four bit wide bus and we're going to do the same with the two buttons specifically the ones attached to physical pins 78 and 79 we will create a bus or a vector out of those hence the array style notation let's save this file and we're going to create our verilog file we want to create a module that gets loaded onto our fpga and the idea is we want to be able to press a button and have it act as a clock in this case it's just going to count up every time we press a button and that count value is going to be displayed in binary on the leds we'll declare our button pins the pmod pins 0 and 1 to be inputs and those are going to act as the clock signals or the sensitivity signals and i'll show you what that means in a minute when we create our always block notice that i'm declaring the led pins as register pins and the reg or register keyword here tells the synthesis tool that we want to connect these lines to those d flip flops which means that it's going to be part of our procedural assignment when things are executed sequentially thanks to or due to the clock signals that come in to those flip flops the synthesis tool figures out how to connect everything together for us so we don't have to worry about the actual connections as we did previously we're going to declare a couple of wires here this is because we want to rename our buttons and pretend that our button signal or pressing a button is going to act like a clock signal where it's just going to toggle high and low although we get to control it with the button as well as the reset signal it's a good idea to have a common reset signal so that when you begin an always block or when an always block starts executing it may not know what state to put some of the variables in and we'll see that in just a second we want reset and clock to be active high essentially which is the opposite of how the buttons work we're going to do a continuous assignment where the signal of the first button goes through a not gate and that becomes the reset signal hence why we're naming the output of that that's the net or the wire in this case is known as reset just like we did with reset we're going to do the same thing for the clock signal we're just renaming the inverse of the second button we define our procedural block or procedural code using the always keyword anything within this block executes sequentially much like how a programming language like c or python would execute it's a little different but because signals can propagate through those d flip flops things happen in order we then need to define a sensitivity list which tells the hardware how the signals should propagate or when the signals should propagate and this is done through the use of clock signals or reset signals and it's looking for a rising or falling edge on those signals in order to execute what's underneath the or what's inside the always block the first case is we're going to define the positive edge so that's the rising edge of our clock signal in this case it's the opposite of a button push so the idea is when we push the button that counts as a rising edge because the signal's inverted always according to this assign line that we created here and that will execute anything within the always block i will point this out now note that because there is a lot of debounce on these simple push buttons you can expect this to execute multiple times per button push that's an expected behavior creating button debouncing is something you can do in an fpga and if you want another challenge i might recommend trying to figure out how to do button debouncing but that won't be the actual challenge for this episode we can have an always block execute based on the input of multiple signals in this case we can have a clock rising edge or a reset rising edge will cause this block to execute note that you can also do a negative edge if you would like to in this case we could do negative edge p mod 0 and we wouldn't need this line but i'm putting it here because a positive edge reset might be useful later on if you have multiple always blocks that need some kind of reset signal and you need it to propagate throughout your design to restart some of these blocks or put them in a default state the begin here kind of acts as a curly brace like you would see in something like c or c plus plus it shows the contents of the always block so we will write begin here then we will create an if statement this works very much like an if statement you've seen probably in c or python in this case our conditional is given in the parentheses if the reset signal is equal to 1 then what's underneath the if statement executes notice that constants can be a little weird in verilog you generally want to define the number of bits because this determines the number of lines or the number of wires that are needed to make this comparison in this case we only need one reset is going to be zero or one since it's one bit or one wire and then we say we're gonna define this in binary and this is one so this could be one b zero or 1b1 those are your only options for a one bit wide binary number so in this case we do want it to be one we're going to call begin and i'm going to indent under that to make it a little easier to read and here is our assignment going to our led bus or vector so if there is a reset signal that goes high in this case a button push then we want the four bit wide binary number zero in this case you could probably also write zero zero zero zero if you want it to be more explicit but zero works just fine that's going to be assigned or loaded into the led bus in this case we have four bits for led three through zero remember we declared this as a register so we can make this assignment and we use this special less than equals which does not mean less than equals it means this number is getting loaded into this bus so 0 0 0 0 which means all of the lines on our led array are going to go low we close out that if statement with end and just like you might expect we have an else statement and we would want to open that up again with begin so this is this is basically the equivalent of doing this but that syntax does not work in verilog so we do end else begin so if this block gets executed because the reset line went high then it should execute this first if part because the reset line is high or if this gets executed because the clock went high and you're still holding the reset line high in this case you're holding the button then 0 is just going to be continually loaded into this led bus however if the reset line is low in this case you're not pushing the button and clock goes high which for our cases is the other button then we want to increment the value on that bus so this value gets red one in this case a binary one gets added to that and that gets stored back into led that's part of the reason we use this style of assignment operator here is because this is all registered it's not like a wire where things happen continuously this would not work you'd be connecting a you'd be potentially connecting a low line to a high line and that's no good so we do this style of sequential or procedural assignment to say hey read this led value in which case it's the 4-bit value on this bus add 1 to it and then store it back into that value because it's all registered this works just fine note that plus works here the synthesis tool knows how to handle basic addition this means that the synthesis tool is capable of creating some type of adder circuitry to make this work and there are a number of different ways that it could implement this addition circuitry it may be the full adder that you designed as part of the last challenge or it might be something else but the synthesis tool knows what to do with plus and that's good to know it can create the logical circuitry necessary to do any number of arithmetic operations so keep that in mind and i recommend looking up some of the verilog syntax to see what kinds of operations it supports but remember a lot of it comes down to what the synthesis tool can support in this case addition is just fine we're going to close out our if else block and we're going to close out our always block you'll see here that we can combine continuous assignments which is creating some of those logic circuits as well as these procedural assignments into one functioning module that gets loaded onto our fpga let's save this we're going to open up our command prompt and i'm going to go into my button counter example that i just created i'm going to call appio init dash b to define the board and i stick that's going to create the initialization or ini file for us then we're going to tell it to build hopefully the synthesis tool works correctly and does not throw any errors and opio upload to send it to my istick that should be plugged in and on it looks like it uploaded so let's test it whenever the clock signal goes low the counter value increments i can also press the reset button to restart the counter notice that my counter might skip a few values whenever i press the button thanks to button debounce we won't worry about dealing with button debounce right now using a button as a clock signal seems a little silly but it was a useful demonstration if you look at the istick data sheet you can see that the board has a 12 megahertz oscillator this oscillator is connected to physical pin 21 on the fpga that should work as a much better clock signal you can give the clock signal a name in the pcf file just like we've done for all the other i o pins on the fpga this will give us a line that toggles at a rate of 12 megahertz your challenge is to create a clock divider for this line and use that to feed your counter instead of a push button the output of your divider should be a one hertz square wave so that your counter increments once per second as a hint you might need to create a second counter to accomplish this also note that you can have more than one always block in your verilog module i just want to tell you good luck we're all counting on you in the next episode we'll take a look at state machines happy hacking [Music] you
Info
Channel: Digi-Key
Views: 7,729
Rating: undefined out of 5
Keywords: fpga, lattice, ice40, yosys, apio, project icestorm, electronics, digital logic, verilog, hdl, procedural assignment
Id: LwQsyeuf9Sk
Channel Id: undefined
Length: 18min 9sec (1089 seconds)
Published: Mon Nov 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.