hdl alu nand2tetris

hdl - ¿Cómo configuro los indicadores de salida para ALU en el curso "Nand ​​to Tetris"?



nand2tetris (5)

Aunque etiqueté esta tarea, en realidad es para un curso que estoy haciendo de manera gratuita. De todos modos, el curso se llama "De Nand a Tetris" y espero que alguien haya visto o tomado el curso para que pueda obtener ayuda. Estoy en la etapa en la que estoy construyendo la ALU con el lenguaje hdl suministrado. Mi problema es que no puedo hacer que mi chip compile correctamente. Recibo errores cuando intento establecer los indicadores de salida para la ALU. Creo que el problema es que no puedo subscribir ninguna variable intermedia, ya que cuando intento configurar los indicadores en verdadero o falso en función de alguna variable aleatoria (por ejemplo, un indicador de entrada), no obtengo los errores. Sé que el problema no está en los chips que trato de usar, ya que estoy usando todos los chips integrados.

Aquí está mi chip ALU hasta el momento:

/** * The ALU. Computes a pre-defined set of functions out = f(x,y) * where x and y are two 16-bit inputs. The function f is selected * by a set of 6 control bits denoted zx, nx, zy, ny, f, no. * The ALU operation can be described using the following pseudocode: * if zx=1 set x = 0 // 16-bit zero constant * if nx=1 set x = !x // Bit-wise negation * if zy=1 set y = 0 // 16-bit zero constant * if ny=1 set y = !y // Bit-wise negation * if f=1 set out = x + y // Integer 2''s complement addition * else set out = x & y // Bit-wise And * if no=1 set out = !out // Bit-wise negation * * In addition to computing out, the ALU computes two 1-bit outputs: * if out=0 set zr = 1 else zr = 0 // 16-bit equality comparison * if out<0 set ng = 1 else ng = 0 // 2''s complement comparison */ CHIP ALU { IN // 16-bit inputs: x[16], y[16], // Control bits: zx, // Zero the x input nx, // Negate the x input zy, // Zero the y input ny, // Negate the y input f, // Function code: 1 for add, 0 for and no; // Negate the out output OUT // 16-bit output out[16], // ALU output flags zr, // 1 if out=0, 0 otherwise ng; // 1 if out<0, 0 otherwise PARTS: // Zero the x input Mux16( a=x, b=false, sel=zx, out=x2 ); // Zero the y input Mux16( a=y, b=false, sel=zy, out=y2 ); // Negate the x input Not16( in=x, out=notx ); Mux16( a=x, b=notx, sel=nx, out=x3 ); // Negate the y input Not16( in=y, out=noty ); Mux16( a=y, b=noty, sel=ny, out=y3 ); // Perform f Add16( a=x3, b=y3, out=addout ); And16( a=x3, b=y3, out=andout ); Mux16( a=andout, b=addout, sel=f, out=preout ); // Negate the output Not16( in=preout, out=notpreout ); Mux16( a=preout, b=notpreout, sel=no, out=out ); // zr flag Or8way( in=out[0..7], out=zr1 ); // PROBLEM SHOWS UP HERE Or8way( in=out[8..15], out=zr2 ); Or( a=zr1, b=zr2, out=zr ); // ng flag Not( in=out[15], out=ng ); }

Entonces aparece el problema cuando intento enviar una versión subscripta de ''out'' al chip Or8Way. Intenté usar una variable diferente a ''out'', pero con el mismo problema. Luego leo que no puedes subindicar variables intermedias. Pensé que tal vez si enviaba la variable intermedia a algún otro chip, y ese chip lo subscribe, resolvería el problema, pero tiene el mismo error. Lamentablemente, no puedo pensar en una forma de establecer los indicadores zr y ng sin subscribir alguna variable intermedia, ¡así que estoy realmente atascado!

Para que lo sepas, si reemplazo las líneas problemáticas por las siguientes, compilará (pero no dará los resultados correctos ya que solo estoy usando una entrada aleatoria):

// zr flag Not( in=zx, out=zr ); // ng flag Not( in=zx, out=ng );

¿Alguien tiene alguna idea?

Editar: Aquí está el apéndice del libro para el curso que especifica cómo funciona el hdl. Mire específicamente la sección 5 que habla sobre los buses y dice: "Un pin interno (como v arriba) no puede ser subíndice".

Editar: Aquí está el error exacto que recibo: "Línea 68, No se puede conectar el pin de salida de la puerta a la parte". El mensaje de error es un poco confuso, ya que no parece ser el problema real. Si simplemente reemplazo "Or8way (in = out [0..7], out = zr1);" con "Or8way (in = falso, out = zr1);" no generará este error, que es lo que me llevó a buscar en el apéndice y encontrar que la variable de salida, ya que se derivó como intermedio, no se pudo suscribir.


Has probado:

// zr flag Or8way( in[0]=out[ 0], in[1]=out[ 1], in[2]=out[ 2], in[3]=out[ 3], in[4]=out[ 4], in[5]=out[ 5], in[6]=out[ 6], in[7]=out[ 7], out=zr1); Or8way( in[0]=out[ 8], in[1]=out[ 9], in[2]=out[10], in[3]=out[11], in[4]=out[12], in[5]=out[13], in[6]=out[14], in[7]=out[15], out=zr2); Or( a=zr1, b=zr2, out=zr );

No sé si esto funcionará, pero parece tener sentido al mirar este documento aquí .

También lo pensaría dos veces antes de usar como nombre de variable, ya que es confuso tratar de descubrir la diferencia entre eso y la palabra clave out (como en " out=... ").

Después de su edición, si no puede subíndices de valores intermedios, entonces parece que tendrá que implementar un "chip" separado como IsZero16 que tomará un valor de 16 bits como entrada (su out intermedia) y devolverá un bit que indica su cero- ness que puedes cargar en zr . O podrías hacer un chip IsZero8 pero tendrías que llamarlo dos etapas, como lo haces actualmente con Or8Way .

Esto parece una solución válida ya que puede subíndices de los valores de entrada a un chip.

Y, simplemente mirando el error, este puede ser un problema diferente al que sugieres. La frase "No se puede conectar el pin de salida de la puerta a la pieza" significaría para mí que no puede volver a conectar las señales del parámetro de salida al área de procesamiento de las fichas. Eso tiene sentido desde el punto de vista eléctrico.

Puede encontrar que debe almacenar la salida en una variable temporal y usarla para establecer zr y out (ya que una vez que las señales se "enviaron" a las patillas de salida de las fichas, es posible que ya no estén disponibles).

Podemos intentar:

CHIP SetFlags16 { IN inpval[16]; OUT zflag,nflag; PARTS: Or8way(in=inpval[0.. 7],out=zr0); Or8way(in=inpval[8..15],out=zr1); Or(a=zr0,b=zr1,out=zflag); Not(in=inpval[15],out=nflag); }

y luego, en tu chip ALU, usa esto al final:

// Negate the output Not16( in=preout, out=notpreout ); Mux16( a=preout, b=notpreout, sel=no, out=tempout ); // flags SetFlags16(inpval=tempout,zflag=zr,nflag=ng); // Transfer tempout to out (may be a better way). Or16(a=tempout,b=tempout,out=out);


La solución que Pax sugirió era usar una variable intermedia como entrada para otro chip, como Or16Way. Aquí está el código después de que arreglé el problema y depuré:

CHIP ALU { IN // 16-bit inputs: x[16], y[16], // Control bits: zx, // Zero the x input nx, // Negate the x input zy, // Zero the y input ny, // Negate the y input f, // Function code: 1 for add, 0 for and no; // Negate the out output OUT // 16-bit output out[16], // ALU output flags zr, // 1 if out=0, 0 otherwise ng; // 1 if out<0, 0 otherwise PARTS: // Zero the x input Mux16( a=x, b=false, sel=zx, out=x2 ); // Zero the y input Mux16( a=y, b=false, sel=zy, out=y2 ); // Negate the x input Not16( in=x2, out=notx ); Mux16( a=x2, b=notx, sel=nx, out=x3 ); // Negate the y input Not16( in=y2, out=noty ); Mux16( a=y2, b=noty, sel=ny, out=y3 ); // Perform f Add16( a=x3, b=y3, out=addout ); And16( a=x3, b=y3, out=andout ); Mux16( a=andout, b=addout, sel=f, out=preout ); // Negate the output Not16( in=preout, out=notpreout ); Mux16( a=preout, b=notpreout, sel=no, out=preout2 ); // zr flag Or16Way( in=preout2, out=notzr ); Not( in=notzr, out=zr ); // ng flag And16( a=preout2, b=true, out[15]=ng ); // Get final output And16( a=preout2, b=preout2, out=out ); }


Aquí hay uno también con un nuevo chip pero se siente más limpio

/** * Negator16 - negates the input 16-bit value if the selection flag is lit */ CHIP Negator16 { IN sel,in[16]; OUT out[16]; PARTS: Not16(in=in, out=negateIn); Mux16(a=in, b=negateIn, sel=sel, out=out); } CHIP ALU { // IN and OUT go here... PARTS: //Zero x and y if needed Mux16(a=x, b[0..15]=false, sel=zx, out=x1); Mux16(a=y, b[0..15]=false, sel=zy, out=y1); //Create x1 and y1 negations if needed Negator16(in=x1, sel=nx, out=x2); Negator16(in=y1, sel=ny, out=y2); //Create x&y and x+y And16(a=x2, b=y2, out=andXY); Add16(a=x2, b=y2, out=addXY); //Choose between And/Add according to selection Mux16(a=andXY, b=addXY, sel=f, out=res); // negate if needed and also set negative flag Negator16(in=res, sel=no, out=res1, out=out, out[15]=ng); // set zero flag (or all bits and negate) Or16Way(in=res1, out=nzr); Not(in=nzr, out=zr); }


Así es como hice la ALU:

CHIP ALU { IN // 16-bit inputs: x[16], y[16], // Control bits: zx, // Zero the x input nx, // Negate the x input zy, // Zero the y input ny, // Negate the y input f, // Function code: 1 for add, 0 for and no; // Negate the out output OUT // 16-bit output out[16], // ALU output flags zr, // 1 if out=0, 0 otherwise ng; // 1 if out<0, 0 otherwise PARTS: Mux16(a=x, b=false, sel=zx, out=M16x); Not16(in=M16x, out=Nx); Mux16(a=M16x, b=Nx, sel=nx, out=M16M16x); Mux16(a=y, b=false, sel=zy, out=M16y); Not16(in=M16y, out=Ny); Mux16(a=M16y, b=Ny, sel=ny, out=M16M16y); And16(a=M16M16x, b=M16M16y, out=And16); Add16(a=M16M16x, b=M16M16y, out=Add16); Mux16(a=And16, b=Add16, sel=f, out=F16); Not16(in=F16, out=NF16); Mux16(a=F16, b=NF16, sel=no, out=out, out[15]=ng, out[0..7]=zout1, out[8..15]=zout2); Or8Way(in=zout1, out=zr1); Or8Way(in=zout2, out=zr2); Or(a=zr1, b=zr2, out=zr3); Not(in=zr3, out=zr); }


Para cualquier otra persona interesada, la solución que el emulador admite es usar múltiples salidas Algo como:

Mux16( a=preout, b=notpreout, sel=no, out=out,out=preout2,out[15]=ng);