My PC works, but why?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

My PC works, but why?

tuzmusic
I'm pasting my hdl code for for the program counter. I struggled a lot and then stumbled upon this solution.

As indicated in my comments, I am completely baffled as to why my `ifLoad`Mux is able to get away with just using the `in` signal without modification, and especially why my final register doesn't depend on the load bit, and more especially why my "else" case basically has the same input as `ifLoad`.

My code comments might be clearer than the previous paragraph.

```
CHIP PC {
    IN in[16],load,inc,reset;
    OUT out[16];

    PARTS:

    // if inc=1, increment the looped back output(=prevInput) (else pass through, use current input)
    Inc16(in=out2, out=incOut);    
    Mux16(a=in, b=incOut, sel=inc, out=ifInc);

    // if load=1, use "in" (else pass through)
    // (if inc=0 a is also "in" and load is irrelevant???)
    Mux16(a=ifInc, b=in, sel=load, out=ifLoad);

    // if reset=1, use 0 (else pass through -- either inc'ed or loaded)
    Mux16(a=ifLoad, b=false, sel=reset, out=ifReset);
   
    // final delay
    // AND FINAL ELSE: load=1 -> out=in(t-1)
    // i.e., save the current input (ifReset) for next time,
    //       and use the previous input this time (if no previous input, 0)
    //      if reset=1,           ifReset = 0
    // else if load=1 (or inc=0), ifReset = in
    // else if inc=1,             ifReset = out + 1 = prevInput + 1?
    // else (if reset=inc=load=0) ifReset = in (why is this the same as load=1?????)
    Register(in=ifReset, load=true, out=out,out=out2);    
}
```
Reply | Threaded
Open this post in threaded view
|

Re: My PC works, but why?

ivant
You can think of this as a chain of modified inputs:

val0 --INC--> val1 --MUX(inc)--> val2 --MUX(load)--> val3 --MUX(reset)--> val4 --> Register.

The goal is to make val4 be the correct value as described in the specification.

tuzmusic wrote
I am completely baffled as to why my `ifLoad`Mux is able to get away with just using the `in` signal without modification
Why and how do you think you need to modify the in signal?


tuzmusic wrote
and especially why my final register doesn't depend on the load bit
The value that you enter in the register actually depends on the load bit. The register itself has to update its value on each clock, that's why it's connected to true.


tuzmusic wrote
and more especially why my "else" case basically has the same input as `ifLoad`.
    // else (if reset=inc=load=0) ifReset = in (why is this the same as load=1?????)
This part is wrong. The specification reads:

/**
 * A 16-bit counter with load and reset control bits.
 * if      (reset[t]==1) out[t+1] = 0
 * else if (load[t]==1)  out[t+1] = in[t]
 * else if (inc[t]==1)   out[t+1] = out[t] + 1  (integer addition)
 * else                  out[t+1] = out[t]
 */

So the else part tells us that if reset, load and inc are all 0, the register should not change its value.
Reply | Threaded
Open this post in threaded view
|

Re: My PC works, but why?

tuzmusic
This post was updated on .
Thank you, and also thanks for such a speedy reply!

I think my head was too much in code land, and not enough in "what's actually happening with sequential chips" land.  I had basically forgotten that load ? in(t-1) : out(t-1) means "if load=1, this time send last time's input, otherwise this time send last time's output aka send the same thing".

The phrasing I just used does leave out the fact that "use last time" means "last time we stored something for this time" which also means "this time, store something for next time." You may argue that those ideas are not important, or perhaps even inaccurate, and I'd love to hear those arguments. But they helped me wrap my head around everything that's going on. Maybe because my brain works much better with code than with a graphical representation, and this is probably a case for graphical representation.

So all of that points to the fact that I didn't really understand what the "ifLoad" functionality was. Taken independently from everything else, the "ifLoad" functionality is the general functionality of any register: if load=1, output the previous in, if load=0 output the previous out. In this case, the a bus of the "ifLoad" Mux chip represents the previous out, but I was confused because I was already giving the "in" to the "ifInc" Mux. However, it turns out that the a input to the ifInc chip doesn't matter AT ALL. I've now set that a bus to get out2 (a fan-out of the final output, which is what is incremented in the Inc16 chip), to symbolize that if inc=0 we'll use the un-incremented previous output.

Anyway, here are my new comments, which are more about things happening at different times than they are about equality/assignment statements.

CHIP PC {
    IN in[16],load,inc,reset;
    OUT out[16];

    PARTS:
   
    // the (previous) OUT of the whole chip will always be the "resolution"(ifReset) of the previous time.
    Inc16(in=out2, out=incOut);    
    // if inc=1, send along this incremented PREVIOUS output.
    // if inc=0, send along the non-incremented PREVIOUS output. (i.e., keep outputting the same thing)
    Mux16(a=out2, b=incOut, sel=inc, out=ifInc);

    // if load=1, send along NEW input. in other words, LOAD THE NEW INPUT.
    // if load=0, send along ifInc (which was either incremented PREVIOUS output, or PREVIOUS output/same output)
    Mux16(a=ifInc, b=in, sel=load, out=ifLoad);

    // if reset=1, send along/OUTPUT 0 (else pass through -- either inc'ed PREVIOUS out; or the NEW input; or the SAME PREVIOUS output)
    Mux16(a=ifLoad, b=false, sel=reset, out=ifReset);
   
    // this is our FINAL DELAY. it says:
    // given the INPUT from the REST OF THE CHIP (ifReset)
    //   which is either 0 (reset), NEW in (load), PREV OUT +1 (inc), or simply the SAME PREVIOUS OUTPUT,
    // store it for the NEXT OUTPUT.
    // this also means:
    // THIS TIME, output this register's input from the LAST TIME.
    // if reset=inc=load=0, the input for this register will equal the initial input ("in"),
    //    meaning if reset=inc=load=0, NEXT out will be THIS in.
    Register(in=ifReset, load=true, out=out,out=out2);    
}