
Designing a CPU in VHDL, Part 6: Program Counter, Instruction Fetch, Branching - skywalker_
http://labs.domipheus.com/blog/designing-a-cpu-in-vhdl-part-6-program-counter-instruction-fetch-branching/
======
choudanu4
Would anyone familiar with the various qualities of FPGA boards care to weigh
in on how to pick a good development board for this project? I personally know
nothing about FPGA specs.

Additionally, the first blog post in this series can be found at
[http://labs.domipheus.com/blog/designing-a-cpu-in-vhdl-
part-...](http://labs.domipheus.com/blog/designing-a-cpu-in-vhdl-
part-1-rationale-tools-method/)

~~~
jamieiles
The Terasic DE0-nano ([http://www.terasic.com.tw/cgi-
bin/page/archive.pl?Language=E...](http://www.terasic.com.tw/cgi-
bin/page/archive.pl?Language=English&No=593)) is a great board for soft CPU's.
It's cheap, has a decent size FPGA and external SDRAM. The Altera tools are
free and run under Windows/OSX/Linux.

I've used this board for my own soft CPU ([http://jamieiles.github.io/oldland-
cpu/](http://jamieiles.github.io/oldland-cpu/)) and it's a rewarding project!

~~~
alain94040
Happy to provide some quick feedback on your coding style:

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;

end

If someone knows of a community like HN that can write great Verilog, let me
know.

~~~
jamieiles
Thanks for the feedback. With regards to initial blocks, the advantage of
using them on an FPGA design is that it's just the initialization value of the
registers in the bitstream so doesn't have any real cost, but doing it with a
reset would take logic, no? Does that really qualify as multiple drivers?

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?

~~~
alain94040
Doesn't your design need to handle reset anyway? If so, then the initial block
is redundant. If your design doesn't have a reset, that's highly unusual.

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.

------
alain94040
Not a great codebase, if you are trying to learn the industry's best
practices. For instance, I recommend naming your RTL signals based on which
pipeline stage they belong to. Assuming this thing even has a pipeline.

~~~
nhaehnle
So, where _is_ a great codebase for somebody who wants to learn?

~~~
gluggymug
Tools vendors each have coding guidelines that their stuff likes. At the RTL
level, industry guys like myself just follow them like puppies due to fear of
something in the tool chain breaking.

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...](https://www.doulos.com/knowhow/vhdl_designers_guide/rtl_coding/)

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.

~~~
sliverstorm
_industry guys like myself just follow them like puppies due to fear of
something in the tool chain breaking_

There's also value to a consistently styled codebase.

