What HDL to start with - Page 1
Forum section: electronics / general

author: JustClaire
author_rank: Contributor
timestamp: March 08, 2020, 06:43:27 am
content: Hello!I am a complete newbie to FPGAs and currently deciding which HDL to start with. So far i am deciding between the more popular VHDL or Verilog and something like MyHDL or SpinalHDL.Which one would you suggest based on the software & hardware support(IDEs, simulators, compilers, etc.) and ease of learning?Another major deciding factor for me is the cost of the software, i'd prefer free software as i am not ready to pay 500$ for a licensed copy of a development package.Thank you

author: OwO
author_rank: Super Contributor
timestamp: March 08, 2020, 07:35:50 am
content: Choice of language isn't as important as understanding the concepts of digital logic design. I would personally start with a traditional language (VHDL or SystemVerilog), and try the new stuff later when you are familiar with hardware design. The most important thing to remember is that designing FPGA logic is *not* writing software, it's designing a circuit. Your code should reflect that; it's basically just a fancy netlist.

author: JustClaire
author_rank: Contributor
timestamp: March 08, 2020, 09:59:14 am
content: Quote from: OwO on March 08, 2020, 07:35:50 amWhat software would you suggest to start with SystemVerilog?

author: mark03
author_rank: Frequent Contributor
timestamp: March 08, 2020, 04:27:41 pm
content: Quote from: JustClaire on March 08, 2020, 09:59:14 amWill you be learning "hands on" with an FPGA dev board? If so, the free version of Vivado (Xilinx) supports SystemVerilog, and I think the free version of Quartus (Altera/Intel) does too. If you want to start in pure simulation without an actual FPGA, those same tools have simulators built in. There is also the free Verilator which supports SystemVerilog.The trick with the Verilog "family" in particular is that it has been a moving target for 20+ years and, generally, the free tutorials and examples you find on the web will not be using SystemVerilog best practices. I can recommend Stuart Sutherland's book "RTL modeling with SystemVerilog for simulation and synthesis".Note that SystemVerilog is actually a huge language spec, most of which is irrelevant for synthesis and FPGA design. But the improvements to old-fashioned Verilog in the "synthesizable subset" are still significant.

author: JustClaire
author_rank: Contributor
timestamp: March 08, 2020, 04:40:36 pm
content: Quote from: mark03 on March 08, 2020, 04:27:41 pmI will most likely start only with simulation untill i get a dev board.Quote from: mark03 on March 08, 2020, 04:27:41 pmThank you, i will check it out!

author: nctnico
author_rank: Super Contributor
timestamp: March 08, 2020, 06:13:42 pm
content: Quote from: OwO on March 08, 2020, 07:35:50 amNO!!!If you go this route you'll be writing a lot of very bad and poorly maintainable code and achieve very little. I've seen this over and over. The trick is to understand how your code is translated into FPGA primitives. But other than that the most time efficient way is to treat writing FPGA exactly like you are writing software. And actually VHDL is more suitable for that compared to Verilog. The only exception are parts that need to meet critical timing but in most cases 99% of the FPGA logic isn't very time critical. It is kind of the trade-off between using C (treat as software problem) and assembly (think in hardware primitives). Modern synthesis tools are very capable of translating HDL into FPGA primitives. As the author you don't need to care.Just a simple example: instantiating blockram (on a Xilinx) versus declaring an array. An array is declared using one line of code, has an x number of bits and y depth. If the memory needs to be bigger (or smaller) then you only need to change y. The synthesizer/placer/router will figure out what kind of memory fits best so the code is very scalable. The memory depth can even be a parameter so if the module is universal (like a FIFO) some instantiations will use small memory blocks while other will use blockrams.Another good thing of VHDL are records (structs in C). Use these to combine related signals and pass these to modules as one variable. It saves writing a ton of code. Last but not least a common mistake in VHDL is to use a vector for signals which are a number. Use the signed and unsigned types; these are easy to use as indexes to arrays which again saves writing a lot of code. In one project I inherited the authors went as far as writing special Python scripts to generate VHDL code. Needless to say this is a very cumbersome way to achieve what they wanted AND they could have achieved the same if they used VHDL directly. Now the project is a convoluted mess with Python and VHDL. The bottom line is: try to make the HDL work for you. There will be a learning curve to go beyond average but there are great rewards.

author: asmi
author_rank: Super Contributor
timestamp: March 08, 2020, 09:01:02 pm
content: Quote from: nctnico on March 08, 2020, 06:13:42 pmThis approach only works if your goal is to design something that runs at 1 MHz. It will fail badly if you need your design to run at any decent frequency.Quote from: nctnico on March 08, 2020, 06:13:42 pmAnd how do you know that it's more suitable if you don't know SystemVerilog at all?Quote from: nctnico on March 08, 2020, 06:13:42 pmVHDL is going the way of dodo, just like Basic and Pascal are. No reason to bother with it.

author: mark03
author_rank: Frequent Contributor
timestamp: March 08, 2020, 09:18:53 pm
content: Quote from: rstofer on March 08, 2020, 08:53:19 pmThis may be true in a narrow sense, but I think it would be hard coming up with reasons to pick Verilog over SystemVerilog in the year 2020, unless you are stuck working with older tools like Xilinx ISE. Also, for the record (VHDL pun intended), some of the comments on Verilog vs VHDL are outdated. For example, SystemVerilog has structures and interfaces.More generally, there is a sort of deep-seated conservatism within the HDL world, which makes it slow to adopt improvements in languages, tools, and techniques. I saw this in previous workplaces, where just getting the FPGA guys to use mainstream source-control tools (git) was an uphill battle. You can also see it in Xilinx's choice of tcl (!), of all things, for the scripting language underlying their shiny new toolset. I think it just goes with the territory. Software people like to move fast and break things. Hardware people are deeply suspicious of change, because any breakage has a much higher cost in hardware.

author: nctnico
author_rank: Super Contributor
timestamp: March 08, 2020, 09:29:51 pm
content: Quote from: asmi on March 08, 2020, 09:01:02 pmThat is your opinion but I have been following the exact principle for almost 2 decades very succesfully in commercial projects running at the FPGA's intermediate frequency (the frequency where timing is not likely to become cricitical; IOW usually 99% of the logic running at several tens of MHz). Maybe you should just give it a try; you'll pre surprised how much you can achieve with very little code. Usually I need at least 5 times less lines of code to achieve the same compared to the average VHDL out there. And my solution is scalable on top of it without getting into trouble with timing. However I did invest the time to learn how VHDL language constructs are translated to FPGA primitives. You are making the C versus assembly argument all over again (and we already know the outcome of that).QuoteLooked into it but SystemVerilog is just the same old Verilog with some stuff from VHDL bolted onto it (note that I wrote Verilog BTW). There is still a lot of opportunity to shoot yourself in the foot. Not saying VHDL is perfect and irreplaceble but the strong types in VHDL and other language constructs are definitely a plus to catch errors which would be hard to find otherwise.

author: coldfiremc
author_rank: Regular Contributor
timestamp: March 08, 2020, 10:10:34 pm
content: Every time that system verilog gets an upgrade, it's a feature coming from VHDL. VHDL inference is a little more deterministic than verilog. Note that if you don't like "if it not compiles, is because is a nonsense" languages, VHDL is not your language. This appears to begineers as a "disadvantage", but there aren't debuggers in the same sense of software for HDL's, so if it compiles, you can't check check in the same way that the code you write is correct. Note that HDL debuggers are mostly paid.More code isn't always more work. There's lots of code snippets and templates for vhdl, so there's less need for manual writing.

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 12:40:24 am
content: Quote from: nctnico on March 08, 2020, 09:29:51 pmLol about 80% of my HDL IS timing-critical and is running at 150 MHz and above.Quote from: nctnico on March 08, 2020, 09:29:51 pmThe problem is the moment you get a timing error you're screwed because in most cases you won't be able to even tell what exactly caused it. Try to P&R any of your "software" code by setting a system clock to 150 MHz and see what happens.Quote from: nctnico on March 08, 2020, 09:29:51 pmThis is what I meant - you obviously have no idea what are you talking about, yet you're going on here like you do. You can make SystemVerilog almost just as type-safe as VHDL if you so desire.As for "stuff from VHDL bolted on" - care to show interfaces in VDHL, or inheritance, or modports? This is the stuff I use all the time. Infact, I would take SV just for interfaces as they make things SO much easier and cleaner. While you're getting buried under tons of stupid boilerplate code (port map? seriously? another copy-paste for absolutely zero reason).

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 12:44:21 am
content: Quote from: coldfiremc on March 08, 2020, 10:10:34 pmWhy is that VDHL users are so ignorant and arrogant?Quote from: coldfiremc on March 08, 2020, 10:10:34 pmLol. More USELESS boilerplate code is BAD because actual useful logic gets buried under that stupid boilerplate. There is a reason dynamically-typed languages are so popular nowadays, while super-strongly typed Pascal is as good as dead.

author: coldfiremc
author_rank: Regular Contributor
timestamp: March 09, 2020, 01:58:03 am
content: Quote from: asmi on March 09, 2020, 12:44:21 amPerhaps if you code to gate level, more text is a terrible thing, totally agree, also Verilog and SV tend to be lot better declaring logic explicitly. However if someone wants more behavioral-like code, languages that compel the programmer to write in certain "fixed" ways, make compilers/synthesizers behave more predictibly. Some V's are almost impossible to understand when some other people write code that tries to infer sequential stuff (Or yourself 3 months later). Fortunately SystemVerilog has some ways to avoid this mimicking some vhdl styles and avoids things like Port Map (Despite that I don't think is bad if you use helpers to code it).Also types must be evaluated sooner or later, and during simulation isn't a good time to do it. Spents time and generates LOTS of useless data until type is evaluated.

author: nctnico
author_rank: Super Contributor
timestamp: March 09, 2020, 11:51:43 am
content: Quote from: asmi on March 09, 2020, 12:40:24 amYour exception doesn't make the rule. And it isn't even certain that hand optimised code is actually much faster compared to letting the synthesizer deal with it. Compare it to the various optimisation levels a C compiler offers. Size versus speed for example. A HDL synthesizer offers similar settings including ignoring the hierarchy of your design and taking the hardware platform into account. The latter offers a scope of optimisation which is (like C) hard to achieve manually. You need to do something really really special in order to make hand-optimised code being cost effective (time/money spend versus cost of more capable hardware). Like any electronic part FPGAs do go obsolete and having code which can be used on a different platform without needing extensive rewrites can save a lot of time/money.

author: tggzzz
author_rank: Super Contributor
timestamp: March 09, 2020, 12:20:42 pm
content: My attitude is mixed...Sometimes I want a specific hardware primitive available in a specific logic family, e.g. when crossing clock domains or i/o structures (especially SERDES). In those cases I "manually" instantiate the specific primitives.Where designing a datapath, especially involving arithmetic, I'll adopt a programming language approach, giving the toolset as much information as possible about my use of the data in the datapath, e.g. signed/unsigned, width etc.Where designing the control and sequencing, I'll adopt an FSM style (frequently a "two process" register+async style), making the code as simple and readable as possible.But non-dogmatic good taste trumps all of those

author: OwO
author_rank: Super Contributor
timestamp: March 09, 2020, 12:23:31 pm
content: Actually no, the code I write in dataflow form is nearly always more concise and easy to read than the same thing implemented with processes. I did a survey of my VHDL code a while ago and the majority of modules are less than 200 lines total, with <100 lines in the body.For example, this is the universal, one-size-fits-all FIFO module I use in all designs:https://github.com/gabriel-tenma-white/axi-util/blob/master/dcfifo2.vhdThe body is only 80 lines of code. Looking at the code I can easily form a picture in my head, which consists of a RAM block, input logic, and output logic. I can see the state variables which are the registers (anything with rising_edge(clk)). I can see the read/write pointer registers, the logic that decides the next pointer value, the clock domain crossing that allows the read side to see the write pointer and vice versa.I find code reuse happening far more often in my hardware designs than software, which completely contradicts what most people who write behavioral code says:https://zipcpu.com/blog/2020/01/13/reuse.htmlThat blog entry even says reusing FIFO code is hard, which completely baffles the mind. As I said, in hardware I have a single FIFO implementation that I use everywhere, and when I need a new feature added (e.g. synchronous clear) I can easily add it to the module without interfering with existing users.Such is not the case in software; for example in one STM32 based project I had 3 FIFO implementations. One was thread safe (lockless) with multiple writers (producers-consumer queue) but can't handle big blocks of items (e.g. byte streams) efficiently, another was a ring buffer for stream data, and yet another was for zero-copy direct access appends. It's simply impossible to cover all these cases in a single implementation in the software world.

author: OwO
author_rank: Super Contributor
timestamp: March 09, 2020, 12:34:31 pm
content: And no, I do not write "low level" code that instantiates primitives. In fact I try to infer everything whenever possible including DSP units and block ram. I have a module called dsp48e1_multAdd that contains logic exactly describing what a dsp48e1 has in a certain mode, and it gets mapped to a dsp48e1 perfectly. If you try to synthesize this on another FPGA vendor it will actually still work but be non-optimal.Primitive instantiation is generally restricted to the top level module where I have the part-specific and board-specific clocking and IO structures. Everything else is supposed to be modular and self contained, which is natural in hardware, but good luck trying to write self-contained modules in C/C++. (I have tried, by using hooks/callbacks for all outgoing calls, but it has a performance penalty). For example, I'd like to have a completely generic si5351 driver that is not tied to a specific SPI driver or even platform. This is trivial in HDL, but impossible in software without performance penalties. To do that in C++ I used hooks (custom std::function that does not use dynamic allocation) for SPI calls.

