كيف أقوم بتعيين إشارات الإخراج لـ ALU في دورة "Nand ​​to Tetris"؟

StackOverflow https://stackoverflow.com/questions/576242

  •  05-09-2019
  •  | 
  •  

سؤال

على الرغم من أنني قمت بوضع علامة على هذا الواجب المنزلي، إلا أنه في الواقع يتعلق بدورة أقوم بها بمفردي مجانًا.على أية حال، الدورة تسمى "من Nand إلى Tetris" وآمل أن يكون شخص ما هنا قد شاهد الدورة أو شارك فيها حتى أتمكن من الحصول على بعض المساعدة.أنا في المرحلة التي أقوم فيها ببناء ALU باستخدام لغة hdl المتوفرة.مشكلتي هي أنني لا أستطيع تجميع شريحتي بشكل صحيح.تظهر لي أخطاء عندما أحاول تعيين إشارات الإخراج لوحدة 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 (في = false ، out = zr1) ؛" لن يولد هذا الخطأ ، وهو ما يقودني إلى البحث في الملحق وتجد أن المتغير الخارجي ، لأنه كان مستمدًا من الوسيط ، لا يمكن الاشتراك فيه.

هل كانت مفيدة؟

المحلول 2

كان الحل كما اقترحه باكس هو استخدام متغير وسيط كمدخل لشريحة أخرى، مثل 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 );
}

نصائح أخرى

لأي شخص آخر مهتم ، فإن الحل الذي يدعمه المحاكي هو استخدام مخرجات متعددة مثل:

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

هذه هي الطريقة التي قمت بها بـ 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);
}

هل جربت:

// 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.

يبدو أن هذا حل صالح بالنسبة لك يستطيع قم بكتابة قيم الإدخال على شريحة.

ومجرد النظر إلى الخطأ، قد تكون هذه مشكلة مختلفة عن تلك التي تقترحها.إن عبارة "لا يمكن توصيل دبوس إخراج البوابة بجزء" تعني بالنسبة لي أنك غير قادر على توصيل الإشارات من معلمة الإخراج مرة أخرى إلى منطقة معالجة الرقائق.هذا منطقي من وجهة نظر كهربائية.

قد تجد أنه يتعين عليك تخزين الإخراج في متغير مؤقت واستخدامه لكلا المجموعتين zr و out (نظرًا لأنه بمجرد "إرسال" الإشارات إلى منافذ إخراج الرقائق، فقد لا تكون متاحة بعد الآن).

هل يمكننا أن نحاول:

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

إليك أيضًا شريحة جديدة ولكنها تبدو أكثر نظافة

/**
 * 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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top