Resources for learning FPGA - Page 1
Forum section: electronics / general

author: aheid
author_rank: Regular Contributor
timestamp: February 06, 2020, 01:08:06 pm
content: Hi,Got myself interested in FPGAs, and picked up an iCE40 UltraPlus devboard. Got Radiant installed and been blinking my first LED, so far so good. I've been programming for 20+ years in various languages, and done a lot of heavy multithreaded code, so I feel comfortable with the idea that a lot of things are happening at once and the potential pitfalls that comes with that.But, I'm new to Verilog, and could really do with a good online reference, as well as some sites describing the fundamentals which I can come back to.For example, I mostly get the difference between a "register" and "wire", but yesterday I got confused as to why I couldn't use a register as output from a module, but had to use wire. I also didn't get why I couldn't cast a 32bit result to 24bit by simply slicing it or similar (ie "counter <= (counter + 1)[23:0]). So I clearly need to learn a bit more about the basic syntax, as well as get a firmer understanding of the various concepts.I searched these forums and foundhttps://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-111-introductory-digital-systems-laboratory-spring-2006/which looks good, but presentations can be a bit too distilled at times so I'd like something a bit more comprehensive to augment it.I'm also interested in typical idioms, as well as things to avoid etc.Anyone got some nice links handy?

author: rstofer
author_rank: Super Contributor
timestamp: February 06, 2020, 02:57:54 pm
content: Google for 'verilog tutorial', they're all over the place.I bought a book 'Verilog by Example' by Readler. It's a place to start.I use VHDL so I can't say very much about Verilog. One day I will do a complete project using Verilog. One day...

author: aheid
author_rank: Regular Contributor
timestamp: February 06, 2020, 03:14:25 pm
content: Yeah been trying but the issue is more information overload as there are just so many, so was looking for some suggestions for good ones. I'm not new to programming etc, "just" FPGA.Stumbled overhttps://www.chipverify.com/verilog/verilog-introductionjust now, looks good so far.How did you find the book?

author: rstofer
author_rank: Super Contributor
timestamp: February 06, 2020, 05:04:19 pm
content: I'm not really sure what to think of the book. It has a lot of information but it doesn't seem to grab my interest but that's probably just me. I have a hate-hate relationship with Verilog so I just don't put enough effort into learning it. I keep telling myself I should learn it but when I compare it to VHDL, I find I prefer VHDL. VHDL is like Pascal (which I love) and Verilog is like C (which I use). One is elegant, the other gets the job done. All of the ambivalence is my fault. Verilog has been around a long time and will continue well into the future unless it is overtaken by System Verilog. We'll see...I could only see the Index of your linked site (unless I turn off my Ad Blocker) but it looks to be very complete. It seems like a very good place to start.And then comes Test Benches. In the early years of my adventures with FPGAs, Xilinx didn't offer a free simulator so I never learned to use one. Skipped the whole process and went straight to synthesis. I'm still not convinced that simulation isn't more time consuming than just implementing the logic but, again, that's me and my projects. So, I decided to learn about test benches in a rather expansive fashion. It is VHDL specific and it costs money but this program is terrific:https://vhdlwhiz.teachable.com/p/dot-matrixThe test bench education was worth every dime. The project itself is fairly trivial but I did learn different ways to code certain aspects. My way would have worked, the author's way is probably better. The test benches are truly educational. I have never viewed education as 'free' so I didn't mind paying a bit for the course.Just for giggles, I'm going to work through the DUAL 7-SEGMENT DISPLAY FPGA CONTROLLER course - seewww.vhdlwhiz.comI already know the parts, I already have the toolchain installed, as soon as I get my Digilent order, I'm off and running - $17 for the course. About what we spend on a trip to Taco Bell for the two of us.

author: rstofer
author_rank: Super Contributor
timestamp: February 06, 2020, 05:46:52 pm
content: I turned off my Ad Blocker and started looking through a few of the topics. Be aware, there are typos in to code: rsnt versus rstn in at least two topics. I usually expect code to actually work as written but I understand how typos come about. I make them all the time.I browsed through the material without spending much time but I don't learn well from the approach. It's a reference manual, not a tutorial. Again, it's just me but I need a 'project'. I'll search the material to find answers to questions about my project but I just don't pay attention to long presentations of topics that aren't directly in support of a project. I want a tutorial to go somewhere. I don't necessarily care where as in the case of the Dot Matrix project but it has to lead to something tangible.My first FPGA project was blinking an LED, my second was adding a Compact Flash drive to the T80 Core (opencores.org) and bringing up CP/M 2.2 on the Z80 core. Lots of work in that project but it kept my interest. I never did mess around with the internals of the T80 core but I did play with the IO bus and the control signals. Learned a lot! You absolutely must terminate the NMI pin.My third project was a complete emulation of the IBM 1130 minicomputer. Card Reader, Printer, Typewriter, Keyboard, Disc, CPU and Plotter. It runs the factory software unchanged including the 27 pass FORTRAN compiler. I had a worthy project so I learned enough VHDL to get it done. It's not always pretty but it works. This is the way I learn! Jump in and make mistakes.Find a project and learn enough to build it. If nothing else, research all you can find on the LC3 RISC CPU. It is used in many universities as a design course. It's a simple processor that the authors create using a microcode approach. That's an interesting approach for an FPGA where we would tend to use a huge finite state machine. I like microcode! I didn't use it but I like it. In any event, the state diagram is given as is the hardware block diagram. It is sufficient. There's a book: "Introduction To Computing Systems" by Patt and Patel. The complete project includes an assembler. By the time you finish this project, you will know a LOT about Verilog. And computer design...Given the book and all the reference material on the Internet, it is not a project too far to reach. It'll take some time but if you create a lot of modules and tie them together, it will all work out.

