Designing a CPU in VHDL, Part 6: Program Counter, Instruction Fetch, Branching
labs.domipheus.com
labs.domipheus.com
Additionally, the first blog post in this series can be found at http://labs.domipheus.com/blog/designing-a-cpu-in-vhdl-part-...
I've used this board for my own soft CPU (http://jamieiles.github.io/oldland-cpu/) and it's a rewarding project!
Please don't use initial blocks to initialize values, use an always block with reset. That will also solve the issue of having multiple drivers per signal (bad). Also, don't load memories from the RTL, do that from the test bench (using hierarchical references).
initial begin
$readmemh({`OLDLAND_ROM_PATH, "decode.hex"}, microcode, 0, 127);
rd_sel = 4'b0;
update_rd = 1'b0;
alu_opc = 5'b0;
branch_condition = 4'b0;
alu_op1_ra = 1'b0;
alu_op1_rb = 1'b0;
alu_op2_rb = 1'b0;
mem_load = 1'b0;
mem_store = 1'b0;
mem_width = 2'b0;
pc_plus_4_out = 32'b0;
instr_class = 2'b0;
is_call = 1'b0;
update_flags = 1'b0;
update_carry = 1'b0;
cr_sel = 3'b0;
write_cr = 1'b0;
spsr = 1'b0;
is_swi = 1'b0;
is_rfe = 1'b0;
i_valid = 1'b0;
cache_instr = 1'b0;
exception_start_out = 1'b0;
endIf someone knows of a community like HN that can write great Verilog, let me know.
There are a lot more "news" esk hardware design places as well but I'm assuming you're looking closer to stack overflow/github of HDL rather than the slashdot/reddit of HDL?
If you want HDL best practices any of the resources you can get your hands on from http://www.sutherland-hdl.com/papers.html <-- those folks are excellent
and I would highly recommend this book: http://www.amazon.com/SystemVerilog-Verification-Learning-Te...
For the memory loading, I don't know how you'd infer a ROM another way - aren't hierarchical references only supported in simulation/test benches?
If your target wasn't an FPGA (but an ASIC), the initial block would be completely ignored, so who knows in what state your design would start. FPGAs are nice, they let you specify initial values. Real chips don't. Just put all initial values in your reset clause, in the same always block you assign those registers. Let the FPGA compiler optimize the logic if it can, or infer a mux if it must.
https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=...
http://www.digilentinc.com/Products/Catalog.cfm?NavPath=2,40...
The DE0-Nano-SoC, which has an FPGA and a dual-core Cortex A9 might be a good option if you wanted to get started with Altera parts:
https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=...
The analogous Xilinx board is probably the Zedboard:
Finally, you might consider the Lattice Semiconductor iCE40. There are two dev boards (small and large, both very cheap):
http://latticesemi.com/iCEstick
http://www.latticesemi.com/en/Products/DevelopmentBoardsAndK...
They are especially attractive since they have the only fully open source toolchain:
https://github.com/cseed/arachne-pnr
Have fun!
Perhaps the better sounding term would be "engineering practices" rather than "industry practices". If it's a hobby, you still want to get a good result out of your effort. That principle in industry still applies to the hobbyist IMO.
The signal names issue that alain94040 mentioned was just an example of one problem with the code.
Assuming the desired result is to get running on an fpga, I think you need to take a step back for a second and look at the target environment you want to run on and plan out how it will all work.
The end result is on FPGA, yes. Still a long way before that works. And I'll make sure any massive screwups are documented in next parts, those are the best parts (and, probably most valuable) to write about :)
It does have a pipeline BTW.
Industry is so different I don't know where to start complaining.
Xilinx tools are not used for simulation usually because they suck and we generally pay those other tool vendors for their stuff so we might as well use them.
Given that newbies don't want to pay, maybe Xilinx is the best. I don't know much about the free stuff.
Looking at previous posts, there is so much behavioral code everywhere. We don't write a lot behavioral stuff in VHDL usually. There are higher level languages for behavioral code. Once again, you probably have to pay for those tools so maybe you have no good choices other that behavioral VHDL.
IF generic you are stuck with the Xilinx behavioral VHDL, I still would NOT write the behavioral stuff to be a cycle accurate representation of the design. You are just as likely to make a mistake in the behavioral as the RTL. Then when you test the behavioral model against the RTL you will spend half your time debugging the behavioral side. Thinking ahead really helps.
The whole approach is wonky from the start. If it were me I would think about the project as a whole and plan ahead. The design is complex in terms of verification. We always assume that every design is complex to verify! If not you wouldn't need HW in the first place.
There will be lots of tests. How does the test bench run a big suite of tests and report failures? You do not want to look at waveforms unless your test finds a failure. This blog jumps straight to waves!
I would start from the whole design first. Figure out the interfaces. Then try to express those interfaces in terms of transactions.
In fact, maybe don't even start writing VHDL as an expression of the design. Most times in industry we design via documents first. Docs express how the HW will work at a high level and how it will be verified. It breaks the design down into modules. It explains the interfaces between modules. These interfaces become possible points for the verification to look at. The test bench compares the simulated result with a golden reference when it sees a transaction event at the interface and reports a mismatch.
The point is create project infrastructure first via planning. Have a big picture view of how it's all going to be thoroughly tested automatically each time new code is committed. In industry on top of directed tests, we use constrained randomized tests. We have to determine whether we have covered everything. So we need functional coverage. All this is designed first BEFORE we play around with flops.
We can tolerate a lot of craptastic VHDL/Verilog code in industry because at the higher levels it looks neat and tidy and it is all tested vigorously.
Basically don't follow any stuff from academia because I would bet those guys have never delivered a commercial product. Educational material from tools guys is almost as bad for similar reasons. No one can hold your hand so you have to use your brain.
I probably vented too much here. It's just tough to see engineering done badly.
You know how in software you always say, "We don't have time for that"? Well, it's a lot harder to get away with skipping it in HDL.
The point about documentation is valid. However, as I've has no training at all in this, I'd be writing a document that basically has no value. After this project has come to it's conclusion, I'll probably go try again using processes/methods learned.
Thanks again for the feedback :)
You don't have to do it the conventional way.
It's just that from my perspective, I can only focus on the future problems. I am too traumatized from the HW experience! I almost rewrote a couple of my points again just now.:)
You are documenting via your blog in a sense. It has value. It is a high level representation of your plans for the project.
Then we complain to them when it misbehaves anyway. A quick google will you find some guides.
https://www.doulos.com/knowhow/vhdl_designers_guide/rtl_codi...
On top of that we had company specific style guides. Having jumped from company to company, each one is different here and there.
To be honest, I think we tended to avoid looking at other people's code when we could! Its like having to wipe someone else's butt. It all looks terrible. Everyone can pick on someone else's stuff.
Having said all that, the basic principles of engineering apply:
- Nice separation between the design and the test bench.
- modularity within the design itself.
- A convention of signal naming that will assist the verification process. Eventually they get thrown a waveform when something has gone wrong. They need to look at signal names that aren't some random alphabet jumble.
- Parameterize variables so they can be reconfigured easily.
etc.
There's also value to a consistently styled codebase.
Maybe it's time for me to add another one: good Verilog RTL coding style, or basic RTL rules for Verilog... Based on the kinds of mistakes I see online, it would be easy to cover initial blocks, multiple assignments, etc.
EDIT: just started https://en.wikibooks.org/wiki/Programmable_Logic/Verilog_RTL... . For now, just contains placeholders for the items I want to cover, but feel free to add to the list, that's the whole point of a wiki.