author: nctnico
author_rank: Super Contributor
timestamp: March 09, 2020, 12:55:50 pm
content: Quote from: OwO on March 09, 2020, 12:34:31 pmBut why not simply use a <= b*c + d? The synthesizer will map this onto a DSP block just as fine. And in your fifo example: why not just do it like this (severaly stripped example from my own synchronous FIFO):type mem_type is array (g_size-1 downto 0) of std_logic_vector (g_data_width-1 downto 0);signal mem : mem_type;output <= mem(to_integer(rd_ptr)) ;mem(to_integer(wr_ptr)) <= inputMuch easier and the synthesizer can determine which kind of memory is most optimal to use given the size of the FIFO and available resources.But I agree with you in general: conditional / parametric synthesis is very powerfull to create truly versatile pieces of code. OTOH in C/C++ you'll end up with only one physical (as in memory filled with code) implementation of a function where in HDL each instantiation creates a seperate physical implementation. In C/C++ you might get close using polymorphism though.

author: OwO
author_rank: Super Contributor
timestamp: March 09, 2020, 01:37:31 pm
content: Quote from: nctnico on March 09, 2020, 12:55:50 pmYes that is what I did a long time ago, and then I realized there are 3 mandatory* registers: before the multiplier (a, b), after the multiplier, and after the adder. That also means the b,c to output delay is different from the d to output delay. I just find it more tidy to enclose all that in a module with the delays documented. Same thing with ram inference; I prefer to keep it in enclosed in one module so that if I happen to switch to a vendor that requires a different style of inference, it can be easily fixed.* the 3 pipeline registers in a DSP48E1 are required to run at the speeds advertised in the datasheet

author: emece67
author_rank: Frequent Contributor
timestamp: March 09, 2020, 03:06:11 pm
content: .

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 03:23:07 pm
content: Quote from: nctnico on March 09, 2020, 11:51:43 amYou're all over the place now. What does hardware obsolescence have to do with writing the code such that it reflects the circuit to be generated?Like I said - try running your "software" code at 150+ MHz and try to see if you'll even be able to figure out where to start fixing all timing violations, or it would be easier to just scrap the code as unfixable and write it anew.That said, I do use behavioral constructs when I know what circuit they create (things like add/sub, multiply, madd, shifts), and will know what do if I get a timing violation going through any of these paths. But it's important to always remember what's going on behind the scenes and don't do stupid stuff like chain arithmetic operations without pipeline registers - this is pretty much a guaranteed timing violation due to extremely long combinatorial chain it produces.I believe making HDLs feel so much like software languages has been a big disservice to this industry.

author: rstofer
author_rank: Super Contributor
timestamp: March 09, 2020, 04:11:48 pm
content: OP, I told you this would happen! It does every time the choice of languages is discussed.In the end, the chosen HDL just takes a high level description of some piece of hardware and maps it onto LUTs. The LUTs don't change, there are just so many in each device and they are generally identical across the device but there may be variations. To argue that one language is 'faster' than another seems more a statement of the quality of the compiler (and the skill of the compiler writer) rather than a credit to a specific language.The LUTs only work just so fast and if there are long serial strings of logic the maximum speed slows down. If you use an if-elsif-elsif-elsif-elsif-else type of priority encoder (where you really didn't mean for the logic to create a priority encoder) then, sure, it's going to be slower than if you get it done in 2 levels. When this happens, and the logic can't be rewritten, the only alternative is to force a pipeline with registers at various stages in the logic. This is the kind of thing that shows up in the RTL Schematic, you can see long strings of logic. Xilinx ISE used to report on the number of levels between registers, I haven't looked for it on Vivado but it is implicit in the Timing Report(s). But this only comes up if your design is too slow.You aren't going to need to worry about this any time soon. There is enough to learn without trying for ultimate speed and most anything you write will probably run at 100 MHz on the new Xilinx Artix 7 devices. Not blisering fast, but impressive.Pick a language, any language, the choice simply doesn't matter. Find tutorials that interest you and use the language used by the author. If you ever do this stuff for a living, you will probably need to be competent in all 3 languages because your employer is going to TELL you what language to use. It won't be up for negotiation because they will have their standard based on a decision made years before. So, start with any of the three and plan to learn the other two as time goes along.The important thing to realize is that your code ultimately gets transliterated into something digestible by a LUT or series of LUTs Further, there are certain types of logic blocks that show up constantly and the most important is the MUX because any time you are selecting from more than one signal, you will likely infer a MUX. Well, darn, there aren't any MUXes in the fabric, just LUTs. The synthesizer takes you expression of a MUX and maps it to LUTs and it doesn't make a bit of difference which language you started with, you will get a MUX inside LUTs. Registers are important but they are simply clocked signals which use the D-flop inside the CLB (see below). Combinatorial logic seems pretty important but, again, that just maps to LUTs and, ultimately, there will be Finite State Machines created in either a single process model or a two process model. Generally, it is your choice unless your employer says otherwise.So, you use some high level language to describe these high level logic blocks and the compiler maps the logic to LUTs and it doesn't make a bit of difference which language you use because, given equally talented compiler writers, the output that maps to the LUTs will be the same. You simply can't create hardware features that don't exist.Some languages have different features or flavors but, in the end, I would expect to be able to implement any logic in any language. It may take more or less typing but it should come out the same.Pick a language and get started.Technically, a LUT is but one part of a CLB (Complex Logic Block) of which there may be several in a Slice. See page 19 here:https://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdfAbove I used the term LUT rather expansively. In most cases CLB is more appropriate but when you look at synthesizer reports, they tend to talk about LUTs, not CLBs.

author: rstofer
author_rank: Super Contributor
timestamp: March 09, 2020, 04:18:54 pm
content: OP, look at page 7 here:http://users.ece.utexas.edu/~patt/05f.360N/handouts/360n.appC.pdfDo you see all the MUXes (plain trapezoids), well, once you know how to create one MUX, you know how to create them all.There is one adder for the Program Counter logic and an Arithmetic Logic Unit to perform the arithmetic/logical operations.The Register File is just an array of unsigned standard logic vectors, the SEXT are just combinatorial statuemtns to sign extend a value in the Instruction Register.All of this is just the datapath for a rather small RISC type processor. But look at the MUXes, they're all over the place!

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 04:59:31 pm
content: Quote from: OwO on March 09, 2020, 01:37:31 pmYou can write it in somewhat behavioral way and still take advantage of DSP pipeline registers because Vivado synthesizer is smart enough to do that for you if you white the code in certain way. I've already showed this example in the past here, so below code is mapped fully onto DSP tile, takes advantage of all pipeline registers and runs at Fmax for DSP tile (550 MHz for speed grade 2 Artix/Spartan-7):Code:module mul_dsp #(parameter WIDTH = 17) (input clk,input [WIDTH-1:0] arg0,input [WIDTH-1:0] arg1,output logic [2*WIDTH-1:0] result);bit [WIDTH-1:0] a0, a1;bit [2*WIDTH-1:0] res_pipe[0:1], res;always_ff @(posedge clk) begina0 <= arg0;a1 <= arg1;res_pipe <= a0 * a1;res_pipe <= res_pipe;res <= res_pipe;result <= res;endendmoduleAs you can see, it's easy to read and understand what's going on, and it perfectly maps to the hardware. Note there is an extra pipeline stage at the end to close IO timing (I did actually run it through P&R to confirm it works), in regular "internal" case it is not needed.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 09, 2020, 05:33:52 pm
content: Yup, remember the thread.Obviously the registering has to be explicit in some way in your code so the synthesis can infer a pipeline - otherwise it won't.

author: james_s
author_rank: Super Contributor
timestamp: March 09, 2020, 05:53:55 pm
content: Quote from: asmi on March 08, 2020, 09:01:02 pmVHDL is hugely popular in the hobbyist/open source circles, that right there is a reason to bother with it. Ultimately though the choice of language is virtually irrelevant, they all have the same capabilities, hardware that can be defined with one can be defined with another.To the OP:Regarding software, you are stuck with the software provided by the vendor for the part you are using.Your question is a bit like asking a group of people what religion to choose though, and you will also find that there are a handful of professional developers who do this for a living and cannot comprehend that the needs of a hobbyist are different than their own. Most of us who dabble in FPGAs are never going to be doing it as a real job so their adamant advice on what you "have" to do is irrelevant.

author: tggzzz
author_rank: Super Contributor
timestamp: March 09, 2020, 09:09:05 pm
content: Quote from: asmi on March 09, 2020, 04:59:31 pmI'll be heretical and ask...What's the advantage if you have to write the code in a certain way to make it fit onto one specific hardware block?Why not just instantiate the block directly?That would, arguably, very explicitly indicate the intention.It would, arguably, not lose any portability or reusability - if the specific hardware block is not available then the specially crafted code would probably have to be rewritten anyway.

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 09:19:18 pm
content: Quote from: tggzzz on March 09, 2020, 09:09:05 pm1. It will still work on different architectures, even though at much lower Fmax.2. It allows using sims which don't know what DSP48E1 is (for example Verilator) for behavioral simulations.3. It is much more clear in what it does, while DSP can do many things, and figuring out what exactly it's set to do at specific instantiation is not trivial unless you specialize on DSP and so memorized all opcodes and config options.3. It's much less code and so it's easier to read. Code is read much more often than it is written, so maintaining readability is very important.

author: tggzzz
author_rank: Super Contributor
timestamp: March 09, 2020, 09:52:44 pm
content: Quote from: asmi on March 09, 2020, 09:19:18 pm1: accepted, but ugh!2: not clear that is a benefit3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.4: readability is very important, but it is arguable whether it is more readable. N.B. it = crafted code plus synthesiser plus logic family blocks.

author: jmelson
author_rank: Super Contributor
timestamp: March 09, 2020, 10:24:49 pm
content: Quote from: nctnico on March 08, 2020, 09:29:51 pmRight, some years ago I did a project where almost all of the FPGA was running at 150 MHz on a Spartan 3A, and it could have gone faster. All pretty simple VHDL.Jon

author: asmi
author_rank: Super Contributor
timestamp: March 09, 2020, 11:59:57 pm
content: Quote from: tggzzz on March 09, 2020, 09:52:44 pmWhat's so unclear in this code? It shows exactly what's happening inside DSP tile (the only simplification is about pipeline register right after multiplication). You can't possibly claim it's "assembly code" vs "C code" situation.Quote from: tggzzz on March 09, 2020, 09:52:44 pmTo me there is no argument as I tried both approaches before settled on one I use today. But you can prove me wrong and show me a better way of doing the same, that works as good as my code (meaning still hits Fmax).

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 12:13:25 am
content: Quote from: tggzzz on March 09, 2020, 09:52:44 pmWell, at some point you need to be aware of the limitations of the underlying hardware. However the patterns to be used are well explained in Xilinx' documentation (synthesizer manual). Ofcourse the more hardware specific your code gets, the more difficult it will be to make the code portable. Still writing a=b*c +d (for example) is much cleaner compared to instantiating a primitve (which usually requires reading how it works to instantiate it correctly).

author: rstofer
author_rank: Super Contributor
timestamp: March 10, 2020, 03:30:19 am
content: Quote from: asmi on March 09, 2020, 04:59:31 pmI haven't had occasion to write code like that, I'm not even sure I would think of it. It's elegant!

author: tggzzz
author_rank: Super Contributor
timestamp: March 10, 2020, 06:45:50 am
content: Quote from: asmi on March 09, 2020, 11:59:57 pmIt was a general observation applicable to the general approach, not specific to one example.It is always possible to choose an example to justify any contention.I'll restate a point I made in an earlier post: "But non-dogmatic good taste trumps all of those [earlier points]".

author: tggzzz
author_rank: Super Contributor
timestamp: March 10, 2020, 06:48:58 am
content: Quote from: nctnico on March 10, 2020, 12:13:25 amAgreed. There is a balance to be struck, and good taste is important.I'll note the comment I made in an earlier post: "Where designing a datapath, especially involving arithmetic, I'll adopt a programming language approach, giving the toolset as much information as possible about my use of the data in the datapath, e.g. signed/unsigned, width etc."

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 11:16:24 am
content: Quote from: tggzzz on March 10, 2020, 06:48:58 amThat is a good comment. It is also an area where you can get stuck if you take the wrong exit when using VHDL. In a lot of VHDL code you see std_logic_vector being used for signals which are a number. Once you want to use a std_logic_vector as a number you have to do a horrific amount of casting and the strong typing of VHDL gets in the way. But the problem isn't VHDL, the problem is the person who is writing the code.

author: tggzzz
author_rank: Super Contributor
timestamp: March 10, 2020, 11:59:14 am
content: Quote from: nctnico on March 10, 2020, 11:16:24 amAgreed.Except in standard well-understood use-cases, casting is an orange flag that something is wrong.It is usually beneficial to occasionally examine a compiler's/synthesiser's output to see that you haven't missed something significant. But needing to do that frequently is an orange flag.