author: aheid
author_rank: Regular Contributor
timestamp: February 06, 2020, 07:41:27 pm
content: Thanks a lot for the info, highly appreciated.Since I'm brand new I haven't really spent much thought on Verilog vs VHDL. The examples I started with were Verilog. I've spent most of my life programming Pascal dialects, but most of the rest reading and writing C/C++, I love and dislike aspects of both. I taught myself programming using F1 in QBasic, so I guess that's why I'm used to learning from reference manuals and such. But sometimes it's nice to get a higher view.I've got a few projects I'd like to complete, nothing overly ambitious I think, but taking an existing core and adding something to it sounds interesting.

author: RoGeorge
author_rank: Super Contributor
timestamp: February 06, 2020, 08:20:58 pm
content: Quote from: aheid on February 06, 2020, 01:08:06 pmThat's the problem,you need to drop the programming language approach.Verilog is a different thing, concepts from programming does not apply much to HDL.HDLs (as VHDL, Verilog) are NOT programming languages, in the sense that HDLs do not describe an algorithm. They describe a schematic diagram, a machine. It is just a coincidence that the HDL schematics (the HDL text sources) reminds about programming languages (the programing code sources). The only resemblance is they are both text, written one line after another, and that's it.Keep that distinction in mind:- programing languages are for describing algorithms- HDL languages are for describing schematic diagrams of digital circuits (as in wires, registers, multiplexers, look up tables, logic gates, flip-flops, etc).Programing code is executed secvential,HDL code is not executed at all, and certainly is not secvential. HDL describes a schematic.On short, HDLs are not programming languages, HDLs are schematic languages.- HDLs are to describe a digital hardware, a machine- programming languages are to describe the software running on a hardware machine

author: rstofer
author_rank: Super Contributor
timestamp: February 06, 2020, 08:32:37 pm
content: VHDL is a STRONGLY typed language, conceptually similar to Pascal. Verilog is a little more loosey-goosey, somewhat like C. Even so, VHDL supports the concept of cast so I can declare a standard logic vector (a simple vector of bits), cast it to unsigned, add 1 and cast it back to standard logic vector. Or I could have just declared the signal to be unsigned in the first place. But the point is that the coder has to get the types straight and prove to the compiler that they know what they are doing. Whether that is a good idea is central to the difference between VHDL and Verilog.Remember, we are designing hardware and all these casts disappear. They don't change the resulting hardware in any way, they are just proof that the coder knows what they are doing.I don't know what you have for FPGA resources but it you can afford a $17 tuition, a $25 prototype board, a $7 display plus a couple of cables, why not follow the VHDL tutorial at VHDLWhiz.comhttps://academy.vhdlwhiz.com/fast-trackSave on shipping by checking inventory at DigiKey first. Truth told, I have no idea how to get parts where you are!I like the author's tutorials because they lead somewhere and the presentations are very professional. I also like that he is kicking back in Thailand but that's a separate matter. FWIW, the author is from Norway!BTW, there is a lot of free VHDL stuff on that site:https://vhdlwhiz.com/

author: mark03
author_rank: Frequent Contributor
timestamp: February 06, 2020, 10:47:03 pm
content: I am still a rank beginner, so you should take this with a big grain of salt. I found Verilog quite confusing and VHDL annoyingly bloated. (It was not the strong typing per se that bothered me. It just feels like the cultural equivalent, in the HDL world, of writing software in FORTRAN.) I recently found Stuart Sutherland's new-ish book on SystemVerilog,https://sutherland-hdl.com/books_and_guides.html#RTL%20Bookand this stuff is making a lot more sense to me now. If you are headed down the Verilog route, I would strongly recommend getting a book like this and learning SystemVerilog from the beginning, because most of the new constructs relevant to synthesis are now supported in tools like Vivado and Quartus (not sure about Radiant). It will encourage HDL "goodthink" which, as I understand it, has been a big part of the anti-Verilog critique from the VHDL folks.Now if I could just find a user-friendly introduction to the art of writing constraints, timing analysis, etc.!

author: Yansi
author_rank: Super Contributor
timestamp: February 06, 2020, 11:26:19 pm
content: I'd suggest this book:

author: RoGeorge
author_rank: Super Contributor
timestamp: February 06, 2020, 11:30:16 pm
content: Quote from: mark03 on February 06, 2020, 10:47:03 pmOne does not write software in HDL, one can only draw a digital circuit with HDL.

author: emece67
author_rank: Frequent Contributor
timestamp: February 07, 2020, 12:00:29 am
content: .

author: emece67
author_rank: Frequent Contributor
timestamp: February 07, 2020, 12:02:24 am
content: .

