Error:This Chip has a circle in its parts connection.

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

Error:This Chip has a circle in its parts connection.

harshchikorde1234@gmail.com
I am getting this error after I load my code for CPU in the hardware simulator. What does this mean? How should I rectify this error?
Reply | Threaded
Open this post in threaded view
|

Re: Error:This Chip has a circle in its parts connection.

WBahn
Administrator
It means that a signal is dependent on itself, either directly or indirectly.

Imagine you have three parts, A, B, and C. The output of A is dependent on the output of B and C. But the output of C is dependent on the output of A. So to know the output of A you have to know what the output of C is, but to know the output of C you have to know what the output of A is. This very simple simulator is not capable of resolving such situations, even if the circuit connections are actually perfectly valid and common in the real world -- examples include latches and flip-flops and oscillators. This is why you don't have to implement a clock part (which is an oscillator) and why you are given the DFF part (which is a flip-flop).
Reply | Threaded
Open this post in threaded view
|

Re: Error:This Chip has a circle in its parts connection.

harshchikorde1234@gmail.com
@Wbahn: I dont have any latches, flipflops or oscillators in my code. I tried a few tweaks with my code, I found that the ALU output is of 16 bits whereas PC can intake only 15 bits, I don't know if this might be the reason for error! The point is I am unable to pinpoint exactly where I am going wrong! Can you please suggest any method to know for myself where I am going wrong, Is it the order of my parts instantiation that need to be changed or some thing else because my code has no errors, how do I avoid circling error?
Here is a rough order of parts in my code, tell me the correct order of parts instantiation if I am wrong:

Logic for writeM

ARegister load logic, Mux and implementation

Dregister load logic, and implementation

Mux for ARegister output
ALU instantiation

Load and incerment logic for PC

PC instantiation


Reply | Threaded
Open this post in threaded view
|

Re: Error:This Chip has a circle in its parts connection.

WBahn
Administrator
Unless and until you post your code, all I can do is tell you what the error message means: somewhere in your code, probably inadvertently, you have an output signal that depends on itself.

The order of the parts is completely immaterial, it is the connections that matter.

If you draw a schematic of your circuit, the circular path is usually pretty evident.
Reply | Threaded
Open this post in threaded view
|

Re: Error:This Chip has a circle in its parts connection.

harshchikorde1234@gmail.com
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/05/CPU.hdl

/**
 * The Hack CPU (Central Processing unit), consisting of an ALU,
 * two registers named A and D, and a program counter named PC.
 * The CPU is designed to fetch and execute instructions written in
 * the Hack machine language. In particular, functions as follows:
 * Executes the inputted instruction according to the Hack machine
 * language specification. The D and A in the language specification
 * refer to CPU-resident registers, while M refers to the external
 * memory location addressed by A, i.e. to Memory[A]. The inM input
 * holds the value of this location. If the current instruction needs
 * to write a value to M, the value is placed in outM, the address
 * of the target location is placed in the addressM output, and the
 * writeM control bit is asserted. (When writeM==0, any value may
 * appear in outM). The outM and writeM outputs are combinational:
 * they are affected instantaneously by the execution of the current
 * instruction. The addressM and pc outputs are clocked: although they
 * are affected by the execution of the current instruction, they commit
 * to their new values only in the next time step. If reset==1 then the
 * CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather
 * than to the address resulting from executing the current instruction.
 */

