13
\$\begingroup\$

I am building a simple 16-bit CPU in Logisim and have the ALU ready and the opcodes that I want to have. Now I find it really hard to find the right coding for the commands so that the different subcircuits (e.g. logic, arithmetic) don't need all control wires (that build up the coding) as input, but as few as possible. Are there any strategies or methods that help with an efficient opcode design?

thx in advance

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Build your ALU first, and see what control wires it needs. Then wire them directly to the "current instruction" register. Same for memory access control logic, and any other major classes of opcodes. Then use whatever bits are left over to select which subcircuit is activated. \$\endgroup\$ Commented Jan 28, 2015 at 5:34
  • 2
    \$\begingroup\$ There is also the original paper from Ken Chapman of his 8-bit programable statemachine KCPSM aka PicoBlaze. It describes how he choose instructions and designed the ISA. dc.uba.ar/materias/disfpga/2010/c2/descargas/… \$\endgroup\$
    – Paebbels
    Commented Jan 29, 2015 at 3:30

6 Answers 6

10
\$\begingroup\$

I think it is a good approach to study some other instruction sets.

A small one would be the MSP430 from TI it is a 16bit Processor with about 22 instructions.

http://www.physics.mcmaster.ca/phys3b06/MSP430/MSP430_Instruction_Set_Summary.pdf

You could also look into the Atmel AVRs they have also a quite small instruction set.

In a little project of mine I tried to develop a simple 32 bit processor in VHDL with a small instruction set (14 instructions):

http://www.blog-tm.de/?p=80

Due to my current free time it is not fully finished. The instructions are implemented but two are not tested and maybe some status flags are missing.

\$\endgroup\$
2
  • \$\begingroup\$ But I didn't find something where I could see what the actual encoding is and why it was chosen to be like this. \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 23:16
  • \$\begingroup\$ You can find the actuall encoding in the repo: github.com/TM90/MISC_Processor/raw/master/Documentation/…. The reason I choose these encodings in a way that the logic in the instruction decoder got minimal. \$\endgroup\$
    – TM90
    Commented Jan 27, 2015 at 23:18
7
\$\begingroup\$

Study (but don't replicate) the ARM approach to instruction coding. It's heavily prefix-orientated (like the Huffman tree approach recommended by Dzarda) and highly uniform in terms of where the register select part of the instruction is.

The unimaginative but reliable approach is to enumerate all the control signals you have, which will probably be more than 16 bits, and then attempt to do Karnaugh-map style logic minimisation on them.

\$\endgroup\$
4
  • \$\begingroup\$ I don't really get what you mean by control signals. \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 19:27
  • \$\begingroup\$ What I found and like about the ARM is the condition field, I will include that. \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 19:28
  • \$\begingroup\$ Control signals are the inputs to the various multiplexers and enables that direct data between the parts of the CPU. \$\endgroup\$
    – pjc50
    Commented Jan 28, 2015 at 0:06
  • \$\begingroup\$ For a 16-bit architecture, I don't think ARM's instruction encoding is appropriate. Mayby thumb2 is better. But I like the MIPS way of encoding, simple and easy to understand, although a bit wasteful \$\endgroup\$
    – phuclv
    Commented Jan 28, 2015 at 9:05
4
\$\begingroup\$

Once I tried doing a 4-bit CPU with 8-bit instruction length core in Logisim. Ended up with a simple state machine, more than a CPU, really.

Random things to look for

  • Huffman trees
  • Fixed-length or variable encoding?
  • Is it a von Neumann design with single address space, or Harvard-style with separate data/program?

Excellent video on Computerphile about Huffman trees:

https://www.youtube.com/watch?v=umTbivyJoiI

\$\endgroup\$
3
  • \$\begingroup\$ Huffman coding wont work for a fixed length encoding, right? \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 15:41
  • \$\begingroup\$ @Benjoyo I can imagine a scenario with the spare bits being used for variations of the most used instructions, thus providing more functionality. \$\endgroup\$
    – Dzarda
    Commented Jan 27, 2015 at 15:53
  • \$\begingroup\$ But I don't get what kind of optimization this brings. It doesn't help me with the circuit design. What is the goal when using Huffman coding for opcode? \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 23:12
4
\$\begingroup\$

The ISA I wrote for class once had a 4 bit op code like so: 1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store

Rather than being the most optimal, this is one of easier styles to construct/design gates for because the input signal of a single bit can control entirely what logic path is taken. Alternatively, you can Huffman Code your most used symbols and zero pad them to get a fixed length op code.

\$\endgroup\$
2
  • \$\begingroup\$ This kind of optimization is what I am looking for at the moment. But I have a 5 bit opcode and I struggle with grouping the commands together so that it makes sense in the circuit. \$\endgroup\$
    – Benjoyo
    Commented Jan 27, 2015 at 23:09
  • \$\begingroup\$ @Benjoyo you could have a bunch more ALU instructions with the upper bit set. Also my jump condition coverage was pretty weak and most normal branches would require two instructions. Generally, I thought of the categories as: Math / Control / Memory \$\endgroup\$
    – user65335
    Commented Jan 28, 2015 at 1:35
3
\$\begingroup\$

One thing you'll need to consider is whether to allow any form of multi-word instruction, or anything that can "act" like a multi-word instruction; if you do, you may then want to consider whether to use additional instruction words following the main instruction, or prefix words before it. Allowing prefixes and follow-on words can increase the complexity of interrupt handling, but it can avoid the need to fit rarely-used instructions in the same opcode space as commonly-used ones.

If instructions are fetched on the cycle before they execute, one could have a "conditional branch" instruction which either causes the next instruction word to be skipped or else have its contents transferred directly into the program counter; such a design might add some extra complexity to interrupt sequencing, but it could ease the need to use a big portion of the opcode space for "branch", "jump" and "call" instructions, while allowing a much wider range of branch conditions than would otherwise be possible. Since a branch which is taken will generally require a dead cycle following execution of the instruction itself regardless of where the address comes from, having the address come from the following word which has been fetched but won't be executed doesn't cost any extra time.

Even though moving the target address out of branch instructions will reduce how much of the opcode space they gobble up, a 16-bit opcode format is still pretty tight. Using prefix instructions can help with that. If, for example, one wants to have 32 registers, allowing any register to be independently specified as source1, source2, and destination would require 15 bits in the opcode, allowing a whopping total of two instructions. Not very useful. On the other hand, being able to use any of 32 registers for each of the three operands would be nice. One could balance the two goals by having any ALU operation which isn't preceded by a prefix use eight bits to make two one-of-sixteen register selections, but have an ALU operation which immediately follows a prefix use some bits in the prefix along with eight from the following instruction, so as to allow independent selection of both sources and the destination from the full set of 32. Instructions which use the upper registers would take two words/cycles rather than one, but in some cases such a tradeoff could be well worthwhile. The biggest difficulty with using prefixes is that one must either prevent an interrupt from occurring between a prefix and the next instruction or else ensure that if an interrupt does occur there the instruction after the prefix will still use the right registers [e.g. by having the program-counter save logic store the address of the last non-prefix instruction executed].

Using multi-word instructions will make some aspects of the design more difficult, but it may reduce the need to make other difficult decisions.

\$\endgroup\$
0
\$\begingroup\$

This guy has the best details on understanding hard wiring the hardcoded portion of a Decoder, which explains the control lines for a hardcoded CPU: http://minnie.tuhs.org/CompArch/Tutes/week03.html As you can see, your choice in Opcodes really impacts how complex the Decode logic is.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.