For some news, check also:
https://hackaday.io/page/11244-more-microcode-compiler-capabilities
So after some time, I was able to find some time to work on the "MCC" (microcode compiler"). The compiler is now mostly written and is able to compile .mcc files (in a "language" I invented in order to make microcode writing simpler and more intuitive).
I plan to eventually create a separate project for it with more extensive documentation, but for now here is a excerpt from the microcode for CDP1802/5/6 CPU I use for validation, which should give some idea:
//-------------------------------------------------------- // 1802 basic instructions //-------------------------------------------------------- .map 0b0_0000_????; // D <= M(R(N)) LDN: direction = mem2any, sel_reg = n, y_bus, reg_d <= alu_y, if continue then fetch else dma_or_int; .map 0b0_0000_0000; // override for LDN 0 IDL: sample; // dead loop until DMA or INT detected if continue then IDL else dma_or_int; .map 0b0_0001_????; // R(N) <= R(N) + 1 INC: sel_reg = n, reg_inc, if continue then fetch else dma_or_int; .map 0b0_0010_????; // R(N) <= R(N) - 1 DEC: sel_reg = n, reg_dec, if continue then fetch else dma_or_int; .map 0b0_0011_????; // 2 byte branch instructions SBRANCH: direction = mem2any, sel_reg = p, y_bus, reg_b <= alu_y, // B <= R(P) if cond_3X then sbranch2 else next; skip1: sel_reg = p, reg_inc, // R(P) <= R(P) + 1 (no branch) if continue then fetch else dma_or_int; sbranch2: sel_reg = p, reg_lo <= alu_y, y_b, if continue then fetch else dma_or_int; .map 0b0_0100_????; // D <= M(R(N)), R(N) <= R(N) + 1 LDA: direction = mem2any, sel_reg = n, y_bus, reg_d <= alu_y, goto INC; .map 0b0_0101_????; // M(R(N)) <= D; STR: direction = cpu2mem, sel_reg = n, y_d, if continue then fetch else dma_or_int; .map 0b0_0110_0???; OUT: sel_reg = x, reg_inc, direction = mem2any, // DEVICE <= M(R(X)), R(X) <= R(X) + 1 if continue then fetch else dma_or_int; .map 0b0_0110_0000; // override for OUT 0 IRX: sel_reg = x, reg_inc, // R(X) <= R(X) + 1 if continue then fetch else dma_or_int; .map 0b0_0110_1???; INP: sel_reg = x, y_bus, reg_d <= alu_y, direction = dev2any, if continue then fetch else dma_or_int;
The compiler produces 2 blocks of memory, one for the microcode, and one for the mapper that maps higher level instructions (from CPU instruction set). These blocks are then written in possible formats:
- VDHL - for direct inclusion into FPGA development projects (I use old "free" ISE14.7 from Xilinx)
- Intel HEX - pretty much any tool can consume these
- MIF ("memory initialization file") for Altera tools
- CGF ("core generator file") for Xilinx tools
At this point I am writing / debugging the 1802 CPU which I intend to eventually test using the embedded software (monitor/Basic) documented here. Once it starts (somewhat) working, I will share that project too.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.