In our undergrad CS curriculum, the compiler course is mandatory. Our
intent is not to train compiler writers. Rather we call it an
"integrative experience." It ties much of our curriculum together as
a learning experience.

I taught it several times a few years ago. I used a tiny
Pascal/C/Ada-like language that I tweaked every year. We did "by
hand' scanners and RD parsing because the implementation was spread
over a semester and scanner and parser generators came too late. We
targeted an invented architecture---a 16-bit MIPS-like RISC with a few
CISC instructions (call/return, integer multiply, divide). I wrote an
assembler that generated binaries and a binary-level machine emulator
(the reason for all that work is down two paras). I provided these to
the students along with an "architecture manual", about 10 pages
patterned after an MC68000 manual I had on my shelf. I also specified
an IL to use because it meshed with the course objectives. I game
them much scaffolding code for the IL so that they had enough time to
generate IL and then generate assembly code from that.

One year I had a student do a source level debugger as an independent
project. This was attached to an API that I offered in the emulator,
which simulated programmed traps. He started with his own compiler,
had fun, and learned a lot.

My reasoning for the emulator approach was that our students don't get
much practice at assembly programming and debugging, and I did not want
my course to be their baptism. The assembler and emulator were
trivially easy to use and pumped out good trace and error information.
The other benefit was that they could run anywhere, so there were no
lab or license constraints.

The kicker is that our EE folks had some students implement the
"fictional" processor in VHDL. They simulated it successfully, but at
that time PLDs were not big enough to reasonably hold the whole thing.
Now they are. I think there would be a lot of enthusiasm generated by
having the architecture/HDL course implement a physical processor while
the compiler course implements the compiler, but other things are
pressing.