author: free_electron
author_rank: Super Contributor
timestamp: March 10, 2020, 01:30:01 pm
content: Verilog was designed from the getgo to produce digital logic.VHDL is a generic hardware description language. You could even describe a nut and bolt or screwdriver with it. For logic you use the logic librariessystemverilog solves a number of 'perceived issues' ( like latch inferrence ) by providing constructs like always_ff and always_comb , but overall makes coding simpler.The big thing is : learn how a logic synthesizer works and use it ! There is a very good book by Bhasker :https://www.amazon.com/Verilog-HDL-Synthesis-Practical-Primer/dp/0965039153There is a difference between writing verilog ( or vhdl) and verilog (or vhdl) for SYNTHESIS ( fpga/ asic). Sure you can model things very high level , but the generated output will be horrible in terms of performance and logic size.One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.It solves many problems , and it tells you EXACTLY what the synthesizer is going to build. I've written multimillion gate logic designs that were first-time right. No need to simulate it even. Synthesize and go ( this involved bus arbiters between two cpu's , memory and a whole bunch of accelerator logic. Some of that system sits in every harddisk produced.I see so much code with if-then else constructions that are unneeded, unterminated (missing cases) , do not cover all possible pathways and create 'unwanted states'. That all could be solved if you just learn how a synthesizer works.Here goes a short description:To convert your list of instructions (which are sequential in nature ) to logic the synthesizer needs to build a 'cloud' of , let's call it 'command logic'. You tell it what you want a block to do and the synthesizer converts that in a bunch of combinatorial logic that will control a register. Doesn't matter what you are building. A counter, a memory , a shifter , a lookup table, a comparator, or even if this block is registered (flipflops) or combinatorial (and/or/not)The synthesizer builds logic on-the-fly. It reads a line of code and drops down a bunch of gates/flipflops , then it evaluates the next line and does this again. At the end of the command list it runs a logic minimization algorithm that compresses the combinatorial stuff to the least amount of gates. This is NOT necessarily the final output. Depending on your target architecture (fpga or asic) the gates may or may not exist and logic may need to be 'expanded' again to fit what is available. ( your selected device may not have a 8 input AND gate and one will have to be built using two 4 input and gates and one 2 input and gate, the device compiler takes care of that, none of your worries, except timing wise )let's look at an example:build me a 4 bit counter.- it needs a system_reset, reset , a preset , a parallel load , a count up/down control, an enable 4 inputs and 4 outputs. And a clk of course.- the system_reset should work always, irrespective of any other control line.- the reset,preset,load,up/down are tied to the 'enable' signal. if the counter is not enabled nothing is to happen.- reset takes priority ,followed by preset , and load (meaning if more than one signal is active , reset has the highest 'weight'. if both reset and load commands arrive at the same time : reset wins.)- updown zero means count down, if one : count upCode:always_ff(@ posedge clk) beginif (enable) begincount <= count-1;if (updown) count <= count+1;if (load) count <=data_in;if (preset) count <=4'd9;if (reset) count <=0;end;if(system_reset) count <=0;end;Let's analyse this a bit:always_ff : i need flipflops here. Don't muck around with other constructs. You tell the compiler explicitly that it must create register logic, so there is no wiggle room for interpretation.@ posedge clk : and we will perform operations based on the rising edge of a clock signal.if(enable) : look at the enable signal : if it is high, process the attached list of commandscount <=count-1 : wait, what ? why do you do this. well here is the thing, i am using the synthesizer to my advantage here by writing so called 'scheduled' logic ( this comes down to the statement that 'statements will be executed in the order they are given' )I Tell the synthesizer : schedule (prepare) to count down.The next statement says "if updown count <= count +1". so now i tell the synthesizer : if updown is active : count up .What is going on here ? ( and this is the KEY difference between software languages and hardware languages. once you grasp this , you can do anything you want. )You will no doubt have had people tell you 'everything happens in parallel in an fpga . Well, it does , but that does not mean there is no 'order' ! there is : the order in which the statements are written !in software this would happen :count <=count -1 // we subtract oneif(enable) count <= count+1 ' if enabled we add oneso, if count was 3, we end up with either 2 (enable=0) or 3 (enable=1, we subtracted 1 (3-1=2), then added one 2+1 = 3In logic that does NOT happen. You end up with 2 or 4 why ? Because of how a synthesizer works. And now i need to switch to a graphic representation of how a synthesizer 'builds' logic. Take a look at the attached picture.The synthesizer starts reading your instruction list. The first thing it encounters is always_ff (posedge clk)So, it drops down a register and attaches the clock to CLK. Since the synthesizer does not know what comes next , it attaches the output (count) to the input. We don't want any dangling lines ...So whenever a CLK happens the register simply stores its own output. No data is corrupted.Now it sees 'if(enable) {list of instructions} (second image down)So the synthesizer injects a multiplexer ( the trapezoid thingie) under control of ENABLE. If ENABLE =0 then COUNT is connected to the data input of the flipflops, if ENABLE =1 then the list {} is connected to the data input of the flipflops.A multiplexer is nothing but a switch under control of a signal. Such a switch in Boolean logic is a very simple equation : out = (in0 and not(enable)) or (in1 and enable) : two and gates, an inverter and an or gate.Note : the list is represented by the yellow box.Now the synthesizer sees : count <= count -1, so it drops a logic subtractor circuit in place.The next statement says : if (updown) count up. So it injects another multiplexer , under control of UPDOWN , that switches between what it already had (count down) , and the new command (count up).The next statement says if LOAD then we need to take in DATA_IN , so we drop another multiplexer that switches between everything that came before , and the now operation.This is the key thing to remember: you switch between WHAT CAME BEFORE and the NEW statement. The ORDER IN WHICH INSTRUCTIONS ARE GIVEN.Yes, all that stuff happens in parallel, the adding, subtracting , loading , but it happens IN THE ORDER IT IS GIVEN. So the LOAD has a higher priority than anything that came before. It doesn't matter what state up-down is in, or what the count value is incremented or decremented , if LOAD is active then we will take in DATA_IN.The synthesizer keeps on reading statements and dropping multiplexers : one for preset , one for reset. Every new statement has a HIGHER priority than what came before. So you will never get a conflict of interest. We have two signals active.. how do we decide ? We need if then else ... no you don't it follows the order given. If you write if-then-else statements there is a risk you forget to specify certain conditions. As we cannot have 'floating' lines ,the synthesizer will tie those 'forgotten' pathways' to something ( and that is not always what you might think it is ... ) and then you end up with logic that does weird things if a state is encountered that was not covered.By using scheduling as i describe it here there are no undefined states in the logic. You know exactly what is described and in what order of priority.now, we have come to the end of the begin..end block so the synthesizer considers this block as 'closed and it goes back to the if(enable) multiplexer if build the very first.The next statement says if system_reset ... so we get another multiplexer under control of that signal. If this signal is active, it doesn't matter what came before as instructions: that entire block is cut off by the multiplexer.So now the synthesizer has a chunk of logic built form multiplexers, input signals and operators such as + and - . This entire 'cloud' of logic is nothing but and,or and not gates. So one huge boolean expression that can be minimized very quickly and efficiently.The truth table is complete, there are no undefined states in the table because if the scheduling principle.If you tried to build the table using if-then elseif or switch case statements , there is a risk you have undefined states. in a switch case you can specify a DEFAULT state that enures the undefined states fall back to this state. With if-then,elseif,else statements you have to be careful to cover all possible combinations. Also ,when someone comes back and say : we want preset to take priority over reset you have carefully alter a complex if-then else cluster. with scheduled logic : move that statement one line below so it gets higher priority.Now, there are going to be people that will tell you ' this is nonsense' , this is not 'how it is done', or 'how can you be sure the compiler works that way' and many other things. Don't listen to them.The compiler ? there is such a thing as a STANDARD (vhdl, verilog,systemverilog). And this scheduling is PART of all these standards. All the synthesizers work this way ( there really is only one way to translate a list of statements into a cloud of logic and that is the way i described it : inject multiplexers under control of signals, that switches the datapath around. Then minimize that logic into a truth table. This gives the fastest and smallest implementation. All the synthesizers i know (alteray, xilinx, lattice, cypress, Synopsys ) all respect the standard.As for this 'is nonsense' or this is 'not how it is done': i've worked with silicon for 23 years and did many complex designs, some of which sit in ADSL/VDSL modems and central office equipment , some of which sit in almost any harddisk that was produced in the last 15 years and controls the motors and positions the heads. And that logic was built exactly the way i described it above. Using scheduling.Learn this principle, and use it to your advantage. You will write more concise code, without undefined states, that is easier to maintain/modify when priorities change.Block level simulation ? Virtually not needed.High level (system level), yes.Timing , yes.Functionally (does it do what i intend it to do) , no. There is no 'wiggle room' or undefined path.

author: laugensalm
author_rank: Regular Contributor
timestamp: March 10, 2020, 01:33:31 pm
content: Quote from: james_s on March 09, 2020, 05:53:55 pmIt's not just popular, it will never disappear in a certain (not just niche) market, where safety and proper functionality coverage is relevant and lazy hacking not an option. And choice of language is not irrelevant when aiming at functional safety or portability, Im afraid.For the beginner, I would summarize my experiences with HDL as follows:Verilog: Less to write, more 'main stream', but: implicit effects can be a real pain (and things can go seriously wrong in silicon, too). Can encourage a lot of 'lazy coding'VHDL: a lot to write/copy paste, very verbose, strict and picky, but always explicit (unless you use std_logic_arith or other broken libraries)Python/MyHDL: Very nice concept, little code to write, converts to Verilog/VHDL nicely. Has a few sticky bugs, and may appear orphaned and little maintained but in fact has my best 'reusability score'.Python/nmigen: Quite a hack, but 'main stream' on the Python HDL side. Pros: Big IP core library, integration with opensource synthesis advancedUnfortunately, none of these is a true description language, although some people will keep repeating that to you and point at that 'D' in VHDL. They are all programming languages, trying to describe hardware. That's what makes them problematic with respect to early design rules, so, as mentioned, you might spend a lot of time trying to find out what is synthesizeable into primitives, and how.And unfortunately, many concepts are broken by design, so let's not go further into niche languages.If you just want to focus on developing logic and functional testing, you can become very effective using the Python approaches, but you still should be able to read Verilog/VHDL for debugging purposes, like the situation C++ <-> Assembly. You can never trust the tools, but at least some of them are free/open tools. And for synthesis, you can learn a lot with yosys and obtain usable results on various FPGAs, while being able to verify the innards with proven simulation tools.

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 01:45:48 pm
content: Quote from: free_electron on March 10, 2020, 01:30:01 pmAnd for a good reason. Logic is supposed to be parallel and now suddenly the order of statements starts to matter. Sure the standard has to define what to do in such a case but it doesn't make it a good practise (similar to many obscure & obfusticated things you can do in C). There are so many ways to shoot yourself in the foot with your proposed way of working that people aren't using it. When writing code always make sure someone fresh from school can understand it and make modifications without tearing the whole thing down by introducing subtle errors. Code needs to be as self-explainatory as possible.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 10, 2020, 02:13:23 pm
content: Quote from: nctnico on March 10, 2020, 01:45:48 pmThe order matters when you are re-assigning the same signals in several statements. If not, it doesn't matter.It also does if you're using variables.Some people never write code like this - because they think it looks sloppy - and some will make use of this to write more compact code. Your call.Such as:Code:a <= (others => '0');(...)if xxx thena <= b;end if;In this trivial piece of code, obviously the equivalent would be:Code:if xxx thena <= b;elsea <= (others => '0');end if;In less trivial examples, the savings in terms of code can be substantial. Again it's up to you and/or the rules you have to comply with.

author: free_electron
author_rank: Super Contributor
timestamp: March 10, 2020, 02:15:04 pm
content: Quote from: nctnico on March 10, 2020, 01:45:48 pmYou haven't understood is at all.Logic IS parallel but there is still an ORDER in which it executes. That is imperative due to the nature of the synthesis process.One way to create order is by using case and if-then-else clauses. But there is a risk you do not cover all possible cases.By using the built in order mechanism (scheduling) you avoid all this. Do not treat logic design as code design ! Logic is building truth tables to drive operations. And your truth tables need to be complete or they become 'maybe' and 'sometimes' tables... with unpredictable results. Use the scheduling that is built in the standard and you avoid all these issues. your logic becomes fully deterministic and without unintentional pathways. There is also no endless nesting of if-then-else clauses that becomes unmanageable

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 02:21:13 pm
content: Quote from: free_electron on March 10, 2020, 02:15:04 pmI understand it perfectly but it results in code which does something else than it suggests at first sight. That is a big problem to get less experienced people to work on a project in a productive way. The problem is not the code but the logistics of keeping code maintainable by as many people as possible. Unless ofcourse you want to maintain your own code until the end of time. And what if you look at your own code after having not used HDL for a long time? Or switched to an HDL which works differently? You'll be in trouble for sure!

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 02:29:11 pm
content: Quote from: SiliconWizard on March 10, 2020, 02:13:23 pmI always use the way from the snippet because it shows exactly what is supposed to happen and keeps the places where (in this case) a is modified in well defined areas. Aks yourself what happens if you merge the code and a line gets shuffled around by the version management system? Or someone shuffles a few lines around? And sure in more complex logic it may require a bit more thinking on how to organise your code. At some point a case statement may be better suited compared to a whole bunch of nested ifs. Maybe use a state variable instead of several seperate signals. Or create a function. IOW: the typical trade-offs when writing software in any programming language to create simple code and improve readability.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 10, 2020, 02:34:46 pm
content: Quote from: nctnico on March 10, 2020, 02:29:11 pmThere could be counter-examples where the first version would actually lead to less bugs in case of code modification: you have an explicit "default" value for the signal (all zeroes), and only assign it to something else in specific cases... so that doesn't necessarily introduce more bugs than the second, and could in some cases introduce potentially fewer.As I said, some people will make it a rule not to do this - you seem to be part of them - and it's fine.But knowing the language rules is still an important thing, and I think you should know them perfectly even when you choose not to use some constructs.As to variables, they should essentially be seen as placeholders, and not at all as variables in the software programming sense. Once you grasp that, they become trivial to use, and are handy to avoid unncessary code duplication.

