20

虽然我标记了这个作业,但它实际上是我自己免费完成的一门课程。无论如何,这门课程叫做“从 Nand 到俄罗斯方块”,我希望这里有人看过或上过这门课程,以便我能得到一些帮助。我正处于使用提供的 hdl 语言构建 ALU 的阶段。我的问题是我的芯片无法正确编译。当我尝试为 ALU 设置输出标志时出现错误。我相信问题是我不能下标任何中间变量,因为当我尝试根据一些随机变量(比如输入标志)将标志设置为真或假时,我没有得到错误。我知道问题不在于我尝试使用的芯片,因为我使用的是所有内置芯片。

到目前为止,这是我的 ALU 芯片:

/**
 * 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 );

}

因此,当我尝试将“out”的下标版本发送到 Or8Way 芯片时,问题就出现了。我尝试使用与“out”不同的变量,但遇到了同样的问题。然后我读到你不能下标中间变量。我想也许如果我将中间变量发送到其他芯片,并且该芯片下标它,它会解决问题,但它有同样的错误。不幸的是,我只是想不出一种方法来设置 zr 和 ng 标志而不下标一些中间变量,所以我真的被卡住了!

请注意,如果我用以下内容替换有问题的行,它将编译(但不会给出正确的结果,因为我只是使用一些随机输入):

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

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

有人有想法么?

编辑:这是本书的附录,该附录指定了 hdl 的工作原理。具体看第 5 节,它讨论了总线并说:“内部引脚(如上面的 v)可能没有下标”。

编辑:这是我得到的确切错误:“第 68 行,无法将门的输出引脚连接到部件”。不过,错误消息有点令人困惑,因为这似乎不是真正的问题。如果我只是替换“Or8way(in=out[0..7], out=zr1);” 用“Or8way(in=false,out=zr1);” 它不会产生这个错误,这导致我在附录中查找并发现 out 变量,因为它是作为中间派生的,所以不能下标。

4

5 回答 5

22

对于其他感兴趣的人,模拟器支持的解决方案是使用多个输出,例如:

Mux16( a=preout, b=notpreout, sel=no, out=out,out=preout2,out[15]=ng);
于 2009-10-23T13:44:48.537 回答
6

这就是我做 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);
}
于 2010-03-20T21:57:29.527 回答
5

Pax 建议的解决方案是使用中间变量作为另一个芯片的输入,例如 Or16Way。这是我修复问题并调试后的代码:

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 );
}
于 2009-02-23T03:22:50.903 回答
1

你有没有尝试过:

// 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 );

我不知道这是否可行,但从此处查看此文档似乎很有意义。

我也会三思而后行,out因为试图找出它与关键字之间的区别out(如“ out=...”)会让人感到困惑。

在您的编辑之后,如果您不能为中间值下标,那么您似乎必须实现一个单独的“芯片”,例如IsZero16它将一个 16 位值作为输入(您的中间值out)并返回一位指示其零性你可以加载到zr. 或者你可以制作一个IsZero8芯片,但你必须像你目前正在做的那样把它称为两个阶段Or8Way

这似乎是一个有效的解决方案,因为您可以将输入值下标到芯片。

而且,仅查看错误,这可能与您建议的问题不同。“无法将门的输出引脚连接到零件”这句话对我来说意味着您无法将输出参数的信号连接回芯片处理区域。从电气的角度来看,这是有道理的。

您可能会发现您必须将输出存储到一个临时变量中并使用它来设置zrout(因为一旦信号已“发送”到芯片输出引脚,它们可能不再可用)。

我们可以试试吗:

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

然后,在你的 ALU 芯片中,最后使用它:

// 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);
于 2009-02-23T01:16:41.890 回答
1

这里也有一个新芯片,但感觉更干净

/**
 * 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);
}
于 2010-01-29T17:08:43.727 回答