CHIP CPU {

    IN  inM[16],         // M value input  (M = contents of RAM[A])
        instruction[16], // Instruction for execution
        reset;           // Signals whether to re-start the current
                         // program (reset==1) or continue executing
                         // the current program (reset==0).

    OUT outM[16],        // M value output
        writeM,          // Write to M?
        addressM[15],    // Address in data memory (of M)
        pc[15];          // address of next instruction

    PARTS:
    // Put your code here:
And(a=instruction[15],b=instruction[3],out=writeM); //1

//ARegister
Not(in=instruction[15],out=nTout);      //2
Or(a=nTout,b=instruction[5],out=loadA);   //3
Mux16(a=instruction,b=ALUout,sel=instruction[15],out=ARegin);
ARegister(in=ARegin,load=loadA,out=ARegout,out[15]=t1,out[14]=addressM[14],out[13]=addressM[13],out[12]=addressM[12],out[11]=addressM[11],out[10]=addressM[10],out[9]=addressM[9],out[8]=addressM[8],out[7]=addressM[7],out[6]=addressM[6],out[5]=addressM[5],out[4]=addressM[4],out[3]=addressM[3],out[2]=addressM[2],out[1]=addressM[1],out[0]=addressM[0]);

//DRegister
And(a=instruction[15],b=instruction[4],out=loadD);    //4
DRegister(in=ALUout,load=loadD,out=DRegout);

Mux16(a=ARegout,b=inM,sel=instruction[12],out=inMout);
ALU(x=DRegout,y=inMout,zx=instruction[11],nx=instruction[10],zy=instruction[9],ny=instruction[8],f=instruction[7],no=instruction[6],out=ALUout,zr=zr1,ng=ng1);

Not16(in=ALUout,out=nALUout);   //5
Not16(in=nALUout,out=outM);     //6

And(a=instruction[1],b=zr1,out=and1);  //7
And(a=instruction[2],b=ng1,out=and2);  //8
Not(in=zr1,out=nzr1);                  //9
Not(in=ng1,out=nng1);                  //10

And(a=instruction[0],b=nzr1,out=and3);  //11
And(a=and3,b=nng1,out=and4);            //12

And(a=instruction[2],b=instruction[1],out=and5);  //13  
And(a=instruction[0],b=and5,out=and6);        //14

Or(a=and1,b=and2,out=or1);   //15
Or(a=and4,b=and6,out=or2);   //16
Or(a=or1,b=or2,out=loadPC);  //17

Not(in=loadPC,out=incrPC);   //18

PC(in=ARegout,load=loadPC,inc=incrPC,reset=reset,out[15]=t2,out[14]=pc[14],out[13]=pc[13],out[12]=pc[12],out[11]=pc[11],out[10]=pc[10],out[9]=pc[9],out[8]=pc[8],out[7]=pc[7],out[6]=pc[6],out[5]=pc[5],out[4]=pc[4],out[3]=pc[3],out[2]=pc[2],out[1]=pc[1],out[0]=pc[0]);

}
Reply | Threaded
Open this post in threaded view
|

Re: Error:This Chip has a circle in its parts connection.

WBahn
Administrator
I'll try to look through this later, but it might take me a while because I'm swamped with other things.

But a couple of quick observations:

You've got quite a bit of unnecessary code here. Remember that you can sub-bus part pins (but not internal signals) AND that you can use output pin assignments multiple times. So say that you have an input signal and you want to invert it and send it to an output signal. But you also want to split the input into bytes, swap them, and invert just one of them. Then you want to And the output of the most and least significant bits of this result and send that to another output pin. Don't worry about why you might want to do this, the point is just to use the various signal assignment options available. You can do it like the following:

Not16(a = inputPin, out = outputPin, out[0..7] = lowerByteInverted);
Not16(in[8..11] = lowerByteInverted, in[0..7] = inputPin[8..15], out[15] = msb, out[0] = lsb);
And(a = msb, b = lsb, out = anotherOutputPin);

Notice that sub-bussing was used only on chip I/O pins, either of the whole part (inputPin), or of the parts being used. The internal signals {lowerByteInverted, msn, lsb} were never sub-bussed, which is not allowed by the HDL syntax rules.

Since we can't use an chip output pin {outputPin, anotherOutputPin} as inputs to internal parts, we simply used the output pins that generate them multiple times to assign the output once to the output pin and then again to an internal signal that we can route elsewhere.