author: OwO
author_rank: Super Contributor
timestamp: March 10, 2020, 03:09:40 pm
content: My way would be:Code:a <= b when xxx else(others=>'0');The only complaint I have is that VHDL doesn't have a mux construct like:Quoteand would error out if not all cases are covered.I *really* do not like the concept of conditionals (if/else) in hardware because it is completely unphysical; you can not swap hardware in and out depending on a condition; the hardware is always there. You can only use a mux to select which output to use, so I'd like this to be explicit.I think the overall structure of the hardware is something that must be explicitly spelled out; for example, an adder that supports dynamic add/subtract selection is not the same as one adder and one subtractor with a mux to select between the two. Although VHDL and verilog do not allow you to distinguish the two, the synthesizer generally does the right thing if the add/subtract selection is by itself (res <= a+b when sub='0' else a-b;). In my experience vivado will generate suboptimal logic if you have it as part of a longer conditional with more cases.

author: asmi
author_rank: Super Contributor
timestamp: March 10, 2020, 03:22:29 pm
content: Quote from: SiliconWizard on March 10, 2020, 02:34:46 pmI actually prefer this way because this way it is guaranteed to be a default option, while in complex control structures what may seem like a default branch may not actually be that. Good news is at least Vivado synthesis issues a warning each time you have not covered all possible cases. Using SV's modifiers (priority/unique if/case, always_ff/_comb/_latch) helps to convey your intent to synthesizer so that it can check if assumptions you make are actually valid and again will issue a warning is something isn't right.Quote from: SiliconWizard on March 10, 2020, 02:34:46 pmIn my experience, the hardest concept of HDL to grasp is a wire. It's somewhat similar to pointer or reference in high-level programming languages, but it's more powerful in a sense that it can "point" to different places depending on some conditions. To those who understand wires it's all very obvious, but it's kind of hard to explain to someone who doesn't understand it yet. I had my own share of issues in code because I didn't fully understand this concept.

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 04:38:18 pm
content: Just some quick food for thought on defaults: on the upside the value is always defined (likely 0) but the downside is that it limits the logic optimisation and this can result in needing a larger amount of logic than strictly necessary.Take a register in a peripheral for example. Does it matter if you read back 0 in unused bits or can they be an unspecified value?

