[myhdl-list] When to use @always, @instance and @always_comb
Brought to you by:
jandecaluwe
From: Christopher L. <loz...@fr...> - 2012-04-27 00:52:58
|
You can see the long term version of this page at: http://wiki.myhdlclass.com:8080/WhenToUse So I have a first draft of my floating point multiplier module, and I just wanted to make sure I am doing the modelling right. I find the best way to work with open source is to document it. Then people after me have an easier path, and the people who came before are quite happy to correct the documents, rather than let poor information hang out there. So here goes again. The different modelling options in MyHDL are very confusing. I get the idea of digital circuits as blocks that have inputs and outputs. But there are three different ways to represent them in MyHDL, @always(), @instance(), and @always_comb() Which should I use? It has to do with what the electrical engineers call sensitivity lists. When do you want the statements to run? If you want something that runs at well defined times, use the @always. So a clock driver would be on @always, or maybe something that runs with each positive edge of the clock signal. Or it runs on the basis of any other signals or signal edges you want it to be based on. Or things that run on regular delay intervals. There are other ways to accomplish the same sensitivity list, but that is the simplest. And sense the sensitivity list is in the @always statement, it should not have sensitivity lists in the yield statements. If you have combinatorial logic, and you want it to run whenever the logic changes, use @always_comb. It figure out by itself when to run based on the inputs to the module. And finally if you want to return changing sensitivity lists, use @instance. Then it can have different yield statements at different times. Having written this documentation, it helped me to figured out the solution to my problem. My floating point multiplier initially just needs to run when the start signal is given. Once it has started, it also needs to wait 14 clock cycles for the pipelined result to be returned. So I need to use the @instance, so I can change the sensitivity list as required. @always(args) This is a decorator. It turns the following function into a generator. The args can either be a delay, or a signal, or a positive or negative edge. No yield statement is required. In fact no yield statement is allowed. @instance() This is a simpler decorator. The decorated function has to be a generator already, meaning it has to have one or more yield statements. @always_comb() This is a decorator. It turns the following function into a generator. It figures out what the input signals are, and if any of them change, the function is executed. I was really surprised by the example in the documents that went statement 1 yield statement 2 yield If you think of yield like a return statement, that makes no sense. But yield is not a return statement, when the code generator picks up again, it just keeps running, so the multiple yield statements do make sense. Just hard to understand the first time I read it. The higher level approach is to model things as objects. There is a queue example in the docs. This stuff blows my mind. How that can be synthesized, what it means in terms of hardware functions, I really do not yet understand. Sure the queue example is easily understandable to a software engineer, but what does that look like when converted? Anyhow I hope that helps you. I am sure I got it wrong, but there is a process of writing, and people correcting it, that hopefully helps all concerned. -- Regards Christopher Lozinski Check out my iPhone apps TextFaster and EmailFaster http://textfaster.com Expect a paradigm shift. http://MyHDL.org |