Chris_C Posted October 23, 2014 Report Share Posted October 23, 2014 Allthough finding ISE an uphill struggle! (but I am getting there) a long term goal is to design and implement my own CPU design. I'm looking to make something small and simple yet also powerful I'd really value peoples thoughts if only just to help get another perspective here's my rough design so far...1 16bit PC4 8bit registers R0 to R3No condition codes1-3 byte instruction codes IIII RaRb NNNN NNNNCCAAAA AAAA AAAA AAAAinstruction bits (IIII)Value (NNNN NNNN)Address (AAA...) where CC is present AAA... is a signed 14bit offset (should address the bus only be 14bit 16kb probably enough?)Ra Register R0 to R3Rb Register R0 to R3Rb16 value 0 or 2 representing 16bit register (0 = R0,R1) (2 = R2,R3)if an invalid Rb16 value of 1 or 3 is used then no 16 bit value is added tothe address (code 3 possible expansion ?)IIII Size Mnemonic Description0000 1 NOP spare ?0001 1 NAND Ra,Rb Ra=Ra NAND Rb0010 1 XOR Ra,Rb Ra=Ra XOR Rb0011 1 AND Ra,Rb Ra=Ra AND Rb0100 1 OR Ra,Rb Ra=Ra OR Rb0101 1 NOT Ra,Rb Ra=Ra NOT Rb0110 1 ADD Ra,Rb Ra=Ra AND Rb0111 1 SUB Ra,Rb Ra=Ra SUB Rb1000 1 SR Ra,Rb Ra shifted right Rb bits (only bottom 3 bits of Rb used)1001 1 SL Ra,Rb Ra shifted left Rb bits (only bottom 3 bits of Rb used)1010 1 HALT1011 2 SET Ra,NNNN Ra = immidiate 8bit value1100 3 PUT ( Rb16 + ADDRESS ) = Ra Ra is stored in address + Rb161101 3 GET Ra = ( Rb16 + ADDRESS ) Ra = contents of (address + Rb16)1110 3 JMPcc Ra,Rb, PC+(A14-A0 signed) where cc (top 2 bit of address) = eq ne gt lt1111 3 JMP Rb16 + ADDRESS PC = address + Rb16Virtual instructionsJMP ADDRESS is actually JMPeq R0,R0, ADDRESS Quote Link to comment Share on other sites More sharing options...
Chris_C Posted October 23, 2014 Author Report Share Posted October 23, 2014 I decided that no one could possibly require more than 16kb of data ! This allowed me to tidy up some of my addressing ideas and I made invalid index register use clearer1 16bit PC4 8bit registers R0 to R38 bit data bus14 bit address bus (16kb)No condition codes1-3 byte instruction codes IIII RaRb NNNN NNNNCCAA AAAA AAAA AAAAinstruction bits (IIII)Value (NNNN NNNN)Address (AAA...) top 2 bits are condition code if needed (eq,ne,gt,lt)Ra Register R0 to R3Rb Register R0 to R3Rb16 value 0 or 2 representing 16bit register (0 = R0,R1) (2 = R2,R3)rbX invalid Rb16 value of 1if an invalid Rb16 value (RbX) of 1 is used then no 16 bit value is added tothe address (code 3 possible expansion ?)IIII Size Mnemonic Description0000 1 NOP spare ?0001 1 NAND Ra,Rb Ra=Ra NAND Rb0010 1 XOR Ra,Rb Ra=Ra XOR Rb0011 1 AND Ra,Rb Ra=Ra AND Rb0100 1 OR Ra,Rb Ra=Ra OR Rb0101 1 NOT Ra,Rb Ra=Ra NOT Rb0110 1 ADD Ra,Rb Ra=Ra AND Rb0111 1 SUB Ra,Rb Ra=Ra SUB Rb1000 1 SR Ra,Rb Ra shifted right Rb bits (only bottom 3 bits of Rb used)1001 1 SL Ra,Rb Ra shifted left Rb bits (only bottom 3 bits of Rb used)1010 1 HALT1011 2 SET Ra,NNNN Ra = immidiate 8bit value1100 3 PUT ( Rb16 + ADDRESS ) , Ra Ra is stored in address + Rb161101 3 GET Ra , ( Rb16 + ADDRESS ) Ra = contents of (address + Rb16)1110 3 JMPcc Ra,Rb, ADDRESS where cc (top 2 bit of address) = eq ne gt lt1111 3 JMP Rb16 + ADDRESS PC = address + Rb16Virtual instructions provided byPUT (ADDRESS),Ra PUT ( RbX + ADDRESS ), RaGET Ra, (ADDRESS) GET Ra, ( RbX + ADDRESS )JMP ADDRESS JMP rbX, ADDRESS Quote Link to comment Share on other sites More sharing options...
johnbeetem Posted October 23, 2014 Report Share Posted October 23, 2014 Since you asked for comments... 1. I notice that you don't have a mechanism for subroutine calls and returns.2. It's hard to get much performance from an 8-bit data path.3. You might consider a stack machine. It's an easy compiler target. Quote Link to comment Share on other sites More sharing options...
Chris_C Posted October 23, 2014 Author Report Share Posted October 23, 2014 These are good points especially subroutines and returns (can't see how to fit it into the current set) I decided to restrict it to an 8 bit bus initially (there may be son and even granson of this cpu!) to reduce complexity and also to ensure it doesn't take up lots of room... While I can see the attraction of stack machines (from a hardware designers point of view) I've never particularly enjoyed programming them, this will be a machine I'll code in assembler and don't have a need for a C compiler That said they are all good points especially subroutines / return, thank you very much for your constructive points. hmmm NOP and SPARE - I did leave myself wiggle room for call / return.... (but this would need a call stack) Quote Link to comment Share on other sites More sharing options...
hamster Posted October 24, 2014 Report Share Posted October 24, 2014 These are good points especially subroutines and returns (can't see how to fit it into the current set) AND R0,R0 is equal to OR R0,R0. You can get four out of there. What does "Ra = Ra NOT Rb" do? You might be able to get Ra = NOT Ra Ra = NEG Raplus another 8 spare instructions. Quote Link to comment Share on other sites More sharing options...
Chris_C Posted October 24, 2014 Author Report Share Posted October 24, 2014 AND R0,R0 is equal to OR R0,R0. You can get four out of there.Nice spot! I missed that! What does "Ra = Ra NOT Rb" do?Ahem its a typo I meant Ra = NOT Rb or possibly Ra = NOT Ra 8 spare? I need to look again when I get home ! Thanks great feedback! Quote Link to comment Share on other sites More sharing options...
alvieboy Posted October 24, 2014 Report Share Posted October 24, 2014 Chris, As someone who is also implementing a CPU, some words of advise: a) Don't use variable sized instructions, unless you want to have your fetch unit as big (almost!) as the rest of the design. Get rid of seldom-used instructions, like NEG. It can be accomplished with other instructions.c) Focus first on basic, then if your ISA space allows, add other instructions. This may come at expense of a larger decode, but pays off.d) Pay attention to immediates (either for arithmetic or offsets). This is the *most* space consuming, both HDL and code-size.e) As johnbeetem already said, you need a calling infrastructure, as well as a calling convention. This is of great importance to get right at first attempt.f) Condition codes are extremely important, and you need them or an indirect way to generate them. They are used for path selection and value setting. We can further discuss this by email, if you like. Alvie Quote Link to comment Share on other sites More sharing options...
Chris_C Posted October 24, 2014 Author Report Share Posted October 24, 2014 Obviously condition codes are useful, but for some reason I was attempting to see if they were really needed...I've never seen the point of fixed(immediate) offsets ?I did intially attempt a fixed size of all instructions but kinda seemed to end up with lots of wasted space for a bunch of instructionsI'm trying to weigh up if a single return address is sufficient or if I need to implement a call stack I'll PM you with my email, it may be that we can help each other by batting ideas back and forth! Quote Link to comment Share on other sites More sharing options...
Jaxartes Posted October 26, 2014 Report Share Posted October 26, 2014 Well, condition codes as such are definitely not needed; many architectures don't have them. But they have some kind of conditional instruction. Oh, I could see doing without it but it's more convenient. A couple of approaches I've seen to doing conditionals without a conditional flag: checking a register directly (jump if Ra > 0); or skipping the next instruction. Skipping would be made trickier by having variable length instructions, but could still be done. Including a stack in your instruction set isn't necessary, if you're willing to use ordinary address arithmetic and an index register to accomplish it. Then what you'd really need to add is an instruction to save PC to a general purpose register, either by itself or combined with a jump. One thing if you're using a small data path size like 8 bits, is you'll want a way to build wider operations out of it. A common way is to use a carry flag. If you really want to do without conditional instructions, I have some idea how it might be accomplished, here's an example:"if (A >= 0) then go to T else go to E" might be done as: shift A right 7 bits // extract the sign bit subtract 1 from A // now, if it was negative, we get 0; if positive, we get 255 build a target pointer P: P = (A & T) | (~A & E) and jump to P But conditional logic is such a common thing to program, you'll probably want it to be easier than that. Maybe a single instruction, "if the last operation's result was in the range 1-127, copy A to B; otherwise do nothing"? Quote Link to comment Share on other sites More sharing options...
Chris_C Posted October 27, 2014 Author Report Share Posted October 27, 2014 yes, condition codes it is! I don't think life without at *least* a carry flag would be much fun! I'm still trying to work out if I really need a stack, while it would make call/return and even parameters easier - I'm still investigating alternatives. Quote Link to comment Share on other sites More sharing options...
hamster Posted October 29, 2014 Report Share Posted October 29, 2014 When I was playing around with ISAs I found some of these big decisions were greatly influenced around how you intend to handle interrupts and traps. If you have carry flags, then you need to be able to save the carry flags somewhere, and then you need a way to restore the flags when returning from interrupts. I have programmed Assembler on a DG Eclipse, and really liked that it had no conditional jumps, just the conditional skip next instruction (which sort of like worked as a prefix) and unconditional jumps. For microcontrollers I liked PICs bit-test-and-skip instructions, as it allowed all the flags to be held in the main memory map. So an ADD would update the carry flag, which is bit 0 in address 3, and then a BTFSC 3, 0 could be used to test if the carry flag was set. A few macros for the STATUS register and the 'C' bit made things cleaner, but it is quite a simple implementation.Start movlw b'10000000' ;set first LED lit movwf LEDPORTLoop bcf STATUS, C ;clear carry bit call Delay ;this waits for a while! rrf LEDPORT, f btfss STATUS, C ;check if last bit (1 rotated into Carry) goto Loop ;go back and do it again goto Start Quote Link to comment Share on other sites More sharing options...
EtchedPixels Posted October 30, 2014 Report Share Posted October 30, 2014 You don't need call return providing you can get access to PC somewhere. Ultimately however all 8bit microprocessor designs that pursue elegance evolve into a 6809 (and I say that as a Z80 fan) You don't actually need a lot of instructions to get a pretty effective processor, but how easy it is to program for and how short the code is are rather different questions. The 6502 for example is pretty minimal and quite effective (if a pita to program), while the 8008 is miniscule but does lack a proper stack and arbitrary depth call/return In your instructions set I'd say you can drop NAND (you have NOT and AND), you can drop NOT (XOR). You can in theory even drop SUB as you have ADD and XOR (thus NOT). Some of the bigger machine word systems also didn't have a jump instruction as such, you merely need store-conditional and you can treat program counter as a register. That also makes stacks or register link calls trivial SL/SR can both be replaced with the more useful rotate operation which is as cheap to implement but can do shift left/shift right/ rotate left/rotate right if combined with AND I suspect you can implement call/return and the stack ok as you've got register relative ops so you can use a register of your choice as stack. The only ugly would be that you basically end up doing "load register with constant computed at link time", stick it in (Rstack), Rstack += 2, JMP xx, and your 'RET' is slightly ugly too Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.