0
votes

I'm creating a simulation in Verilog.

I have a memory module, loaded with MIPS instructions like so...

20082000
200d2030
8dad0000
240a0001
ad0a0000
..
..
..

the memory module outputs the instruction to the input of a "Control" module, this module has the following signals:

RegDst,Jump,Branch,MemRead,MemtoReg,ALUOp,MemWrite,ALUSrc,RegWrite

The signal values will be generated for a list of supported instructions, which the memory module is loaded with. Instructions such as add,addi, etc.

How do I know if the signal is going to be true or false for a given instruction?

1
By reading the documentation and/or source code of the "Control" module.mkrieger1
@mkrieger1 im the one thats creating the moduleRijad Hadzic
Shouldn’t you be the one who knows what the module is doing then?! How are we supposed to know that?mkrieger1

1 Answers

3
votes

You have to decompose what it is that each instruction does.

Use the MIPS green card, for example.

All R-Type instructions share certain control signals, which follow from their basic instruction format — that they source/read rs & rt, and target/write to rd, for example, which means that:

  • RegDest is true (rd is written, not rt)
  • RegWrite is true (some reg is written)
  • ALUSrc is true (the 2nd alu input is from register, not from immediate)

I-Type instructions all have certain shared control signal patterns:

  • RegDest is false (rt is written, there is no rd for I-Types)
  • RegWrite is true (some reg is written)
  • ALUSrc is false (the 2nd alu input is from immediate, not from register)

No instructions touch memory except loads and stores, so MemRead and MemWrite are false for all of the other instructions.  MemRead is true for loads only and MemWrite is true for stores only.

MemtoReg is true for loads as the result comes from memory, but false for most other instructions, as the result (if any) comes from the ALU instead.


For many instructions, some of these control signals don't matter, so can be classified as "don't care" rather than true or false (either of which would be fine by the hardware).  For example, since a store instruction sends data to memory, it doesn't update a CPU register — thus, MemToReg for that one is don't care, since no reg is written anyway (same for branches as they also don't write/update a register).

When RegWrite is false, then MemtoReg doesn't matter (is don't care).


Unlike most of the rest, the ALUOp is one control signal that is bigger than a single boolean.  So the ALU needs to know what operation to perform, and for R-Type instructions, this comes from the funct field of the instruction, whereas for I-Type instructions this comes from the opcode field itself.

For loads and stores, the ALU (in the single cycle MIPS CPU) is used to perform the addressing mode computation, so the ALU should be told to add.

For branches (in the single cycle MIPS CPU), the ALU should be told to subtract (i.e. compare).


High level: the hardware is a union of all the components necessary for all the instructions.  The control signals are used to "activate" the proper hardware components for any single instruction being executed — but, the trick is that these signals don't actually activate the components, but instead choose whether to accept or ignore their output(s) after they have computed something useful or useless, respectively, given the instruction being executed.

It's kind of screwy, but that union of all the needed hardware components (for every possible instruction) are sitting there doing something all the time (unless very advanced power saving circuitry is used).  So, what the control signals do — instead of turning off components that don't contribute to the current instruction — is to simply ignore their computations results, favoring something relevant instead.

For example, effectively, the immediate hardware is sign extending the I-Type 16-bit immediate on every cycle for every instruction, but that computed value is only used when the instruction actually is an I-Type, and otherwise ignored due to the control signal (ALUSrc).

While we might think of this as power inefficient, there is a parallelism performance to be appreciated, which is that things unnecessary are computed in advance, just in case they are needed and only suppressed later when more is known.