author: RoGeorge
author_rank: Super Contributor
timestamp: February 07, 2020, 12:38:56 am
content: Please don't tell HDLs are Turing complete, so technically they can be considered programming languages. Yes, they are, but this is not the point. This is not the point when learning them for the first time, especially when switching from software design to digital design. It will only add confusion.Writing testbenches is another story, but first comes the synthetizable code. If we think about HDL as a schematic, it would be easy to understand this kind of problems:Quote from: aheid on February 06, 2020, 01:08:06 pmLater, we can always switch back to programming language thinking, when necessary.

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 12:39:25 am
content: The thing about HDL is that you are using templates, in effect. Once you know how to code a MUX, an array of registers, an ALU and a Finite State Machine, you are pretty much all set (I'm going to ignore DSP). The next MUX looks a lot like the last one - more or less inputs, narrower or wider but the select signal has the same effect. How many ways are there to build a register? The big task for the compiler is to take your written description of the hardware and interpret it in such a way as to use standard blocks that can be implemented in one or more LUTs. The compiler can pull a MUX out of an IF-THEN-ELSIF-ELSE statement. It knows how to convert the written statements to hardware. Of course, the designer has to be thinking in terms of these basic building blocks when they write the code. It helps to give the compiler a hint.Look at page 35 here:http://www.cs.utexas.edu/users/fussell/cs310h/lectures/Lecture_10-310h.pdfWhat you see is a RISC CPU built up from Muxen (I invented that word, not knowing the plural of MUX), registers, adders and a FSM. Nothing magic. Make each block a process or module and wire them together.Look at the MARMUX in the upper left corner. It has 2 inputs each 16 bits wide. It chooses to send either the result of some address generation or an extended field of the Instruction Register to the Memory Address Bus. So write a module that describes just this piece and call it, oh I guess, MARMUX, Worry about wiring it up later.Look at PCMUX - same drill but 3 inputs all 16 bits wide - call the module PCMUX and it's done!The REG FILE is a little tricky. It has 2 banks of 8 registers (a 2 dimensional array of standard logic vector) each register is 16 bits wide. Here's the trick: both parallel registers are written at the same time independent of which registers are being read. Note that we have two outputs, SR1OUT and SR2OUT, we have two 3-bit selectors and only one 3 bit DR selector - the destination register.The FSM has a maximum of 64 states but only 58 are implemented in the microcode. Here is the state diagram:https://hkn.illinois.edu/wiki/wiki:architecture:lc-3_instruction_processingPage 584 in this document has the microcode worksheet. It is missing one column:http://people.cs.georgetown.edu/~squier/Teaching/HardwareFundamentals/LC3-trunk/docs/LC3-uArch-PPappendC.pdfNote that all 3 documents come from a different university. This is quite a popular project!

author: james_s
author_rank: Super Contributor
timestamp: February 07, 2020, 01:23:02 am
content: Honestly I think programming experience is more of a liability than an asset when you are learning HDL. HDL *looks* like a programming language but in reality it is describing hardware.People often say "everything executes in parallel" but this is not entirely accurate. Nothing is "executing", the circuit is defined and then all of the parts operate at once. This is obvious if you think of it as wiring up several ICs on a board, of course the ICs will all operate at once, they're all wired up on the board and once you wire up an IC it will do whatever it is that it does for as long as power is applied, putting more ICs next to it is not going to affect it.Keep reminding yourself that you are not writing a program, you are describing hardware, getting used to that mindset was difficult for me. It is further complicated by the fact that you can describe the same circuit using various abstraction levels, behavioral modeling is starting to really look like a program, but it's still describing hardware.

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 01:56:58 am
content: The smaller the module, the more it looks like a chip. The big FSM is usually the exception. That’s the trade off of HDL logic versus a more obscure chunk of microcode. I like microcode, it is more compact than the typical FSM, but only when I have a meta-assembler. And I don’t have one!

author: mark03
author_rank: Frequent Contributor
timestamp: February 07, 2020, 03:37:16 am
content: Quote from: emece67 on February 07, 2020, 12:02:24 amI didn't mean to suggest any commonality whatsoever! I was making an analogy:VHDL is to Verilog in the HDL world asFORTRAN is to ____ in the software world (probably C)The OP specifically mentioned "wire" vs "register" confusion which I also had (past tense may not be fully accurate. SystemVerilog is much better in this regard. If you're going to learn Verilog from scratch, try to get a SystemVerilog text and learn it the right way, so you don't have to unlearn stuff later.

author: mark03
author_rank: Frequent Contributor
timestamp: February 07, 2020, 03:48:02 am
content: PS folks piling on to say how you need to get out of the programming mindset, and remember that you are wiring circuits, is almost cliche in these threads. It is true, but most new students figure that out pretty quick. For me, the hardest part of "getting past blinky" is all of the stuff they *don't* cover in a text on VHDL/Verilog for synthesis. How to write constraints, how to know when to instantiate vendor-specific blocks vs trusting the synthesizer to do it for you, how to decompose complex tasks---especially DSP stuff.IMO the vendors could do a better job at providing gentle on-ramps to this sort of thing, but I think they are incentivized to push their fancy HLS tools instead. So for questions like "What are all of the ways I can code a FIR filter in HDL?" there is a real dearth of practical information, and the best introductions are often really old app notes from the vendors, before they started telling you to "just use the filter wizard."

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 04:17:30 am
content: In VHDL, you don’t have to worry about reg versus wire. They are all ‘signals’

author: RoGeorge
author_rank: Super Contributor
timestamp: February 07, 2020, 04:26:01 am
content: Quote from: mark03 on February 07, 2020, 03:48:02 amWhat you are missing is "digital design".The study ofdigital designis for hardware what the the study ofcomputer algorithmsis for software.

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 08:25:44 am
content: I think I have a fairly ok mental model, I guess it's just the syntax and abstractions of HDL that trips me up. Like yeah it's all wires and circuits, but why then doesn't the slicing work? If I have a breadboard with an IC that has 8 output pins I can just NOT hook up 3 of them to get 5 output signals.Or the wire vs reg... I made the module declare an "output reg sig", why couldn't I pass a reg to it when instantiating the module, why did it have to be a wire? For regular code I set a register from another, say x <= ~x for example, without specifying the implicit wiring.Anyway thanks, I'll have a look at the resources suggested.

author: RoGeorge
author_rank: Super Contributor
timestamp: February 07, 2020, 01:12:03 pm
content: Quote from: aheid on February 07, 2020, 08:25:44 amFor the last time, the mental model you have is incorrect, and that is what stays in your way, not the syntax. Just put aside, for a moment, your 20+ years of programming. Let's take your example.Quote from: aheid on February 06, 2020, 01:08:06 pmI can only speculate that is a piece of synthetizable HDL, and your intention here is to use only the first 24 bits of a 32 bits counter. Is that what you want to do? If yes, then it doesn't make sense if you think of it in terms of circuits. You had before 32 flip-flops chained as a counter, and now you suddenly want to disconnect the last 8 of them? What if another signal arrives in the meantime? How should the counter act, as a 24 or as a 32 bits counter?If you draw a schematic of 32 chained flip-flops, and think about them in terms of schematic (and not as software) it doesn't make any sense to increment only the first 24 bits. What should the other 8 bits do? Should they just sit there, or should they increment? Maybe they should reset?Picture them as physically minuscule ICs inside the FPGA. That's a counter. It's not data, it's a circuit.Please put the code of the whole module, so we can discuss it line by line, and make an idea of what is happening under the hood. It's not like a typecast in programming, but enough metaphors. Put a simplified version of the whole module, say in words what you expect from it, where it does something else than you expect, and the errors spit by the IDE.Now if you don't have the time to do that, to stay on topic about links, I'll recommend this for a FPGA 101. Seems trivially simple, but is also concise, so it can be parsed very fast. Read even the parts you think you know, and think schematics.https://www.fpga4fun.com/That was what helped me when, after decades of programming, I stepped for the first time into FPGAs.

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 01:37:05 pm
content: Quote from: RoGeorge on February 07, 2020, 01:12:03 pmWell say I got 32 outputs from a bunch of ICs sitting on a breadboard. I want to feed these to a new set of ICs on another breadboard. Why can't I just hook up the 24 wires for the first 24 ouputs, and ignore the last 8 outputs? Alternatively, if I got a 32bit adder as one big IC, why can't I simply ignore the pins representing the upper 8 bits? What's wrong with that?Quote from: RoGeorge on February 07, 2020, 01:12:03 pmThe module I copied from some sample code, I just modified the name of it and the text file it reads the data from:Code:module ROM_SIN_256(input clk,input [7:0] addr,output reg [7:0] dout);reg [7:0] memory [0:255];initial$readmemh("sin_256.txt", memory);// synchronous ROMalways @(posedge clk)dout <= memory;endmoduleIn my top.v file I have this:QuoteThis leads to: "ERROR - concurrent assignment to a non-net sin_val is not permitted. VERI-1195 [top.v:78]".If I change the declaration of "sin_val" toCode:wire [7:0] sin_val;I don't get an error. What confused me was that dout is declared as "reg", and since I've not yet studied modules in depth I just have an implicit understanding of the syntax. But I think that has more to do with how Verilog works than how the hardware works.

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 02:01:43 pm
content: The reason I wanted to slice off the 24 lower bits, is that the implicit addition circuit produced is apparently 32bit, and so I get a warning that I'm discarding the upper 8 bits. So far I get around that by using a function:Code:reg [23:0] count;function[23:0] truncate24;input [31:0] data;begintruncate24 = data[23:0];endendfunctionalways @ (posedge oclk or posedge rst)beginif (rst)begincount <= 24'd0 ;endelsebegincount <= truncate24(count + 1) ;endendAlso, thanks again for the responses, much appreciated.

author: Yansi
author_rank: Super Contributor
timestamp: February 07, 2020, 02:18:09 pm
content: That is probably the incorrect programmers thinking model.It defaulting to 32bits is likely just your incorrect assumption. HDL does not work with bytes.

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 02:23:40 pm
content: Quote from: Yansi on February 07, 2020, 02:18:09 pmNot really:Code:count <= (count + 1) ;gives me the following output: "WARNING - top.v(42): expression size 32 truncated to fit in target size 24. VERI-1209 [top.v:42]See the code in my previous post for context.

author: emece67
author_rank: Frequent Contributor
timestamp: February 07, 2020, 02:27:37 pm
content: .

author: Yansi
author_rank: Super Contributor
timestamp: February 07, 2020, 03:05:34 pm
content: Quote from: aheid on February 07, 2020, 02:23:40 pmHDL has nothing to do with bytes. It has zero reasons to default to any multiples of 8 bits other than you have defined the other signal or set of flip flops to be 32 bits wide.Maybe it is just me, because I am no Verilog guy, I can understand only VHDL.

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 03:30:07 pm
content: Quote from: Yansi on February 07, 2020, 03:05:34 pmThis is crystal clear.Quote from: Yansi on February 07, 2020, 03:05:34 pmRight, but clearly the tool I'm using generates a 32bit adder when I'm using the + operator. I did not expect this since I declared the "register" as 24 bits, but ok, similar widening happens in C too and is nice if you want the extra carry bit. My confusion stems from not being able to discard the output from the upper 8 bits via a simple [23:0] at the end.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 07, 2020, 03:34:57 pm
content: Quote from: aheid on February 07, 2020, 02:23:40 pmI don't know Verilog much - VHDL here too - but from the above, I'm assuming that Verilog in that respect is kind of similar to C as to how it handles arithmetic expressions.Looks like 'count + 1' is not the same type as 'count', but probably the same type as '1', which is likely to be of some integer type, making the whole expression 'count + 1' effectively an integer. Then it is implictly cast back to the type of 'count' with the assignment, and the warning is thus correct.If, instead of "1", you use "24'b1" (I think this is the correct syntax?), I guess the warning should go away? Like: "count + 24'b1".This just shows that Verilog does more of implicit "casts" (like C does in a way), whereas VHDL in general does not. But with the example above, it's a bit trickier than this.If you're using an 'unsigned' type for 'count' in VHDL, for instance, you can absolutely write "count <= count + 1" without any warning. This is because the '+' operator is redefined for unsigned types, and in this context, the '1' litteral is not seen as an integer.As to why 32 bits, it's consistent with what I said above. It's just because the expression implicitly becomes an integer, and integers are likely 32 bits by default in Verilog, just like they are in VHDL (but using integers in VHDL would require explicit casts).

author: aheid
author_rank: Regular Contributor
timestamp: February 07, 2020, 03:40:34 pm
content: Quote from: SiliconWizard on February 07, 2020, 03:34:57 pmGood call, that seems to be it. I should add that the "count <= (count + 1)" line was not written by me, but came with the Radiant skeleton example I used as base.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 07, 2020, 03:48:32 pm
content: Quote from: aheid on February 07, 2020, 03:40:34 pmGood. I think this would qualify as "sloppy Verilog", even though that compiles right (but with a warning) and does what is intended here.

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 04:07:30 pm
content: When you draw out your block diagram, physically, not just mentally, every time you use 'reg', draw a flip-flop. What's connected to D, where is the Clk coming from, is reset synchronous or asynchronous? The compiler didn't like the way you tried to connect a flop to another flop without clocking the second flop. Between modules, I'm pretty sure you can only use wires. Again, I know next to nothing about Verilog.I can't offer any advice about Verilog and this wire/reg issue is one of the reasons I find it difficult to wrap my head around what is happening. Again, that's just me.See section 1.2 here:https://inst.eecs.berkeley.edu/~eecs151/fa19/files/verilog/wire_vs_reg.pdfSection 1.3 deals with regsThere are very specific rules for where wires can/must be used and similar rules for regs.There's a trap in copying code off the Internet in that snippets are unlikely to work without the identical foundation.I like the VHDL 'alias' construct for pulling subfields out of a standard logic vector. Think about the Instruction Register and how source (SR1, SR2) and destination (DR) fields would be in certain bit positions.Code:signal IR : std_logic_vector(15 downto 0);alias Immediate : std_logic is IR(5);alias DR : std_logic_vector is IR(11 downto 9);alias SR1 : std_logic_vector(2 downto 0) is IR(8 downto 6);alias SR2 : std_logic_vector(2 downto 0) is IR(2 downto 0);To me, that is a clean way to name various fields

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 04:27:36 pm
content: Quote from: SiliconWizard on February 07, 2020, 03:48:32 pmI agree, the code seems a little off. In Verilog, especially, I think there is a simpler construction trying desperately to get out.Verilog can absolutely create a 24 bit counter without remnants of 32 bit addition but I think that is settled. Apparently the increment value needs to be specified as a 24 bit value = 24'b1. This makes sense in a way because in VHDL, if I am dealing with a std_logic_vector, I have to do a lot of casting to add '1'. Mainly, the operands need to be numbers - signed or unsigned - but numbers, not a std_logic_vector.Code:PCplusOne <= std_logic_vector(unsigned(PC) + 1);Here, both PC and PCplusOne are declared as std_logic_vector(15 downto 0). To add decimal 1 to a standard logic vector, I first have to convert the signal to an unssigned then do the math and convert the result back to std_logic_vector before assigning it to PCplusOne. Like C casting in a lot of ways...OK, I used to think this was UGLY and there was an unofficial library that would let me do that kind of addition without casting but, as I get used to it, I find it comforting. The compiler still generates a 16 bit adder with PC and decimal 1 as inputs but it is very clear exactly what the programmer expected. I'm getting to like it!STRONG typing is a benefit, not a hindrance.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 07, 2020, 05:30:08 pm
content: Quote from: rstofer on February 07, 2020, 04:27:36 pmYes, and I know it's just an illustration. But in this form, it probably just looks too verbose to many.To avoid this incessant casting all over the place, you just define internal signals with the proper type, and cast only when strictly needed.In your example, I'd have an internal PC and PCplusOne signals declared as 'unsigned'."PCplusOne <= PC + 1;" would be all that's needed, it's compact and besides, it helps making things clearer and convey the intent, in other words, it really leverages the typing system.Then you only cast to std_logic_vector to interface with external ports, so basically just in one place.I almost never use the std_logic_vector type internally in my entities, except for signals that are really to be handled just as zero or one. And even so, I tend to use the boolean type instead, and cast again only from/to external ports in just one place.Just makes your code a lot more compact and easier to maintain, with exactly zero cost.Quote from: rstofer on February 07, 2020, 04:27:36 pmOh yes.

author: RoGeorge
author_rank: Super Contributor
timestamp: February 07, 2020, 05:36:47 pm
content: Quote from: aheid on February 07, 2020, 01:37:05 pmNothing wrong. But then you need to increment the whole 32 bits counter, and wire to the next circuit only the 24 bits you need. Seems very similar to a typecast, but it's not about changing a data type, it's about rewiring a circuit.Quote from: aheid on February 07, 2020, 01:37:05 pmLet's focus only on the registers that gives the error. The toolchain will see in the top.v file you described some registers. A register is built out of D-type flip-flops. A D-type flip-flop is a circuit that, on the rising edge of the clock signal, it copies at the Q outputs what the data present at the D input. Once copied, the flip-flop will memorise the data, and doesn't look at the D input any more until the next rising edge, when it will copy D to Q again, and so on.The typical D-type flip-flop has some more pins, S and R for (asynchronous) set or reset, non Q, as can be seen in the next hand drawing, or in this (random googled) datasheet in figure 3:https://assets.nexperia.com/documents/data-sheet/74HC_HCT74.pdfwhere there are 2 flip-flops in the same case of an IC.An 8 bit register will be made out of 8 D-type flip-flops (FF), where the clock and the reset inputs are usually connected together. To stay with the breadboard you mentioned, an 8 bit register will be 4 x 7474 ICs, each with 2 flip flops inside AND THE WIRES necessary to build the circuit from the right side of the picture:Now, let's get back to the FPGA toolchain.- at some point toolchain reads the line "reg [7:0] sin_val;", take 4 x 7474ICs and insert them in our breadboard- it continues reading, do some other stuff, and at some points it readsCode:ROM_SIN_256 sin_inst(.clk(sin_clk),.addr(sin_addr),.dout(sin_val));This is very close to what a macro does for the preprocessor of the C language, but I will be afraid to call it a macro. On short, the toolchain will look in the module file, and start to generate the circuits described in the module. One of the lines inside the module ROM_SIN_256 is "output reg [7:0] dout". This will synthesise yet another 8 bits register.For our breadboard, the toolchain inserts another 4 IC (meaning another 8 flip-flops). At this point, we have 16 flip flops in 2 x 8 bit registers, one is "sin_val", the other "dout". At this point, the toolchain is left with 3 busses of 8 bits each, databus Z", "databus X", and "databus Y", as seen in the next pic, and doesn't know how to wire them.My guess is that you probably didn't want yet another register in main.v, the one you created with "reg [7:0] sin_val;".However, if you wanted it, then you need to instruct the toolchain how to wire it to the outputs of the "dout" register, and keep in mind the sin_val will be filled with data one clock later than dout (assuming they are driven by the same clock).My point is, in the very beginning, it is very misleading to think of all these as typecasts or macros, or even worst, class instantiation of an object, when in fact we deal here with circuits, wires and clocks.Very soon you'll get use to it, and you'll naturally start to mix software and hardware design techniques, but for now keep thinking about HDL in terms of circuits.

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 06:19:50 pm
content: Quote from: SiliconWizard on February 07, 2020, 05:30:08 pmNot really, I actually coded it that way on purpose.QuoteI can certainly agree with that but I can type pretty fast when I get down to it.QuoteI agree, unsigneed is the way to go but either way, I need to cast signals from one type to another. That's a practice I haven't quite caught on to. When I create a new entity and I use the 'fill-in-the-blanks' creator in Vivado (and ISE), if I declare the signals in the dialog they will always come out as std_logic_vector.Either way, I need to know what type I'm using and why I'm using that type. And I need to know which operators accept the various types. And, yes, unsigned is the right way to do it.

author: rstofer
author_rank: Super Contributor
timestamp: February 07, 2020, 06:54:09 pm
content: Maybe the reason I don't often use unsigned instead of std_logic_vector is the way I think about the hardware. I realize the program counter is an index into memory but that isn't the way I view it. Instead, I think of it as a 16 bit vector with LEDs attached. Nothing numeric about it, it's just a string of bits.A better example might be the accumulator. Sure, it does numeric add and subtract and could be defined as unsigned but it also does AND and OR which are clearly bit-vector operations. I'm not sure what to think about shift because it has meaning in numbers as well as vectors.I think this is why employers have 'style manuals'. They make a decision about this stuff and it's over and done. My indecision is overridden by corporate edict. If I wasn't long retired...I think I'm going to stick with std_logic_vector despite all the reasons to do otherwise. Old people can write their own style manual.I actually used an integer type for the current and next state values on the LC3 FSM. I wanted the state number to match the state diagram. It looks a little weird but it works fine.Code:signal State : integer range 0 to 63;signal NextState : integer range 0 to 63;I still had to cast State to a std_logic_vector to include it as part of a wider diagnostic output to the LEDs. But only the one time.

author: aheid
author_rank: Regular Contributor
timestamp: February 08, 2020, 12:43:19 am
content: Thanks again for the input and discussion. I've gotten some solid suggestions on reading material, and cleared up some syntax confusion.Got my led to pulse with nice sin wave intensity using my own PWM module, yay. Time to do some serious reading before trying something more complex

author: james_s
author_rank: Super Contributor
timestamp: February 08, 2020, 03:11:56 am
content: Quote from: mark03 on February 07, 2020, 03:48:02 amAnd yet almost every self taught HDL beginner who has previous programming language starts trying to code HDL as if it's a program being executed, and it's also the aspect that I found most difficult early on, so cliche or not I tend to mention it.

author: OwO
author_rank: Super Contributor
timestamp: February 08, 2020, 06:59:33 am
content: Yes, before writing any HDL you should have a drawing of the circuit being designed. HDL is often called "designentry" for a reason, as in you are only "entering" into the computer a circuit that is already designed. The diagram is the "master design" while the HDL is only a copy of it, therefore when making changes always do it on the diagram first. In the future when you need to look at your design again, code is much harder to read and reason about than having a well documented diagram of the system that shows you the big picture at once.If you ever learn VHDL, ignore 90% of example code out there. Avoid using "process" except when trying to infer a block ram. Everything should be done as a "signal flow graph" model. You define your signals, then you define drivers for each signal. Example:

author: OwO
author_rank: Super Contributor
timestamp: February 08, 2020, 07:04:08 am
content: The associated diagram of the above design:

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: February 08, 2020, 07:19:16 am
content: QuoteNice tips, Do you have a book or reference for this?

author: OwO
author_rank: Super Contributor
timestamp: February 08, 2020, 07:49:07 am
content: Nah, it's the style taught by a professor at my university.Also btw it's not about "low level" design - I avoid bit level manipulations and use high level types when possible; for example complex value types, library functions for math, etc.However the structure and layout of the circuit - this is what I think must be explicitly spelled out. I want to be sure exactly what each flipflop is driven by, any clock enables used, where all MUXs are, etc.An example of code I don't like:Code:if rising_edge(clk) thenif alumode = 0 thenres <= a + b;elsif alumode = 1 thenres <= a - b;elsif alumode = 5 thenres <= a xor b;elsif alumode = 6 thenres <= a and b;elseif addr != X"ffffff" thenres <= 0;end if;end if;end if;What circuit is this going to actually infer?Most FPGA adders support dynamic add/subtract selection. Is that going to be inferred here or is it going to be a 5:1 MUX?It's not obvious from the code, but res is going to be driven by logic that traverses at least 2 stages of slices in a Xilinx device (adder, then mux). This ruins your Fmax.Can you see the high fan-in clock enable logic?If this is a long process, I have to read the whole thing and look for every instance of assignment to "res", look at all conditionals, and track duplicate assignments to know what res is actually driven by. Instead, something like:Code:resNext <= XXXXX when CONDITION elseYYYYY when CONDITION ......res <= resNext when CONDITION and rising_edge(clk);is far easier to understand.A slow and unoptimized design like the above is still viable with the "process" approach, but what do you do when you want to add pipelining? You kind of have to guess at the structure of the circuit. It's much easier when that is explicit from the start.

author: sporadic
author_rank: Regular Contributor
timestamp: February 09, 2020, 03:44:52 pm
content: Quote from: OwO on February 08, 2020, 07:04:08 amAny software recommendations for creating and managing state diagrams?

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 09, 2020, 04:20:38 pm
content: Quote from: sporadic on February 09, 2020, 03:44:52 pmWant something with a GUI or something that can generate diagrams from a textual representation?For the former, there is DIA (unfortunately not maintained, tends to be clunky to use, but open source). There is XMind. There is yEd Graph Editor (which is the one I currently use the most). Probably a lot more, but those are the ones I use(d).For the latter, there is graphviz. And of course various Latex packages if you ever use Latex.

author: sporadic
author_rank: Regular Contributor
timestamp: February 09, 2020, 05:09:44 pm
content: Quote from: SiliconWizard on February 09, 2020, 04:20:38 pmI can't believe I've never run across yEd while looking for diagramming software. I'd always painfully used DIA in the past. Just watched intro video on yEd and it looks like just what I need. Going to grab it now, thanks!

author: rstofer
author_rank: Super Contributor
timestamp: February 09, 2020, 05:49:41 pm
content: A worthy project is to take some of these constructs, like the FSMs and synthesize them. Then look at the RTL schematic. The synthesizer will warn you if you have inferred a latch but what it won't tell you is whether you have inferred a priority encoder and whether that priority encoder is realized as a long string of logic which doesn't help with Fmax.Here is a comment re: using the 'case' statement rather than a long chain of 'if-elsif-else' statement:https://www.nandland.com/vhdl/examples/example-case-statement.htmlJust for a drill, code a simple FSM with both schemes and look at the RTL schematic. No, I don't know how it's going to turn out. I sure wouldn't use the "when" construct for an FSM with 100+ states. The other problem I have with that approach is that it tends to divorce the actions to be taken in a state from the next-state generation. I then have to scroll down to see what happens as a result of being in a particular state. More to the point, there may be several constructs that use the state information and they could span many pages of code.I think I'm going to stay with the two process state machine, one to clock the next-state and the other combinatorial process to generate the output signals. I don't know how the big kids do it but I like this approach.Code:process(State, BEN, IR,MemReady, Immediate, PSR, Interrupt)begin-- set default values for all signals - many omitted for claritySR2select <= SR2OutSel;GateBusSelect <= GatePC;LD_Reg <= '0';LD_CC <= '0';ALUop <= ALUpassA;case State is<snip>when 1 => -- ADD Instructionif Immediate = '1' thenSR2select <= Sext5sel;elseSR2select <= SR2outSel;end if;ALUop <= ALUadd;GateBusSelect <= GateALU;LD_Reg <= '1';LD_CC <= '1';NextState <= 18;<snip>end case;end process;When the FSM is in state=1, we can see exactly which output signals are generated inside the combinatorial process. The adder is going to do an add operation, we're going to gate the ALU to the bus and load the result into some register (selected the DR field in the instruction) as well as loading the condition codes prior to fetching the next instruction in state 18.Everything is in one place and the operations performed in any particular state are right there.The state info is from the LC3 project I linked above.

author: ralphrmartin
author_rank: Frequent Contributor
timestamp: February 09, 2020, 06:05:08 pm
content: Going back to the original question, and perhaps not being entirely helpful, as this is VHDL not Verilog, I have just been readingDigital System Design with VHDL by M. ZwolinskiIt's rather old, but it does cover quite a lot of useful and helpful ideas at just the right pace (for me, anyway), covering what VHDL can do and how to use it, key elements used in digital design, and how to put them together.Unlike many other books which either teach digital design, or teach VHDL, it treats digital design and VHDL hand in hand.I'd specifically recommend it if you are a software guy getting into FPGAs, for example.

author: rstofer
author_rank: Super Contributor
timestamp: February 09, 2020, 08:35:49 pm
content: This book deals with both VHDL and Verilog in the implementation of a MIPS type processor. They discuss pipelining but they don't provide logic for it.https://www.amazon.com/Digital-Design-Computer-Architecture-Harris/dp/0123944244There is an ARM specific version that deals with VHDL and System Veriloghttps://www.amazon.com/Digital-Design-Computer-Architecture-ARM/dp/0128000562Both are really good but pricey. Again, I need a project in order to keep my interest. Both of these books present enough code to become a complete processor.

author: OwO
author_rank: Super Contributor
timestamp: February 10, 2020, 04:20:39 am
content: Quote from: rstofer on February 09, 2020, 05:49:41 pmI don't disagree that case statements are preferable when you have many possible states. Personally I would restrict it to one or a few signal assignments per process and enforce that every branch of the "case" has exactly the same assignments. Never think of it as "control flow" like in programming; a case statement with signal assignments is a mux.Regarding big state machines, the answer is avoid them in optimized designs. Inherently a big state machine with many inputs will generate a big combinatorial circuit, which is always going to mess up your timing. Instead, design the system as many smaller "building blocks", where each building block may have small state machines.I still prefer to see all possible sources of a signal, rather than all things that "happen" at a state because this way tells me right away what the circuit is like and any possible timing bottlenecks. When I need to reason about the design, I don't read the code, I go back to the diagram.Btw I don't think of it as a single "machine" that does "actions"; rather a circuit that has some state variables, plus some independent "circuit fragments" that data passes through and may behave differently depending on the state. When I look at an output-forming circuit, the possibilities of the circuit are more relevant than other circuits that happen to change their behavior during the same state. In other words, I don't think the output forming logic are part of the state machine, and different output forming circuits may be completely independent (e.g. the part generating sync signals vs the part that computes next synthesizer frequency).

author: rstofer
author_rank: Super Contributor
timestamp: February 10, 2020, 04:47:01 pm
content: Quote from: OwO on February 10, 2020, 04:20:39 amAssuming that ultimate speed isn't a criteria, we need to figure out who/what the code is written for. I have seen the disjointed approach to machine design and I don't see it as being nearly as easy to read as the single case statement generating all of the outputs. Having to look through a few thousand lines of code to find every occurrence of a state variable (even with the editor 'find' feature). Since I view the code as something I write for me to understand, I don't worry much about the difficulty imposed on the toolchain. The compiler writers are pretty smart, they'll come up with a decent solution.For my IBM1130 project, the main FSM is 907 lines of code, 52 inputs, 41 outputs and 111 states. Non-restoring division is probably the worst instruction with 7 states and a 15 count loop within one of them. It's a really good thing I found a pseudo microcode example in a textbook or I never would have gotten this worked out.I realize I could break this up into MANY smaller blocks but it just wouldn't be as clear to the observer what exactly is happening. If I ported the code to one of the Artix devices, I could probably run at 100 MHz (on a Spartan 3E it easily runs at 50 MHz) while the original machine ran at about 400 kHz. Modestly fast for 1965...I see your point about small blocks of code representing small circuits and I realize that with one-hot encoding, my state variables are 111 bits wide (insane register width). Maybe next time I will try the disjointed approach.I'm not sure there are any 'absolutes' in HDL, I think it comes down to choice.

author: coldfiremc
author_rank: Regular Contributor
timestamp: February 12, 2020, 05:09:47 pm
content: HDL is like HTML. Aestethically and syntactically have nothing in common, but conceptually had lots, specially that there's no "Program Counter", file orientation and all code at once, except when explicitly programmer asked for it.

author: james_s
author_rank: Super Contributor
timestamp: February 12, 2020, 05:17:47 pm
content: That's because neither one is a programming language, they're both used to describe something.