Design Progress
Programming update: I wrote a simple microcode assembler, and used it to implement a dozen or so common instructions. Then I wrote a few simple programs using those instructions, to count through a loop a fixed number of times, and then branch somewhere else. Woohoo, it’s a computer! I still need to flesh out the microcode assembler a bit more, and get/write a regular program assembler. Since my instruction set is intentionally similar to the 6502, I’m looking at getting an open-source 6502 assembler, and then hacking it as needed for my purposes. Is it enough to assemble all code to an absolute address, or do I need to support the idea of relocatable code, libraries, and linking?
ALU musings:I had planned to use a 74LS181 ALU, and my Verilog model reflects this. I’m now realizing it has a couple of drawbacks. For one, its A=B output is asserted true when the result of the ALU operation is (binary) 11111111, not 00000000 as you would expect from testing equality by computing A-B. I can get around this by testing for equality by computing A-B-1 instead (the chip supports this as a single ALU op), but then I can’t use the result of other non-compare operations to see if they’re zero. For example, a handy pattern would be to sit in a loop, decrementing a counter each time, and branching back to the top of the loop if the counter isn’t zero:
LDX #04
LOOP: ; do something useful
DEX
CMP #00 ; '181 would require an explicit compare against zero here
BNE LOOP
I need to test for zero (and equality) by testing if the ALU output is 00000000, which I can do with an 8-input NOR gate, and ignore the ‘181’s A=B output. Bing! My chip count just increased by one.
I also realized I need an overflow flag from the ALU, to signal when the result of a signed addition/subtraction is outside the range -128 to +127. The regular carry flag performs a similar job for unsigned arithmetic, but is no help here. An overflow flag can be constructed from XOR-ing some of the input bits with the output and carry, but that would add even more chips to the design.
Enter the 74LS382. It’s very similar to the ‘181, but it jettisons the useless A=B output, and provides an overflow output instead. It also requires just 3 mode select input lines, compared to 5 needed by the ‘181, reducing pin count and required microcode space. It does this by providing fewer functions that it can compute, but it has all the important ones. The only useful functions on the ‘181 not supported by the ‘382 are bitwise negation (1’s complement) and left shifting. You can simulate bitwise negation by XOR-ing with 11111111, so that’s no problem. Left shifting can be accomplished by adding a number to itself, although given my design, that will require an extra clock cycle to copy the number to the temp register first. Given that I was planning to implement right shifting as 7 left shifts, then doubling the cost of left shifts is a problem. But if I can find a work around for right shifts, then I’ll switch my design to use the ‘382.
Interrupts: Bill Buzbee suggested I look at what it would take to support interrupts. I need to find a good source for explaining the theory and practice of interrupts on similar 8-bit computers, because it’s not totally clear to me how they’re intended to be used. My possibly broken understanding is that an external interrupt signal prevents the CPU from loading the next program instruction. Instead, it checks an interrupt vector for the address of an interrupt handler to run. Presumably the vector is stored in RAM rather than ROM, so application programs can install their own interrupt handlers. The interrupt handler would do, um… something about the interrupt. Finally, control would return back to the original program at the point where it left off.
I think this implies that the interrupt handler saves the current state of the registers and condition codes, and restores them when done. This could be a problem, since my design lacks any way to set the condition codes directly. It also implies a way of preventing another interrupt from happening while in the middle of processing the first interrupt. And it implies a way of signaling that the interrupt handler is done.
I guess the whole process could be viewed as a forced subroutine call. It wouldn’t be hard to create a machine instruction that does something similar to JSR, but with indirect addressing, and an implied address. The tricky part would be inserting this instruction into a running program in response to the interrupt signal. Maybe a mux on the input to the OP register, and use the interrupt line to select between the memory data bus and a hardwired IRQ opcode?
Be the first to comment!No comments yet. Be the first.
Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.