Dave and I spent all of one late night implementing the first generation (unpipelined) of our 552 project, a 16-bit MIPS processor in Verilog, and then we spent a couple hours this afternoon debugging it. Around 5:15 we ran into a snag:
The assembler we were provided was for a slightly different instruction set architecture than the one we were required to implement. Specifically, in that other ISA, PC-relative branch offsets assumed a least-significant bit of
0 and thus didn’t waste a bit in the instruction for that zero. As a result, the next PC calculation (for that ISA) would be
PC < - PC + 2 + (sign ext. Immed. << 1).
This is a problem, because Our ISA is byte-addressable, and says the PC calculation should be
PC < - PC + 2 + sign ext. Immed. (See beqz instruction for an example.)
Those of you familiar with computer architecture will recognize this as a severe problem: The assembler is generating offsets to odd byte addresses, due to the off-by-one-bit error, while all of our instructions are word-aligned.
On the upshot, I was able to hack around this in the assembler source and get a working version. Plug in the new binary, fix a minor bug in the parameterization of our sign extender and voila:
This is the (admittedly meaningless out of context) output of running the branchTest test program (assembled by my modified assembler).
To see the full output and verify perfect branching functionality for yourself, here is a link to the full waveform [PDF].