All: when it comes to running VHDL simulations I'm starting from absolute zero. I'd be happy to hear of tips, suggestions and perhaps pointers to tutorials for running simulations / test benches on the Altera Quartus II software. My confusion already starts at the constraints file.
Start slow, it will take time. I recommend you get an FPGA devboard that has some tutorials that you can just load and blink an LED first, that is the "hello world" equivalent for FPGAs. Getting the full end-to-end process working quickly is really important, even if you don't understand all the pieces yet.
I have only ever once looked at Altera's FPGA software, and that was in 2011. For better or worse, I went with Xilinx. I'm sure Quartus can create the TB (test bench) boiler-plate stuff, and I have to image they have some sort of simulator that lets you see the signal waveforms and such.
As for the constraints file, keep in mind that an FPGA is a big pile of circuits and I/O that get configured into the circuit you describe. The constraints file is where you specify what physical I/O pins on the FPGA is connected to the specific "net names" (the term "net" comes from schematic capture and PCB layout, and is a named wire, essentially). You can also specify electrical constraints, like that an I/O is 3.3V or 1.8V, etc. For clock input signals (usually you have an external oscillator providing a clock input to an FPGA), you must also specify the frequency of the clock so the synthesizer can perform the proper propagation delay calculations. You don't need a constraints file until you want to load your design onto a real FPGA. You will need a schematic and FPGA pin-out documentation for this task.
My coding style is also influenced by this project: https://github.com/wfjm/w11
That is an interesting project, thanks for the link. It looks very clean and there are definitely some things in there I have not seen before (the "alias" type for example). I'm constantly looking for better ways to do HDL, to make it easier to read and manage, etc. so I'll be experimenting with some of that and maybe adopting some new methods.
My understanding of variables and signals in VHDL is as follows. When used for simulation, the VHDL runtime keeps an event queue with the next, current and previous state of all signals. Assigning a signal reads from the current state and writes to the next state. What is 'current' shifts continuously forward as simulated time progresses. Variables only exist inside a process block and are like regular variables. It would seem that variables keep their value from event to event (i.e. process blocks in simulation are "closures") and if one relies on this the block becomes non-synthesizable. In my "*_cmb" process block code all variables are re-initialised for each event (i.e. the process blocks are pure combinational) and this can be synthesised, or so it seems.
I try not to think or HDL in terms of "programming", or even make correlations to programming. It was a programming mind-set that got me into trouble with the F18A HDL, and only after I stopped thinking in terms of "code", and started thinking in terms of "how would I do this with 74LS logic?", only then did I start making progress again.
Assigning a signal in simulation is expensive (it requires updating the event queue) and according to Gaisler some 100x slower than simply assigning a variable. Hence I keep all my intermediaries in variables, even though my designs are so small that I probably won't notice the difference.
It depends on the size of the project. I did a simulation on an entire Joust SoC that I wrote without too much trouble. I would be careful when adopting claims like that one. In most cases, your simulations are so small that you won't notice. Then again, I have never simulated a design with variable vs signals. I just know that my simulations are typically so fast that it was not an issue.
My understanding is that synthesising was something that was later overlaid on the VHDL language (and is arguably a language in itself). What constructs are being recognised as what circuit seems to me to be a bit of a black art, with differences between tools and changing as technology progresses. In effect, my *_cmb process blocks are truth tables written up like code. It would seem that toolchains have learned to recognise this (and even the 15 year old synthesiser shipped by Atmel/Microchip seems to handle it well).
You can think of synthesizing as being roughly analogous to compiling. The synthesizer reads the HDL and infers logic, like muxes, counters, comparators, registers, memory, ROM, RAM, etc. You should always read the output of the synthesizer carefully to make sure it found the circuits you are trying to describe with your HDL. After all, that is what HDL is, describing hardware. Thats why I think most people avoid the language constructs that do not correlate to hardware.
There is then a step where the results of synthesis are mapped to an actual device, and FPGA resources are consumed. This is called "place and route". From that there is another step where the bit-stream is produced. The tools like ISE, Vivado, Quartus, etc. mash all this together, kind of like a compiler will call the linker for you.
Now that I have written some code I think that I did not quite understand Gaisler: I'm still writing code with each register in a separate process statement. This is not necessary: all the registers for the timer could be in a big single record, as could all the registers for the transmitter. Doing so keeps all related code together and this is perhaps easier to read and maintain. Once I have working code I will try that refactoring and see if makes sense.
There are many ways to organize your HDL, format your HDL, etc. and coming up with an organization and style that makes sense to you is the most important. After that, try for readability and understanding. The parallel nature of hardware makes it hard to follow when presented in a form that resembles "code". IMO a schematic is far more superior for hardware, which is probably why schematics were invented. Try to organize you code into blocks just like you would in real hardware.