author: free_electron
author_rank: Super Contributor
timestamp: March 10, 2020, 05:36:00 pm
content: Quote from: nctnico on March 10, 2020, 04:38:18 pmThey should be hard set to 0 or 1, not left with 'garbage' depending on which way the wind blows.Why ? let's assume the 'other guy' that has to read that register (the programmer writing some C code on the cpu that will access this register) has cast this variable as an INT.If that MSB randomly flips to 1 you just read a NEGATIVE number from the register ... Let's say this is an ADC with 10 bits mapped into a 16 bit register . You are going to create massive issues down the line. Especially if this ADC is signed ! ( you would have to map bit 10 onto bit 15 and the other would contain 'garbage' .. good luck filtering that in software. you now have to dick around with a bunch of data sanitizing because the logic designer was too lazy to lock those bits. If i were to encounter a chip that does shit like that i would fire the engineer on the spot !There is no such thing as 'undefined' bits. It does not cost additional logic to return zeroes (or ones) for unused bits. That is a misconception ! logic is not generated out of clouds of and,or,not gates. It is generated out of LUT's : look-up-tables. Basically roms. Whether you use them or not : it consumes the same amount of LUTS. So have a 'Default' statement. It populates all undefined states with whatever you specified , as opposed to leave it random. It is only a bit more work for the synthesizer to fill the table.During minimisation, the flipflops that never alter state ( yes, the synthesiser can spot that ) are not even instantiated. They are replaced with a hard zero or hard one.The reason for using LUT's and not random cloud logic is that , for a given size of LUT the propagation time is a constant. It does not matter what line in the rom you select. the time from change to output is a constant. With random clouds of logic , depending on the state, the chain may be shorter or longer. this leads to race conditions and immense trouble doing timing analysis and timing closure. A rom based lut does not have this issue. But,but,but having such a decoder takes up silicon space too. All those and/or/gates to make a 4 to 16 decoder to select the table... wrong ! in reality such decoders are not made using 'logic' gates , they are made using selectors ( basically one transistor ).two to 4 decoder using selectors (SEE IMAGE)for every additional input you need 1 inverter and a set of p-mos (or PNP's). the outputs of the selectors are used to 'power' the mosfets in the rom. they drive (for zero) , or do not drive (for 1) the gate of the selected rows. so every rom cell is also a single transistor. in an fpga this cell is loadable by precharging the gate during loading of the bitmap. In an asic this stuff becomes a diode matrix.See where this is headed ? For many things on silicon you have to let go of this notion of and,or,not and stuff. it's all selectors and diode matrixes. It is much faster, much smaller, and timing deterministic. the speed of selection is purely given by how fast you can turn on that transistor ( or switch it off ). the only true Delay is the switch delay of the selector + the delay in the inverter ( which you have one per control line ) so this entire hoopla , no matter how many inputs, has a propagation delay of maximum two transistor delays.you can chain hundreds of mosfets if you want.Same way many flipflops are actually a chain of inverters. They simply dope the channel of the mosfets in the second inverter to be very weak (relatively high-ohmic) so it can be 'overdriven'. need a clock ? that's a pass transistor cutting off the input.a multiplexer ? that's an n-p pair.

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 05:43:32 pm
content: But did it occur to you that having a default may need to use more inputs than a LUT has and therefore can introduce extra logic? In the end the default condition is based on a combination of inputs and the relevant output states depend on a combination of inputs. Together this can result in the output depending on more inputs than strictly necessary. And LUTs have a limited amount of inputs so the less inputs an output relies on, the less LUTs need to be cascaded.But as I wrote: having defaults is a situation specific trade-off.Regarding your ADC example: in such a case (2's complement data out) you'd left align the result and leave the bottom bits undefined. Otherwise it won't even work because you have to extend the sign bit to the unused bits to get the right result. BTW... just checked an NXP datasheet for an LPC1700 microcontroller: unused (bottom) ADC data bits are undefined.

author: free_electron
author_rank: Super Contributor
timestamp: March 10, 2020, 06:10:16 pm
content: Quote from: nctnico on March 10, 2020, 05:43:32 pmyou were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.and yes you do need to do a sign extention by stuffing the unused bits with '1'as for undefined in nxp : i wouldn't touch those with a 10 mile long pole. so how do they handle signed values if they have undefined bits ? i guess their devices are so poor they can't even do signed a/d.this kind of sloppyness leads to extremely difficult to debug issues. Lock down stuff that is unused. There should be no 'mystery states' in a design. People will get killed.Go read up about the people that were radiated to death by a cancer treatment machine because of sloppy coding int he control logic. the Therac-25 incident.. Caused by 'undefined states' in the control logic that allowed the machine to radiate patient with max dose . (anything that was not defined yielded 'max dosage' )it's the same concept as in writing code: initialize your variables. you do not know what that memory location was used for, before.

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 06:30:57 pm
content: Quote from: free_electron on March 10, 2020, 06:10:16 pmOfcourse it does! If you have 7 input signals then you'll need to cascade two 4 or 5 input LUTs to get the result. This will cost extra logic, routing resources and adds delay to the path. There is no magic way around that.

author: free_electron
author_rank: Super Contributor
timestamp: March 10, 2020, 07:22:43 pm
content: Quote from: nctnico on March 10, 2020, 06:30:57 pmYes, you will be consuming one additional lut. So what ? You will be consuming that LUT whether it is initialized or not. The interconnect is already part of the raceways in the fpga fabric , so that doesn't cost anything , nor does it add delay (like i said : switching and decoding in an FPGA , of which the raceways are part, is delayless between in and out. There is a setup time , but once the connection is made there is no delay as it is simply the drain-source channel) . A wider lut does not add setup delay as the delay is purely based on transistor switching time , which is a constant in a lut, irrespective of what combination. you have one inverter to pass and one selector gate so two transistor switch delays. Doesn't matter if it is one lut , two chained luts (wider inputs). it is only important for cascaded ( more outputs) as there you need subswitching and need to put luts behind luts, but even then you incur virtually nothing as the synthesizer use one lut to do a global enable on the cascaded ones. So you get the first one for free. You only get hit by 2 more transistor delays.And again, it doesn't matter if you hard lock the states or 'don;t care'. the cells are there anyway. it's not like you can erase them. if a lut is half used it is spent. you may as well use it completely by stuffing it.in short : lock down the states !. Just like you initialize variables in a program. If you can't be bothered to do initialization you are an idiot and should take up a different job , like painting the lines for parking spaces.

author: nctnico
author_rank: Super Contributor
timestamp: March 10, 2020, 07:37:00 pm
content: Quote from: free_electron on March 10, 2020, 07:22:43 pmThe whole point is to avoid needing 7 input signals if possible. If you avoid needing that extra LUT by not having a default you'll need less FPGA resources, have shorter delays and thus have a better chance on meeting timing / fitting the design in an FPGA. Whether you need initialised values or not is a functional design decision. Sometimes it will matter, sometimes not and sometimes you'll have to compromise in order to meet timing requirements. There is no general rule (whether you like it or not). This also circles back to code style in general. If you have a whole flurry of nested ifs (which is poor coding style because the purpose is lost quickly) then it is very likely a case / state machine approach is better suited to have better code clarity. A case / statemachine approach will also allow the synthesizer to choose between various encodings (number or one-hot) in order to get to the most optimal result. In the end the resulting hardware implementation may even be better compared to the nested if statements.Also in most (digital) semiconductor devices you'll see that unused bits have undefined values. So appearantly your statement that default values come for free is false.But this is getting wildly off-topic.

author: mrflibble
author_rank: Super Contributor
timestamp: March 10, 2020, 11:48:53 pm
content: I'll just quote it in full so we don't get any of that quoted-out-of-context nonsense...Quote from: nctnico on March 10, 2020, 07:37:00 pm*edit*Okay, before I write waay too much based something thatcouldbe a misunderstanding... Lets just verify that what you mean is what I think you mean. Because, that which I think you mean is ... uhm, "not entirely accurate" would be the polite way of putting it. Less subtle would be "that is a load of shit, and it can be mathematically proven that it is a load of shit". It is in fact such a load of shit, that I honestly think that I must have misunderstood, because how the fuck can someone come to that conclusion. But then again ... three posts all of which are consistent with "that which is meant" is just not true. And these same three posts are not consistent with "that which is actually happening in real actual synthesizers made by real actual companies selling real actual FPGAs".What I think you mean is:blackbox/module/whatever with 7 inputs. As per discussion one of the inputs is a default value. The other 6 signals are truly variable, could be anything.So 7 input lines, one of those is always the exact same boring value always always always. And the other 6 could be anything. You (as in ntcnico you) are free to choose any random input sequence for those 6 variable input to fuck up my example. For now I'll just keep it as follows: those 6 inputs are the 6 outputs of another module, they are nice and registered, boring old flip-flops, clocked with positive clock edge. Lets say they are the output of some random generator, so I make no assumptions about those 6 input bits. And about that 7th default value input we agree that it is always 1. Or always 0. I don't care, as long as it is static, you are free to pick which one in order to fuck up my example.The output of our blackbox is some function that depends on ALL of the input bits, so no assumptions about that on my part. We could make it the bit reduction XOR operation for all I care. Again, you are free to pick something else to fuck up my example. So our blackbox module has 7 bits of input, it takes the bit reduce xor of those, and voila, that is the output. And we register it for good measure.What you seem to be saying is that in that sort of situation the synthesizer will need more than 1 LUT6 to get the job done? Do understand that correctly? Because IthinkI know for a fact thatthatis: rubbish, not true, false, how the hell can you even think that, take your pick. But as said, that is just so ... wrong that I have a hard time believing that this is what you mean. In which case, could you clarify?PS: Damnit, too long anyways.

author: nctnico
author_rank: Super Contributor
timestamp: March 11, 2020, 12:13:59 am
content: No; you misunderstood.Say you have 10 inputs in total feeding a complex piece of logic. If you create a default value you need 7 out of those 10 inputs to create an output (single bit). If you don't have a default value you only need 4 inputs to create the output value (*).In the latter case one typical LUT would suffice to create the output instead of two.Think about the good old Karnaugh diagrams: the more 'don't cares' you have the less inputs and/or logic are needed to generate the output. Having a default means less 'don't cares' in the Karnaugh diagram and thus possibly needing more inputs and/or logic. I'm not saying you'll always be able save resources but in order to reduce the amount of logic you will want to optimise your code to make outputs depend on the least amount of inputs. So you have to consider the benefits of having a default value versus the extra amount of logic it may create.* Don't wonder about the how and why you get from needing 7 inputs or 4; it is not important. These are just numbers to show that in an FPGA you work with LUTs (building blocks) which have a particular size and that you need extra LUTs if you exceed the capacity of one LUT.

author: mrflibble
author_rank: Super Contributor
timestamp: March 11, 2020, 03:25:33 am
content: Had a longer post here, but on reflection I deleted it. The synthesizer will optimize what it will optimize, regardless of what we write about it.

author: coldfiremc
author_rank: Regular Contributor
timestamp: March 11, 2020, 05:39:57 am
content: Quote from: mrflibble on March 11, 2020, 03:25:33 amAnd that's very important. How inference will work in our description and how much time the analyzer will compile our simulations. RTFM is the best advice here. I think, despite not always generates the most "economical" circuit, to wrap any IP or explicit reference to internal blocks into separate entities or files. That probably will make the design a little more portable.

author: james_s
author_rank: Super Contributor
timestamp: March 11, 2020, 05:59:34 am
content: I think this is all getting a little out of hand. The OP asked what HDL to start with, IMHO they're a LONG way from needing to worry about the nuances and optimizations.

author: emece67
author_rank: Frequent Contributor
timestamp: March 11, 2020, 03:46:54 pm
content: .

author: ale500
author_rank: Frequent Contributor
timestamp: March 30, 2020, 10:01:17 am
content: QuoteIt builds a priority encoded logic sequence. It can be written explicitly too.

author: Bassman59
author_rank: Super Contributor
timestamp: March 30, 2020, 08:25:13 pm
content: Quote from: ale500 on March 30, 2020, 10:01:17 amIndeed it does, and indeed it can. And in general I prefer to write explicit code and not make the future reader (including myself!) guess at what I was doing.But in some recent designs I've used the following paradigm. One use is for a sensor readout sequencer, where my state machine has a bunch of defined states, but the time spent in each state is variable. I took advantage of the "last assignment wins" feature of our HDLs to make the code more readable. So a simple example.Code:architecture foobar of bletch issignal duration : natural range 0 to LONGEST; -- this counts time in each statetype state_t is (S_INIT, -- wait for "go"S_S1, -- state 1S_S2, -- state 2S_S3, -- state 3S_S4); -- state 4signal state : state_t;beginMachine : process (clk, rst) isif rst = '1' thenduration <= 0;state <= S_INIT;elsif rising_edge(clk) then-- Time spent in each state:StateTimer : if duration > 0 thenduration <= duration - 1;end if StateTimer;Decoder : case state iswhen S_INIT =>if go = '1' thenduration <= s1_duration;state <= S_S1;end if;when S_S1 =>if duration = 0 thenduration <= s2_duration;state <= S_S2;end if;when S_S2 =>if duration = 0 thenduration <= s3_duration;state <= S_S3;end if;when S_S3 =>if duration = 0 thenduration <= s3_duration;state <= S_S4;end if;when S_S4 =>if duration = 0 thenduration <= s4_duration;state <= S_INIT;end if;end case Decoder;end if;end process Machine;end architecture foobar;It's quite simple. The counter always counts down to zero and then idles.A mux is built for the counter load. Each load happens for only one clock. When we are in one of the four loading states, the load happens only when the counter is zero.What's neat about this is that the duration of each state can be stored in registers (which themselves have initializers which are stored in nonvolatile memory and fetched at startup) so you can tune the sequencer as needed.This isn't a priority-encoded sequence in the usual sense (if this then that elsif this2 then that2 elsif this3 then that3 end if).Is this "efficient?" I don't know. What matters is if it meets my actual timing constraints. And its operation is immediately apparent to the reader.In each state we have the compare-to-zero for the duration. For long durations that comparison, as well as the timer itself, might require pipelining, so you might register the comparison:Code:-- Time spent in each state:StateTimer : if duration > 0 thenduration <= duration - 1;end if StateTimer;-- pipeline comparison for speed reasons.-- This could have been written with the same paradigm as above!if duration = 1 thendurationIsZero <= '1';elsedurationIsZero <= '0';end if;-- and in each state we use the pipelined comparewhen S_S1 =>if durationIsZero = '1' thenduration <= s2_duration;state <= S_S2;end if;The pipelined-compare flag means that the state machine decoder looks at only two bits to determine when to update the timer and advance to the next state. Those bits are the one-hot state bit and the compare-true flag. It's "better" than doing, say, a 16-bit compare to zero in each state.Your mileage may vary. Write your code for clarity first, then optimize only when necessary.

author: free_electron
author_rank: Super Contributor
timestamp: March 30, 2020, 11:04:53 pm
content: to make such constructions more readable i typically define something like:'define nextstate duration <= duration - 1so i can write`nextstate;

author: Bassman59
author_rank: Super Contributor
timestamp: March 30, 2020, 11:30:19 pm
content: Quote from: free_electron on March 30, 2020, 11:04:53 pmThat's supported only with Verilog, not VHDL.But I wonder -- if each state has its own timer, will the synthesizer be smart enough to optimize them into one, or will you end up with one counter per state that has that `define?

author: nctnico
author_rank: Super Contributor
timestamp: March 31, 2020, 12:29:52 am
content: Quote from: Bassman59 on March 30, 2020, 08:25:13 pmYou can change this by putting the case / when in an else clause in the 'if if duration > 0' (or the if durationIsZero) to make your examples unambiguous. However I get the feeling these are just small examples. Just like in any programming language a very long (nested) if or case statement is an indication a function may be better suited for the job.

author: Bassman59
author_rank: Super Contributor
timestamp: March 31, 2020, 04:59:17 am
content: Quote from: nctnico on March 31, 2020, 12:29:52 amIf you have any ideas on how to reduce a parser that looks at an 8-bit command token and does, well, one of 256 disparate actions as a result, I'm all ears. In the current project, I have such a beast.Now I suppose it could be made into a ROM lookup table, but then there's the questions of readability and maintainability.For the sensor-controller/sequencer state-machine example, the number of states is small. And, in fact, the original idea was to use a ROM lookup table, sequenced by a state counter and embedded in the ROM are the duration of each state and branch control as well as machine outputs. Basically it was a 2901/2910 bit-slice processor without the ALU! Or the Apple ][ floppy-disc controller. (Those ancients, always stealing our ideas.) The ROM was a dual-port RAM, so the "program" could be changed at will. (The program would be fetched at startup from some nonvolatile memory.)I don't really think that there's a "best" way to do this. Do it however it makes sense to you. Don't be clever; that's the synthesizer's job. Just make sure you can understand it in a few months. If it meets timing and area constraints, you're done.

author: free_electron
author_rank: Super Contributor
timestamp: March 31, 2020, 03:36:58 pm
content: Quote from: Bassman59 on March 30, 2020, 11:30:19 pmdon't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...For delays i create macros that would load a value on a counter`define after system_ticks[15:0] <=`define goto if (system_ticks==0) state <=`define goto_next state <= state +1`go (system_ticks ==0)...always@(posedge clk) begin// note that this tick counter here needs to be ABOVE the state machine so we can override the counter valueif (tick) beginsystem_ticks <=system_ticks -1;if (system_ticks ==0) system_ticks <=0;endendselect case statecase 1if `go begin // unrolls to if (system_ticks==0) begin`after 1000; // unrolls to: system_ticks[15:0] <= 1000;`goto `some_state; // unrolls to : if (system_ticks==0) state <= `some_state;// or `goto_next;endcase 2if `go begin....endkeep in mind that the 'after' only executes once the state has transistioned. essentially you are telling the system : do this bunch of work , go state <x> , THEN wait for this timeyou can play tricks : if you omit the 'go test you can chain states that are 'timerless'. to resynchronize a process you simply go back to a state that has a 'go statement.Let's say you have a machine that needs to fire every 1000 system ticks. That means you have 1000 ticks to execute the machine. in that case you test for 'go only at the last state of the machine. the machine will execute and then halt until the counter has zeroed.I had multiple such 'machines' when i was working on harddisks. When the platter passes index i would fire of the main machine and load the length of 1 revolution in the counter ( actually a little bit less , so i could end up in the state that checks for the index pulse to pulse and resynchronize the machine ). Depending on track i would load another machine with the length of a sector ( again a bit smaller so i would end up in the state that is responsible for checking sector transition )This automatically gave me 'time slots' that were locked on sectors , irrespective of drive speed or sector size. i knew up front how many time slots were available and could do things nicely in lockstep with a spinning motor. during spinup or spindown the numbers would change (speed changes ) or when hopping from inner to outer tracks the sectors per track would change. all i needed to do was alter the time between a system 'tick' the machine would always have the correct number of 'subdivisions per sector, irrespective of motor speed or number of sectors per track. if i knew i needed 10 states per sector passing i could easily program that. the 'tick' was generated by a programmable divider from a master clock that was running much faster ( basically a fractional_n synthesizer)i could have nested processes by using mulitple of such timer blocks. every process was attached to its own timer block and all were driven by the same master tick. I could have processes wait for their own 'tick' to expire' or wait until another process synced up.

author: rstofer
author_rank: Super Contributor
timestamp: March 31, 2020, 04:15:00 pm
content: Quote from: free_electron on March 31, 2020, 03:36:58 pmFortunately, the designers of VHDL omitted the macro capability in favor of clean reading code. Somehow, VHDL coders have been getting along without macros for a very long time.VHDL does have procedures and functions and these can be defined in a package and used throughout a project. 'Generic' parameters also help create compile time configuration of procedures and functions.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 31, 2020, 04:27:27 pm
content: Quote from: rstofer on March 31, 2020, 04:15:00 pmYep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.

author: Bassman59
author_rank: Super Contributor
timestamp: March 31, 2020, 06:08:55 pm
content: Quote from: SiliconWizard on March 31, 2020, 04:27:27 pmTo be fair, in the many years I've been designing with VHDL, not once have I needed a macro. When I did Verilog, I used ` macros for constant things like state names. (Oh, and the use of `define for state machine state definitions in Verilog is inferior to using an enumerated type in VHDL.)Let's use the example provided.Code:if `go begin // unrolls to if (system_ticks==0) begin`after 1000; // unrolls to: system_ticks[15:0] <= 1000;`goto `some_state; // unrolls to : if (system_ticks==0) state <= `some_state;// or `goto_next;The first thing I noticed is that you have comments to explain the function of the unrolled code.Second, I don't see howif `go beginis better than simply writingif (system_ticks == 0) begin.Third, if I am looking at simulation waveforms, I don't see the macros`goand such. I see the signal names. This means I have to remember the definition of the macro and translate it into what I see on my waveform display or in my simulation messages.Macros, in this case, are obfuscators.

author: mrflibble
author_rank: Super Contributor
timestamp: April 02, 2020, 05:47:35 pm
content: Quote from: SiliconWizard on March 31, 2020, 04:27:27 pmCode:typedef enum { Oh, IfOnly, SystemVerilog, Had, Some } SortOfEnumerationDataType;SortOfEnumerationDataType oh_if_only;

author: Bassman59
author_rank: Super Contributor
timestamp: April 02, 2020, 11:07:45 pm
content: Quote from: mrflibble on April 02, 2020, 05:47:35 pmAs you note, enumerations are a SystemVerilog thing, so not applicable to regular Verilog users. Of course, VHDL has had enumerated types since, oh, forever.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 03, 2020, 12:01:28 am
content: Quote from: Bassman59 on April 02, 2020, 11:07:45 pmIndeed! And enumerations are not macros either, so I wasn't even sure what the above post was meant to show anyway, and how they would relate with functions and procedures?

author: mrflibble
author_rank: Super Contributor
timestamp: April 03, 2020, 12:59:29 am
content: Quote from: SiliconWizard on April 03, 2020, 12:01:28 amWhat in the hell?You know what, you are absolutely right! No idea how I managed to mangle those info tidbits together.Best guess ... probably managed to grab the"enumeration vs macro"related bit from Basssman59's post, then read your post containing "yes X and Y can .* macro .*". Then called `BRAINFART . And of course forgot to terminate it with a;, because that is what dodgy macro definitions are for!

author: nctnico
author_rank: Super Contributor
timestamp: April 03, 2020, 10:54:58 am
content: Quote from: SiliconWizard on April 03, 2020, 12:01:28 amMacro's are somewhat related to enumerations especially if you want to use pre-defined 'values' with a name. There is more to it in VHDL because the synthesizer has some freedom as to what kind of value to assign to each member (think about a statemachine with one-hot encoding).

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 03, 2020, 01:54:55 pm
content: Quote from: mrflibble on April 03, 2020, 12:59:29 amNo problem. As nctnico added, if you use "macros" to define constants, sure there is some link with enumerations. But isn't there another mean of defining constants in Verilog than using macros? (Don't know enough of Verilog here...)True enumerations (such as what VHDL offers, and I guess SystemVerilog offers something similar?) are a lot more than just constants. (Some may be influenced by C's enum - which is nothing more indeed than just a list of constants, but in C++ they are closer to true enumerations.) They represent a finite set. The benefit is not just for synthesis - it's already a benefit from a coding perspective.

author: nctnico
author_rank: Super Contributor
timestamp: April 03, 2020, 05:29:37 pm
content: Quote from: free_electron on March 31, 2020, 03:36:58 pmThis would be great for a book titled 'coding styles straight from hell'I have a nice sub-title too: 666 ideas for when you want to be the only one to ever be able to work on a project.

author: free_electron
author_rank: Super Contributor
timestamp: April 03, 2020, 08:31:00 pm
content: Quote from: Bassman59 on March 31, 2020, 06:08:55 pmNope. -sigh- This is always the case when trying to explain something on a forum... i try to give the minimum info so it would be clear what the intent is. But then it is misunderstood.This has nothing to do with obfuscation, on the contrary. It is intended to make it easier to create state machines and logic that can sync up .You make definitions for all kinds of events and items that need to happen at certain timestamps. in essence you are creating a language in which you describe the machine and what it does, what it waits for , how long , what it syncs with and so on.these 'keywords' are then defined as verilog backticks ( `define ....)When reading the machine description you don't need to wade through a bunch of complicated syntax. It is an english text that describes what happens. The underlying verilog can be complex and be a block of separate modules.Code:case revolution_statecase `index`start_revtimer;`wait_for_sector_sync;case `first_sector;`get_sectorcount;`current_sector <=1;`start_sector_handler;`wait_for_sector_sync;case `last_sectorblabla...default `wait_for_revolution_sync;If this machines flow needs to change it is easy to understand where to alter the code.In semiconductor design many systems are built like that. They use TCL or some other scripting tool to describe the desired system in a macro language. that then gets translated into instantiated block of verilog that are full of such `defines. the low-level designers make the primitive blocks needed and the `define headers. The rest is driven from outside the verilog world.Nobody reads the actual 'generated' verilog code. A module is designed, simulated and done. How the modules fit together and interact with each other : that verilog is never seen by humans as it is generated by another tool.I had over 300 control registers that needed mapping into dual port memory or hard registers. One side goes to the cpu , the other is hardware. I made a software tool where i can describe the registers and their layout and it would generate the verilog, the c code for the ARM , the C code for the 8051 , the transport code for the USB packet handler and the Visual basic code to throw visualize the data.examplereg 0 r/w ,[15:14] state,  ready,[12:0] version;reg 1 w, [15:13] 0, [12:0] desired_speed;reg 1 r, [15:13] 0, [12:0] current_speed;This would define the registers in the fpga and map them through an address decoder.On the ARM you got a variable defined hard cast at adresses that map into the FPGAIn the arm code i could just write desired_speed = current_speed +1; since both are hard mapped there is no 'i/o code'In visual basic an object was created called current_speed. if you 'read the object' a call us done over usb to a c function on the 8051 that picks up the data from the dpram in the fpga and returns it.same thing with desired_speed. all that stuff was totally handled 'under the hood'.When a new chip came along all i had to do was write the layout of the registers . write-only registers were automatically 'shadowed' in the fpga so neither ARM nor 8051 nor pc had to do any of that.The realtime code on the arm was a short program to spin up the motor and perform seek operations. That would have been impossible due to latency and command jitter in usb. So the ARM did those things in lock-step with assistance from the FPGA.the 8051 code was just i/o transport into the registers and dpram. That was hardcoded and never needed altering as the 'mapping' was handled by the fpga.Basically the top level program did not deal with registers. If a register contained mulitple bit fields , those all became individual 'variables' or 'objects' that could be read and written. The FPGA verilog made sure to 'assemble' all the required bits and pieces to form the true 'register' content and blast that of into real control register. The software did not have to do and/or masking to alter 1 bit in a register. The bit was accessible as a boolean.Development of the platform went from months to half a day. Spend an hour making the table, send it through the compilers and while waiting for synthesis ,write the UI and ARM code. The verilog took 3 hours to synthesize. It filled the largest Cyclone-5 to 80% capacity . I think that was a 35 million gate device. on some large SOC with hundreds of registers and thousands of variable the verilog was hundreds of thousand of lines)The tool create a .h file for the arm , a .h file for the 8051 a .vb file for the user interface and a .v file defining all the registers and the access code for them. In the FPGA the logic would 'trap' a write operation to a variable and fire of the serial protocol handler to shift out the entire register contents into the SOC. The protocol handler was also 'programmable' and the protocol had its own description language.The user interface on the pc used custom control i designed that would lock onto the 'variable' objects. Building the UI was a matter of hours.The whole system had the processors run in lockstep with the FPGA. The fpga generated the clock for the cpu's and it controlled the bus cycles. The fpga emulated the ram and rom for the ARM so the processor did not know that behind a memory location there was actually an enormous block of logic that disassembled and reassembled registers.Why not do this in software ? because the hardware can do it much faster !Think about it this way :you have an SPI bus accessing a 16 bit register. this register has 3 fields. bits 15 to 11 , bits 10 to 6 and 4 to 0. called x, y and zyou need to write a piece of code on the cpu that does the followingx = ((y+3) *z)/32So you need to call an spi handler to read the register , then you need to unpack the bitfields to create 3 integers , then you do the calculation , then you need to repack because you need to leave Y and Z intact but only need to update the bits 15 to 11 (x) and then you need to do another spi operation.My system : i didn't do diddly squat. X Y and Z are all variables hard located somewhere in 'ram' of the processor. The Fpga knows they are each 5 bit but it gives these to me as three int32 with the highest bits already set to 0 so all the bit masking and shifting is handled in hardware. actually it is not even 'shifting' as all this stuff is done in 1 clocktick.Code:reg something [15:0]`define x_read data_out[15:0] = {[15:5] 0 , something[15:11]}`define y_read data_out[15:0] = {[15:5] 0 , something[10:5]}`define z_read data_out[15:0] = {[15:5] 0 , something[4:0]}`define x_write something[15:11] <=data_in[4:0];always_reg @posedge clkif (write_event) begincase addressvariable_x : x_write;.....case read_cycle :- perform SPI access to fetch register contentsalways_comb read_system begincase read_addressvariable_x : x_read;variable_y : y_read;The fpga runs the bus cycle of the processor. When it sees a read event come in it knows the target address. The cpu will only pick up the data 8 clockticks later. ( Hard defined by the ARM bus cycle. You could set the cycle independently for read and write. Write was single cycle , but read was 8 clock ticks. The arm bus clock is 50MHz (generated by the FPGA in sync with its masterclock) . The FPGAs internal clock is 500MHz.... that gave me 80 FPGA clockticks... i need 8 ticks to send the address , 1 tick for the read bit , 1 wait tick , and 16 ticks to fetch the data. the spi-like bus clock was 160MHz. So i was guaranteed to be able to do 1 transport within 1 bus cycle of the arm. ) The processor picks up the data and goes on. The CPU is completely unaware that there was a bunch of stuff happening over a serial bus to fetch the data. The return path is one huge combinatorial address decoder that strips the data and returns what is needed directly into the bus format of the cpu. No need on the processor to do and-mask or-mask or shifting. (or things like sign extention or combining 2 registers into 1 variable ( 32 bit number split over 2 16 bit registers)I also had a dma-like mechanism that would prevent the cpu having to wait for mulitple writes. The fpga would wait until it got a trigger that basically said : send all 'dirty' registers over. the cpu could then do other things.. IF it needed lockstepping those write operations used a different bus-cycle that guaranteed the data leaving before the cpu could execute its next instruction. The Arm-7 has 4 or 8 definable bus cycles and you can control what cycle is used for what memory range. so for data that always needed to leave before continuation you used a slower cycle.That system has been in use since 2007 and everyone loves it. The generated verilog is'unreadable' by humans. but that is not required anyway.Whenever you have peripheral blocks with large register sets , each containing multiple fields : abstract it. it is madness to try to code that by hand. it is mindnumbingly boring and if the register map changes during design you are royally screwed. good luck editing thousands and thousands of lines to relocate a variable or a field. The semiconductor design toolkits are full of 'generators'. feed a table and it generates the verilog for you.Look at the design tools themselves. they come with macro wizards. i need this function. this is in , that is out, this is clock, that and this happens there and then. a is rising , b is falling, and z is asynchronous. . click a button and you end up with a thousand line verilog block. do you ever read that ? no. Would you ever craft that by hand from nothing ? no! that is madness.I didn't invent this. This is standard practice. It's a macro generator for a very complex SPI-like device with hundreds of registers. It generates the hardware and the 'co-ware ( the arm-code) to interact with it in the , from a development perspective, shortest amount of time.So what if the generated code is unreadable for humans and uses macros and many other things. you are not supposed to muck in that anyway. if it needs changing : use the top-level tool.That being said : you can still exploit this by hand for smaller systems. make a 'human-like' language using macro definitions. That makes the flow of the state machine easier to understand than having to read through a bunch of syntax 'tree's that hides the forest. ( that what needs to be done ). I will craft the forest first. the Tree's are small macro's. IF my forest needs to change ( trees further apart, more pines than oaks , a narrower but longer forest ) i can do that in my 'forest description language'. That then gets 'translated' to tree instances.

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: April 03, 2020, 08:51:40 pm
content: Quote from: nctnico on March 08, 2020, 09:29:51 pmPerhaps you should post an example of an average VHDL example and your 5x smaller code implementing the same example so we can see how you do it.

author: nctnico
author_rank: Super Contributor
timestamp: April 03, 2020, 10:38:44 pm
content: Quote from: Sal Ammoniac on April 03, 2020, 08:51:40 pmI already posted several examples. For example instantiating memory primitives instead of using a single line to declare an array. Another good example are address decoders and priority encoders. Google some examples; 9 out of 10 will have a line for each register or output combination. You can solve the first by using an array (together with meaningful constants which greatly enhance code readability if you like). The priority encoder can be written in a simple function with the added benefit that it will work for any bit length.

author: nctnico
author_rank: Super Contributor
timestamp: April 03, 2020, 10:40:39 pm
content: Quote from: free_electron on April 03, 2020, 08:31:00 pmBut why invent a new language if a better language (SystemVerilog and VHDL) already exists? I think you just gave a perfect example of the limitations of Verilog and why people shouldn't start with it nowadays.

author: tggzzz
author_rank: Super Contributor
timestamp: April 03, 2020, 10:58:14 pm
content: Quote from: Bassman59 on March 31, 2020, 06:08:55 pmMacros were a necessary evil back in the 70s an 80s with 64k address spaces. Now they are just evil.One big problem they bring is that they screw up tools that parse the code for automated analysis, and require that the whole codebase has to (in effect) be compiled before a line can be analysed.Another big problem is they also screw up the next person that looks a codebase. Personal little languages are a pain in the arse.Languages have advanced since the 70s and have good mechanisms that achieve the same ends. Use them.

author: rstofer
author_rank: Super Contributor
timestamp: April 04, 2020, 03:20:55 pm
content: Quote from: free_electron on April 03, 2020, 08:31:00 pmThe idea of creating an application specific "language" is certainly a valid use of macros. I started playing with a macro assembler way back around 1970 and really got into the idea with the Digital Research Macro Assembler for CP/M. It's really just a different way of looking at a problem. Do I want to see something that reads closer to hardware or would I rather see something that reads closer to the application.VHDL doesn't have macros so we use state names in the enums to provide context. State variables can be simple integers but this doesn't provide much information. So, we're going to use state names that are closer to the actions being taken.It's pretty easy to dismiss macros and I'm pretty much in that camp but the idea of an application specific "language" is still a compelling use.Alas, I use VHDL and have no intention of changing horses.

author: tggzzz
author_rank: Super Contributor
timestamp: April 04, 2020, 03:37:31 pm
content: Quote from: rstofer on April 04, 2020, 03:20:55 pmDSLs are beguiling and have some benefits. But they have a lot of disadvantages when compared with alternative techniques like domain specific libraries.DSLs always grow incrementally like a cancer, frequently until the creator doesn't understand all the interactions.It can be difficult to get people willing to work in a DSL. Developers want to gain transferable skills, and DSLs aren't.There is no tool support for DSLs. Either you spend time and money developing your own special purpose tools, or you are back in the early 80s using grep.I one wrote a DSL. Fortunately I only spent a week on it before realising I should simply have used Forth (embedded tiny application).I've seen a DSL scripting language take down a company.Use standard language features and libraries in preference to going off in your own world.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 04, 2020, 05:03:55 pm
content: Quote from: tggzzz on April 03, 2020, 10:58:14 pmThere is no real substitute when using C for a number of cases. In other languages, when there is, sure, use something more advanced.Quote from: tggzzz on April 03, 2020, 10:58:14 pmIf the preprocessor is run before the analysis, they screw up nothing, and it's usually not hard to do especially when said tools have a CLI. Decent tools already do this on their own.But they can make reading the output of the analysis more difficult, as they will deal with the expanded macros and not the macros themselves.Quote from: tggzzz on April 03, 2020, 10:58:14 pmThey may, or not. Depends on how consistent they are overall. It just takes reading their definition to understand them, as long as they are written in a logical manner. I know this is a very common argument against macros, but this has never really bothered me. Sure if the macros make no sense, it can be a pain to deal with. There's a good chance that if some developer can't write good macros, they can't write good code either, so that's often just the tip of the iceberg though IME.If you still need to use macros, use them with a few rules. For instance, with C, my first rule for macros is to always define them in all uppercase, so you spot them immediately, and they can't be confused with any other identifiers or language keywords. Another rule: don't make them hide variables, so if they act on any variables, pass these as macro parameters only.Quote from: tggzzz on April 03, 2020, 10:58:14 pmSome do, and when they do, I totally agree. But C, for instance, still doesn't really, and whatever you think of C, it's still widely used.Now I admit we're talking about HDLs in this thread specifically, and for that, there is no contest, although Verilog still lacks a lot without macros compared to VHDL, and I'd agree you should probably switch to SystemVerilog if you're a Verilog user, but sometimes you just can't in a given project.

author: tggzzz
author_rank: Super Contributor
timestamp: April 04, 2020, 05:14:03 pm
content: Quote from: SiliconWizard on April 04, 2020, 05:03:55 pmPrecisely. And let's not think of C++ and templatesQuoteFor anything that has to last, or anything that is bigger than a half a dozen people, you will always have sub-optimum developers.That can be true either because of simple probabilities, or because one developer's good style is another developer's incomprehensible mess.Quoteit is horrifying that we are still writing very elaborate "COBOL" isn't it. I would have hoped for more advances in the last half century.QuoteYup.

author: rstofer
author_rank: Super Contributor
timestamp: April 04, 2020, 06:38:23 pm
content: Even FORTRAN has advanced! It is now called Fortran...I like Fortran and use it every chance I get. It is particularly useful for demonstrating things like the Riemann Sums for approximating integration or Euler's Method for solving differential equations. I've been working with FORTRAN for more than 50 years! Half a century!Like VHDL, I started with FORTRAN and plan to use if forever. These Johnny-Come-Lately languages like C++, Python, et al, won't have the staying power of FORTRAN.It's a little bit newer (a year or so) but COBOL is still kicking around in the banking world. Due to a scarcity of new programmers, I imagine the old-timers are paid very well.

author: tggzzz
author_rank: Super Contributor
timestamp: April 04, 2020, 08:26:06 pm
content: Indeed. Or at least to some extent, indeed.But if C++ is the answer, you've asked the wrong question. Languages should be part of the solution (to your problem), not part of (an addition to your) problem. FFI the C++ FQA (sic).In that vein, I prefer languages that make me jump through hoops to express unambiguously what I need, since that gives me the best chance of getting a working solution.

author: mark03
author_rank: Frequent Contributor
timestamp: April 04, 2020, 08:43:07 pm
content: Quote from: rstofer on April 04, 2020, 06:38:23 pmYou forgot an smiley / wink emoji here, right?!If not, don't worry:Quotehttps://web.mit.edu/humor/Computers/real.programmers

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 05, 2020, 12:25:50 am
content: Quote from: rstofer on April 04, 2020, 06:38:23 pmThose are good examples. Or counter-examples might we say. Whereas many other newer languages can perfectly be used for the same applications, Fortran and Cobol were tailored for specific tasks, and it's often hard to beat that with monstrous general-purpose languages, however new, featureful and shiny they are.As surprising as it may be, Cobol is actually still evolving; we can't consider it a dead language just used for legacy reasons. Its latest standard is from 2014 AFAIK!

author: rstofer
author_rank: Super Contributor
timestamp: April 05, 2020, 03:42:27 pm
content: Quote from: mark03 on April 04, 2020, 08:43:07 pmProbably...The thing is, I'm sort of serious. Fortran will never die and it has a huge headstart on these newer languages so they will never be able to catch up.QuoteThe more or less 'classic' FORTRAN examples I mentioned above can be written in any language and, for the most part, look amazingly similar at the source level.In grad school, I had a project to create an 8080 Assembler using PL/I on an IBM 360/45. Upon completion, my faculty advisor said I had succeeded in making PL/I look exactly like FORTRAN.The original PL/M compiler for the 8080s was written Fortran but it certainly wasn't FORTRAN IV. It seems to be a VAX dialect in use around 1980.

author: mrflibble
author_rank: Super Contributor
timestamp: April 05, 2020, 03:44:05 pm
content: Quote from: SiliconWizard on April 03, 2020, 01:54:55 pmWell, there are theparameterandlocalparamkeywords. For a more comprehensive overview of some of the uses and hideous abuses of Ye Olde Preprocessor, see for example this paper:https://www.veripool.org/papers/Preproc_Good_Evil_SNUGBos10_paper.pdfAs for venturing past the Macro Mountains and entering yonder Dark DSL Forest, I pretty much subscribe to this:Quote from: tggzzz on April 04, 2020, 03:37:31 pmBecause yes, it seemed such a good idea at the time. And oh look at how big and unwieldy it has become. And lets not forget the ever popular cryptic error message caused by the inevitable"oh oops, I forgot that one crucial yet easy to overlook character in my macro call". Said error is of course reported as originating from file X, while theactualoffender is located in some completely different file Y.By sticking to the more established tooling you enjoy the benefits of support & updates available for said tooling. That in turnshouldmean the time cost of maintaining the tool chain is lower, when compared to rolling your own.Coming back to the original question, put together a list of the various HDL revisions. Hopefully that provides the OP some help navigating the (sometimes confusing) HDL landscape.That is, working under the rather optimistic assumption that said OP has not fled from the impromptu incarnation of our annual VHDL vs Verilog Flame-fest.VHDL-1987 (IEEE 1076-1987)VHDL-1993 (IEEE 1076-1993)VHDL-2000 (IEEE 1076-2000)VHDL-2002 (IEEE 1076-2002)VHDL-2008 (IEEE 1076-2008)VHDL-2019 (IEEE 1076-2019)Verilog-95 (IEEE 1364-1995)Verilog-2001 (IEEE 1364-2001)Verilog-2005 (IEEE 1364-2005)SystemVerilog-2005 (IEEE 1800-2005)SystemVerilog-2009 (IEEE 1800-2009)SystemVerilog-2012 (IEEE 1800-2012)SystemVerilog-2017 (IEEE 1800-2017)https://en.wikipedia.org/wiki/VHDL#Revisionshttps://en.wikipedia.org/wiki/Verilog#Historyhttps://en.wikipedia.org/wiki/SystemVerilog#HistoryAs for Verilog vs SystemVerilog ... from the wiki page:SystemVerilog is a superset of Verilog-2005, with many new features and capabilities to aid design verification and design modeling. As of 2009, the SystemVerilog and Verilog language standards were merged into SystemVerilog 2009 (IEEE Standard 1800-2009).Out of curiousity I wanted to see if VHDL support in vivado was any better or worse than SystemVerilog. So googled for "xilinx vhdl-2019". Couple of relevant hits:https://forums.xilinx.com/t5/Synthesis/Xilinx-roadmap-for-VHDL-support/td-p/969806https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug901-vivado-synthesis.pdfOh look, people complaining about certain VHDL-2008 features still not being implemented. So, business as usual then!Similar situation for SystemVerilog.Incidentally, is there anyone out there using the mucho dinero synthesis tool$$$? Is the VHDL/SystemVerilog for synthesis support any better there? I would expect/hope"yes", but who knows?

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 05, 2020, 03:56:04 pm
content: Quote from: mrflibble on April 05, 2020, 03:44:05 pmYes and not that surprising either. Look at how much time it took to get full compliance to C99 in C compilers, especially commercial ones. And the world of digital synthesis is yet a lot more conservative, and relatively slow to evolve.New features of VHDL-2008 are nice, but not game-changing either. Many are just sugar coating. You can do without them while still having something pretty powerful at your disposal.One of the most useful features of VHDL-2008 though IMO is generic packages. Before VHDL-2008, you had of course generic entities, but not generic packages. You'd sometimes find yourself wishing they existed, and was forced to use workarounds. So as long as generic packages are supported, I'm happy with the tools (and yes, even that I can do without, but it's just nice to have on occasion.)

author: tggzzz
author_rank: Super Contributor
timestamp: April 05, 2020, 05:20:15 pm
content: Quote from: SiliconWizard on April 05, 2020, 03:56:04 pmYes indeed. ISTR the triumphant announcement of the firstcompleteC99 complier (or C++ something or other) aboutsix yearslater. That was yet another confirmation that that toolset was as much part of the problem as part of the solution.Mind you, things weren't necessarily better in the good old days: witness the plethora of compilers for subsets of Algol and Algol-68 languages.

author: mrflibble
author_rank: Super Contributor
timestamp: April 07, 2020, 09:15:50 am
content: Quote from: SiliconWizard on April 05, 2020, 03:56:04 pmIt indeed did not come as a total surprise.Especially Xilinx andAlteraIntel are not particularly fast with implementing new language features. Definitely compared to companies that are more on the verification side of things like Mentor Graphics.As for doing without the useful but not game-changing features, I've got mixed feelings there. Lets take for example port declaration. Sure, in Verilog-95 you can declare ports just fine, but the "new" Verilog-2001 syntax is more concise, and IMO helps readability. And to stick with the example of port declaration, in SystemVerilog you getinterfaceandmodport. Sure, you can get theinterfacefunctionality with a few macros to pack and unpack ports. Been there, done that. But I'd much rather use the real thing. Less custom code to maintain, plus more meaningful error messages when shit hits the fan. Also, no name mangling required while constructing constraint files. And something likemodport, mmmmh, I don't think I would attempt cobbling that together with a few macros. I vaguely recall that VHDL has had the interface-like functionality for eons, but not sure about modport. Does VHDL have something similar to modport? I did a few searches but came up dry. But that could easily be because I don't know the proper VHDL related search terms...Quote from: tggzzz on April 05, 2020, 05:20:15 pmKeeping with C compilers, things were definitely not better in the good old days. I still remember the day when hunting down the actual error based on somelooselyrelated error message was a skill on its own. Error message for line 1023? Aaaah, the error is here, on line 42 ... of a different file. With modern C compilers the error messages are spot on a lot more often. Someone finally spent some time on that"Parser must facilitate user-friendly warnings and error messages"TODO item.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 07, 2020, 02:28:20 pm
content: Quote from: mrflibble on April 07, 2020, 09:15:50 amOh, I was specifically talking about VHDL-2008 vs. VHDL-2002 here. This was not meant as a general thought about new language features!As to "modport", I don't know what it is. I've just taken a look at this:https://verificationguide.com/systemverilog/systemverilog-modport/which was only moderately helpful. I'm under the impression we get the same thing with in/out/inout qualifiers in port declarations in VHDL, but I'm sure I'm missing the subtlety of "modport"...

author: emece67
author_rank: Frequent Contributor
timestamp: April 07, 2020, 02:54:57 pm
content: .

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 07, 2020, 05:16:27 pm
content: Quote from: emece67 on April 07, 2020, 02:54:57 pmOk, this is clear now.I do use records in VHDL when implementing relatively "complex" designs, but I'm trying to think about the above and I'm questioning the benefit of directionality for each member. Whereas I can see when this would be useful, I'm not completely sure using record signals in that way would be a good idea design-wise. A bit undecided. But thanks for pointing out this new feature in VHDL-2019, I admit I haven't looked into it yet (and expect it to be implemented in commercial tools in like 10 years if we're lucky.)

author: nctnico
author_rank: Super Contributor
timestamp: April 07, 2020, 05:35:01 pm
content: Record in VHDL are great to get a large number of related signals through several layers of a design. Saves a lot of typing and renaming if you want to add/delete/change a signal. I have used records as inout in the past but nowadays I use seperate in and out records.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 07, 2020, 05:39:13 pm
content: Quote from: nctnico on April 07, 2020, 05:35:01 pmYes, and it just adds structure to your design.But precisely - if each member can have a different directionality, manipulating the record as a whole in general becomes impossible. And IMO it would tend to add slopiness instead of improving things. So the idea of member directionality seems dubious to me, but that's just my opinion at the moment.

author: emece67
author_rank: Frequent Contributor
timestamp: April 07, 2020, 06:57:13 pm
content: .

author: rstofer
author_rank: Super Contributor
timestamp: April 08, 2020, 07:36:55 pm
content: Quote from: rstofer on April 04, 2020, 06:38:23 pmNot only is COBOL kicking around, it is used for Unemployment Insurance in New Jersey (and several other states) and they don't have enough programmers to keep up with the increased demand for benefits:https://www.cnn.com/2020/04/08/business/coronavirus-cobol-programmers-new-jersey-trnd/index.htmlYou would have thought this stuff would have been recoded into PL/I or something. I wonder what language is preferred for banking and business applications? I hope the list doesn't include C++, JAVA, Python or any of the other Johnny-Come-Lately languages but it's a world of programming I don't know anything about.BTW: They would probably have better luck finding Fortran programmers.

author: hamster_nz
author_rank: Super Contributor
timestamp: April 08, 2020, 09:30:33 pm
content: Quote from: rstofer on April 08, 2020, 07:36:55 pmI now think of COBOL as the perfect example of a domain specific language. The way the datatypes are defined in the user's problem space is great. Useless for general computing but perfect for financial business systems.

author: mrflibble
author_rank: Super Contributor
timestamp: April 09, 2020, 02:03:27 pm
content: Quote from: SiliconWizard on April 07, 2020, 02:28:20 pmThe example in the asic-world link I gave is a bit more clear IMO.http://www.asic-world.com/systemverilog/interface3.html#ModportsOr maybe you read that as well and thought is was sub-moderately helpful. Not sure, my crystal ball is in the shop.Quote from: nctnico on April 07, 2020, 05:35:01 pmYeah, that's the feature that was sorely lacking in Ye Olde Verilog. So finally they decided to steal the idea, clean it up, give it a bit of polish and stuff it into SystemVerilog under the guise ofinterface.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 09, 2020, 02:15:56 pm
content: Quote from: mrflibble on April 09, 2020, 02:03:27 pmOK, that makes the use case clearer indeed.I'm still not convinced that modport is a good idea though at this point, at least compared to what we already have in VHDL and if the feature is indeed similar to what's going to be in VHDL-2019. I'll have to look that up if I can find any more info on that.

author: asmi
author_rank: Super Contributor
timestamp: April 09, 2020, 03:13:44 pm
content: Here is a real-life example (I'm sure any more-or-less experienced designer will recognize the bus):Code:// Interface: axi4_lite_intf//interface axi4_lite_intf #(parameter DATA_WIDTH = 32,parameter ADDRESS_WIDTH = 32);//read address channellogic [ADDRESS_WIDTH-1:0] araddr;logic [`AXI4_MM_PROT-1:0] arprot;logic arvalid;logic arready;//read data channellogic [DATA_WIDTH-1:0] rdata;logic [`AXI4_MM_RESP-1:0] rresp;logic rvalid;logic rready;//write address channellogic [ADDRESS_WIDTH-1:0] awaddr;logic [`AXI4_MM_PROT-1:0] awprot;logic awvalid;logic awready;//write data channellogic [DATA_WIDTH-1:0] wdata;logic [DATA_WIDTH/8-1:0] wstrb;logic wvalid;logic wready;//write response channellogic [`AXI4_MM_RESP-1:0] bresp;logic bvalid;logic bready;modport slave( input araddr, arprot, arvalid,rready,awaddr, awprot, awvalid,wdata, wstrb, wvalid,bready,output arready,rdata, rresp, rvalid,awready,wready,bresp, bvalid);modport master( output araddr, arprot, arvalid,rready,awaddr, awprot, awvalid,wdata, wstrb, wvalid,bready,input arready,rdata, rresp, rvalid,awready,wready,bresp, bvalid);endinterface: axi4_lite_intfHere is a module declaration using that interface:Code:module gpio #(parameter ADDR_WIDTH = 64,parameter DATA_WIDTH = 64,parameter GPIO0_WIDTH = 6,parameter GPIO1_WIDTH = 4)(input clk,input axi_areset,axi4_lite_intf.slave bus,output [GPIO0_WIDTH-1:0] gpio0_pins,output [GPIO1_WIDTH-1:0] gpio1_pins);And here is instantiation of that module:Code:axi4_lite_intf #(.ADDRESS_WIDTH(ADDR_WIDTH), .DATA_WIDTH(DATA_WIDTH)) periph_bus();//<....>gpio #(.ADDR_WIDTH(ADDR_WIDTH),.DATA_WIDTH(DATA_WIDTH)) gpio_inst(.clk(clk_periph),.axi_areset(axi_areset),.bus(periph_bus),.gpio0_pins(gpio0_pins),.gpio1_pins(gpio1_pins));Imagine what the code would look like if all interface wires will be declared individuallyThis radically reduces the amount of noise in the code, and so dramatically improves readability.Modports define direction of a wire (input or output), and also make it clear which side of the bus (master or slave) the module expects to be connected to. Of course there can be more than two modports - imagine a control bus which connects to a control module on one end, and to all slave modules will have their own modports. This makes it clear which wire goes to which module, also adding new signals is trivial - you declare it in the interface and in required modports, and there is no need to make any other changes in the wiring up. So modports provide a level of abstraction above wires, kinda like interfaces in Vivado's IPI (you can think of interface as a cable, and modports as connectors on the ends of this cable). This makes working with large buses (like AXI) MUCH easier because there is much less noise from all individual wires' declarations. Just think about how many wires would you have to deal with in typical peripheral interconnect with a dozen of AXI peripherals and few masters (like CPU cores, DMA modules)!!

author: rstofer
author_rank: Super Contributor
timestamp: April 09, 2020, 03:25:31 pm
content: Quote from: hamster_nz on April 08, 2020, 09:30:33 pmI would add Fortran to the list of ideal domain specific languages. Maybe not the jazzed up current incantations but certainly some of the earlier versions. I'm just starting with F77 and F90 and I like some of the changes from Fortran IV and I'll just evade the ones I don't like.I think that when a language lasts for 50 years, the designers did something right.I feel the same way about VHDL. I like its verbosity, I like the strict type checking and I'm glad I started with VHDL rather than Verilog.Like all language wars, there won't be a consensus. So, to each their own!I don't know why the COBOL statement MOVE CORRESPONDING caught my fancy way back when but it is the one thing I remember about the language. Talk about a Unit Record approach...

author: mrflibble
author_rank: Super Contributor
timestamp: April 09, 2020, 03:48:06 pm
content: Quote from: SiliconWizard on April 09, 2020, 02:15:56 pmWell, if the VHDL-2019 version is how emece67 described it, then I would say "no they are not the same". Because emece67 mentioned the VHDL flavor fixes the port directionality upon instantiation. In Systemverilog this is already declared in the interface definition itself. See the previous example, that has the 3 differentsystem,memoryandtbmodport declarations INSIDE of the original interface definition. So before you even decide to instantiate anything you declare 3 different "flavors" of the same interface, for use in 3 different use cases. The practical difference being, that with the modports inside the interface definition, you have a single location where you define the interface and the intended use cases. So no direction modifications inside some other file three design levels down.

author: tggzzz
author_rank: Super Contributor
timestamp: April 09, 2020, 04:02:01 pm
content: Quote from: rstofer on April 09, 2020, 03:25:31 pmIn school I read about COBOL while learning Algol. I remember three thigs:typical statement was ADD A TO B GIVING Cadvanced use was COMPUTE C=A+B (can't really remember if the "compute" was there)vowing never to program in COBOL, and never regretting it in almost 50 years

author: Bassman59
author_rank: Super Contributor
timestamp: April 09, 2020, 05:32:30 pm
content: Quote from: asmi on April 09, 2020, 03:13:44 pmI don't need to imagine it -- I have exactly that same sub-optimal thing in my current design. It started out simple (as all things do, I suppose), and as features were added, the entity that manages setting operational registers has gotten unwieldy. So today's plan is to simplify all of it and make the registers into a record. This plan wasn't spurred on by this thread. I don't think, anyway ...

author: emece67
author_rank: Frequent Contributor
timestamp: April 09, 2020, 07:36:50 pm
content: .

author: rstofer
author_rank: Super Contributor
timestamp: April 10, 2020, 02:17:49 pm
content: This idea of using a record with views could be quite handy. I have a DMA controller with several devices connected. Some devices are readers, some are writers and some are bi-directional yet all have the same set of signals with the only real difference being whether the device is requesting a read or a write. There is also a memory-to-memory channel for placing the cold start loader in RAM at startup.If nothing else, the record/view concept would add a certain amount of uniformity to the interface.Then there are the 4 identical serial ports (these should be easy) which are, themselves, connected to the DMA controller. I could use a generic to specify the baud rate.One of these days I'm going to clean up that project.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 10, 2020, 02:47:36 pm
content: I see the idea. I'll have to get ahold of a draft of VHDL-2019 if it's available anywhere.

author: rstofer
author_rank: Super Contributor
timestamp: April 10, 2020, 04:48:27 pm
content: As near as I can tell, Xilinx Vivado only supports up through VHDL 2008 and maybe not all of that. The User Guide shows what special features are defined but around page 214 (of the document) it talks about how to set up VHDL 2008. I found another comment on the Interwebs that says VHDL 2008 is now enabled by default.https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug901-vivado-synthesis.pdfI wouldn't expect to see the 2019 version any time soon - at least in Vivado. Maybe a 3rd party vendor will incorporate it but I have never convinced myself that outsiders can synthesize (actually, place and route) better than the factory. It is also likely that I'm completely wrong - again!ETA: In looking around the IDE, it doesn't seem possible to select VHDL 2008 when a file is created but its properties can be changed by right clicking on the file name and selecting Set File Type from the fly-out menu then selecting VHDL 2008 from the drop-down box.I don't use any of the advanced features (yet) so I can get by with the default VHDL setting - whatever it is...

author: asmi
author_rank: Super Contributor
timestamp: April 11, 2020, 02:29:08 am
content: Xilinx is improving SystemVerilog support with almost every release of Vivado. I guess the reason is they constantly improve AXI VIP (which is 100% SystemVerilog and ships with full source code), and so they need better language support.

author: rstofer
author_rank: Super Contributor
timestamp: April 11, 2020, 02:55:12 pm
content: Quote from: asmi on April 11, 2020, 02:29:08 amWhich means the language is a moving target. I wonder how many projects become broken when there is an upgrade. It's interesting that Xilinx turned on full support for VHDL 2008 in Vivado 2018. Ten years to get to a point where the language was supported and stable.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 11, 2020, 03:27:57 pm
content: Quote from: rstofer on April 11, 2020, 02:55:12 pmIf they keep *adding* support for some features without removing anything, this shouldn't break projects after an upgrade. It just means you can never use all features of a given standard at any point until there's full support, which is annoying but shouldn't break anything. Fortunately, those standards are evolving in such a way that backward compatibility is most often ensured, so if you had to use only a subset of new features, your code shouldn't break when support for other features is added.The fact you'd use a subset of a given standard version tied to the tools you're using sucks though, and said subset should be clearly documented on a project level so any new contributor would know what is allowed and what isn't... In practice, I usually shy away from that and only use a given std version if it's fully supported.

author: rstofer
author_rank: Super Contributor
timestamp: April 11, 2020, 06:58:24 pm
content: OK, project shouldn't break but will they port to another vendor's tools?I like the idea of staying with a fully supported version so long as other tools also support it. Even though Vivado appears to fully support VHDL 2008, maybe I'll avoid those extra features (whatever they are).

author: Bassman59
author_rank: Super Contributor
timestamp: April 11, 2020, 07:44:42 pm
content: Quote from: rstofer on April 11, 2020, 06:58:24 pmPorting to other vendors is more than just HDL support. All of the interesting features of modern FPGAs require, at minimum, “IP core” instantiation, or worse, some kind of “Wizard” to generate the block. The vendors know this, of course. You can be clever and try to write an abstraction layer/wrapper around those vendor-specific blocks, but sometimes it’s easier to realize that porting to a different vendor’s parts means a significant re-design, so why bother.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 11, 2020, 11:18:05 pm
content: Quote from: rstofer on April 11, 2020, 06:58:24 pmThen this is a slightly different problem... choosing the std version which is supported by most tools around.At this point, VHDL-2002 is a safe bet. Never had a problem with it. VHDL-2008, OTOH, is still problematic.

author: james_s
author_rank: Super Contributor
timestamp: April 12, 2020, 02:46:50 am
content: Quote from: rstofer on April 09, 2020, 03:25:31 pmI agree on all points. VHDL works well for my brain, I don't like the coding style some people use where they declare all the entities and then instantiate them all rather than just instantiating from the work library but whatever.I've never really understood why some people are so passionate about their language choice, I guess it becomes a religion and part of their own identity for some. I'm not aware of anything you can define in Verilog that you can't define in VHDL or vice versa. There's also nothing stopping anyone from leaning multiple languages, indeed I'd encourage anyone starting out with HDL to try them both and then go with the one they find easiest to work with.

author: james_s
author_rank: Super Contributor
timestamp: April 12, 2020, 02:50:51 am
content: Quote from: Bassman59 on April 11, 2020, 07:44:42 pmMost of these features have mostly equivalent features offered by other vendors. A lot of my early learning projects involved porting existing projects from one vendor to another, I got pretty good at it after a while.

author: tggzzz
author_rank: Super Contributor
timestamp: April 12, 2020, 07:48:23 am
content: Quote from: james_s on April 12, 2020, 02:46:50 amPrecisely, and the same is true for software languages.Engineers should be able to realise that, to a good approximation, Java=C#, Pascal=Delphi, Lotus123=Word, Verilog=VHDL, but that Java/C# != Verilog/VHDL etc.Once you know one example of each class, you will be able tochoose the right class - oftennotachieved!use whichever example of the class is convenient, with only a short learning curve

author: nctnico
author_rank: Super Contributor
timestamp: April 12, 2020, 09:41:22 am
content: Quote from: james_s on April 12, 2020, 02:46:50 amI'd be careful with this advice. It takes a really long time to learn how to use a programming language effectively. It is not only the syntax but also the libraries which come with it (or a set of vendor specific libraries). As I wrote before: I have invested quite a bit of time to learn the more advanced constructs of VHDL which makes me work very effectively with it. If I had to do the same with Systemverilog I'd be learning a different language with the same goal. That isn't very efficient use of time. BTW you can swap the language names and my claim is still true.@tggzz: Lotus123 is a spreadsheet; not a word processor and VHDL most certainly isn't equal to Verilog. There is too much missing from Verilog as a programming language to make a meaningful comparison to VHDL. VHDL compares to Verilog like C compares to assembler.

author: emece67
author_rank: Frequent Contributor
timestamp: April 12, 2020, 10:01:47 am
content: .

author: tggzzz
author_rank: Super Contributor
timestamp: April 12, 2020, 10:43:04 am
content: Quote from: nctnico on April 12, 2020, 09:41:22 amShrug. I couldn't remember the name of the MSOffice spreadsheet component.QuoteYou miss the point. An,any, HDL isradicallydifferent from a spreadsheet or an HLL. By comparison the differences between HDLs isminor.Ditto between HDLs and analogue simulators or symbolic algebra languages.In a similar vein, all screwdrivers are pretty much the same when compared with hammers.It is necessary to know when to use a hammer and when to use a screwdriver. If you can use one screwdriver, you can quickly learn to use another.

author: nctnico
author_rank: Super Contributor
timestamp: April 12, 2020, 11:10:18 am
content: Quote from: tggzzz on April 12, 2020, 10:43:04 amUnfortunately your screwdriver analogy doesn't work for programming languages. Sure if you know how to use GCC you can use a different C compiler as well. But to say that -for example- if you know how to program in Pascal you can pick up C easely is just wrong. A programming language goes far beyond just the syntax. The ecosystem around it also comes into play.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 12, 2020, 03:50:32 pm
content: Quote from: emece67 on April 12, 2020, 10:01:47 amWhat a weird assumption. What would make you think that?Whereas I have no hard figures (they are hard to find), my small humble research tended to show me that VHDL was more widespread than Verilog worldwide actually. I can't provide hard proof of that though.But whatever, VHDL has been around (and supported) for much longer than SV, there are still much fewer tools supporting SV than VHDL.As we discussed earlier in the thread, if you specifically think that vendors tend to lag in supporting VHDL-2008 and later, that is true, but they tend to lag in supporting SV as well. And as I said, VHDL even with older std versions (such as 2002) is perfectly usable. There's a much narrower gap between VHDL-2002 and 2008 than between Verilog and SV.And whereas VHDL still tends to be favored for safety-critical designs, I think it has nice days ahead.I'm absolutely not worried about it.

author: TomS_
author_rank: Frequent Contributor
timestamp: April 19, 2020, 08:01:36 am
content: I've just started playing with some CPLDs and decided to go with Verilog after watching some videos and reading examples for both.For me, the Verilog syntax looked and felt better to write than VHDL.I'm happy with my choice, but I don't have the experience to know whether I've made the "right" choice.So far I'm feeling productive and achieving what I need to achieve, but I've got a pretty good ability for picking up new languages, so if this doesn't happen to work out for some reason I'm not that worried.

author: tggzzz
author_rank: Super Contributor
timestamp: April 19, 2020, 08:23:43 am
content: Quote from: TomS_ on April 19, 2020, 08:01:36 amI suggest that, for any language, the syntax is much less important than the semantics.I'm less interested in whether I can "express things right", more interested in whether I can "express the right things".