Well, one of my life goals (according to my CV) is to create my own processor in an FPGA.
Well, I've finally set out to accomplish this goal. So far, VHDL has been very mind expanding. Things happen sequentially, yet at the same time. Wrapping your head around it can probably be compared to understanding recursion in programming terms.
But anyway, I've finally got to where I can synthesize my CPU design and put it in an FPGA, load it's internal memory from an mbed/arduino/whatever and finally execute a stream of instructions... Of course it's not done, the only instruction supported right now is
mov reg, immediate.. but it's a start. There is still a ton of work to be done with it, but hopefully it should be halfway usable as a processor in the next week or two.
If you're curious about the source code of my TinyCPU project, the code is at opencores
For reference, TinyCPU has the following goals:
- Mostly single cycle instructions
- Von Neumann architecture (code is data and vice-versa)
- 8-bit processor (8 bit registers and operations)
- 16-bit address bus (capable of accessing it by using segment registers similar to the 8086)
- Be simple code and it has to fit within my 250K gate Spartan 3E
It's been about 2 weeks since I set out to conquer VHDL and I think I'm finally to the point to where I can say I'm familiar with VHDL. Still learning a lot with each piece of code though.
Basically the learning curve of VHDL is so steep not because of VHDL as a language, but rather because describing hardware is much different from creating software. There is no real easy way to get over the learning curve either without persistence and practice.
So anyway, now as a learning project I'm making a super tiny CPU for my FPGA. I both hate and love VHDL. There is a ton of boiler plate code it seems like, and yet it's so powerful and expressive in describing hardware.
For instance, my simple register file for my CPU totals up to only 30 lines of code... and now imagine describing such a circuit with just logic gates as a circuit drawing:
entity registerfile is
Write:in std_logic_vector(7 downto 0); --what should be put into the write register
SelRead:in std_logic_vector(2 downto 0); --select which register to read
SelWrite:in std_logic_vector(2 downto 0); --select which register to write
UseWrite:in std_logic; --if the register should actually be written to
Read:out std_logic_vector(7 downto 0) --register to be read output
architecture Behavioral of registerfile is
type registerstype is array(0 to 7) of std_logic_vector(7 downto 0);
signal registers: registerstype;
writereg: process(Write, SelWrite, UseWrite, Clock)
registers(conv_integer(SelWrite)) <= Write;
Read <= registers(conv_integer(SelRead));
Honestly, it might should be more complicated than I made it, but I can already tell describing hardware in VHDL is going to be much easier than describing it in kcircuit.
Also, I actually have found that following TDD principles makes a lot of sense when describing hardware. Writing tests first shows you quickly how many possible ways your component will be used and allows you to develop and make sure it satisfies all of your needs.
I've never wrote tests first in software, but in hardware it actually seems more intuitive than writing them later.