2009-02-23 26 views
16

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.¿Cómo configuro los indicadores de salida para ALU en el curso "Nand ​​to Tetris"?

Aquí es mi ALU chips 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); 

} 

Así que el problema aparece cuando estoy tratando de enviar una versión con subíndice de 'fuera' 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 de las líneas problemáticas con lo siguiente, se compilará (pero no dar los resultados correctos, ya sólo estoy usando alguna entrada al azar):

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

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

Alguien tiene alguna ideas?

Editar: Aquí está el appendix of the book for the course 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".

Edit: Aquí está el error exacto que obtengo: "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.

+1

¿Por qué se cerró esta pregunta? Definitivamente ha ayudado a muchos visitantes como lo demuestran las votaciones y las respuestas. –

+0

Votación para volver a abrir, porque la pregunta es sobre un problema común al resolver un problema en un curso en línea bien conocido. –

Respuesta

5

La solución como Pax sugirió fue usar una variable intermedia como entrada a otro chip, como Or16Way. Aquí está el código después de He arreglado el problema y depurado:

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); 
} 
+0

Bizarre que no hay dispositivo de almacenamiento intermedio y que tiene que volver a y16/o16 con entradas idénticas para emular esto. La electrónica real tiene buffers sin perder puertas, quizás este programa de emulación debería tener también. – paxdiablo

+0

Sí, debe haber alguna otra solución que no me obligue a hacer un nuevo chip (hice Or16Way), ya que la idea es usar solo los chips que acumuló en los proyectos anteriores. – MahlerFive

+4

no tiene que hacer un nuevo chip. Solo use salidas múltiples, como esta: Mux16 (a = F16, b = NF16, sel = no, out = out, out [15] = ng, out [0..7] = zout1, out [8 ..15] = zout2); Luego use Or16Way en esas salidas: \t Or8Way (in = zout1, out = zr1); \t Or8Way (in = zout2, out = zr2); \t O (a = zr1, b = zr2, out = zr3); \t No (in = zr3, out = zr); – mudge

1

Ha intentado:

// 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 va a funcionar, pero parece tener sentido de mirar este documento here.

también me lo pensaría dos veces sobre el uso de out como nombre de variable ya que es confuso tratando de averiguar 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 tendrá que implementar un "chip" separado como IsZero16 que tomará un valor de 16 bits como entrada (su intermedio out) y devolverá un bit indicando su cero que puede cargar en zr. O podría hacer un chip IsZero8, pero tendría que llamarlo dos etapas, como lo hace 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 usted sugiere. 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 tiene que 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 los pines de salida de chips, 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 su chip de ALU, usar 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); 
+0

El problema es que no puedo subscribir la variable 'salir' en absoluto ya que se derivó como una variable intermedia. Además, no importa si asigna cada subíndice individualmente o no. Si 'in' tiene un tamaño de bus de 8, entonces el lado derecho de la ecuación tiene que ser del tamaño 8. – MahlerFive

+0

Muéstrenos el error real que está recibiendo, @MahlerFive. Puede ayudar. – paxdiablo

+0

De acuerdo, publiqué eso como una edición – MahlerFive

21

Para cualquier otra persona interesada, la solución del emulador soporta es utilizar varias salidas Algo así como:

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

Aquí está uno también con una el 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); 
} 
5

Ésta es la forma en que 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); 
} 
Cuestiones relacionadas