Дизайн 16-битного процессора: проблемы с реализацией цикла выборки-выполнения

Я прохожу курс по компьютерной архитектуре на Coursera под названием NandtoTetris и борюсь с дизайном моего 16-битного процессора. В курсе используется язык под названием HDL, очень простой язык, похожий на Verilog.

Я потратил так много часов, пытаясь повторить дизайн моего процессора на основе диаграммы ниже, и я не понимаю, что я делаю неправильно. Я изо всех сил старался представить механику извлечения и выполнения. Есть ли у кого-нибудь совет, как это решить?

Вот ссылки на синтаксическую диаграмму дизайна и управления:

Диаграмма высокого уровня ввода-вывода процессора: введите здесь описание изображения

Диаграмма ЦП на уровне шлюза: введите здесь описание изображения

Синтаксис инструкции управления: введите здесь описание изображения

Вот мой код ниже:

    // Put your code here:

    // Instruction decoding:from i of “ixxaccccccdddjjj” 
    // Ainstruction: Instruction is 16-bit value of the constant that should be loaded into the A register
    // C-instruction: The a- and c-bits code comp part, d- and j-bits code dest and jump(x-bits are ignored). 
    Mux16(a=outM, b=instruction, sel=instruction[15], out=aMUX); // 0 for A-instruction or 1 for a C-instruction  
    Not(in=instruction[15], out=aInst); // assert A instruction with op-code as true 
    And(a=instruction[15], b=instruction[5], out=cInst); // assert wite-to-A-C-instruction with op code AND d1-bit
    Or(a=aInst, b=cInst, out=aMuxload); // assert Ainstruction or wite-to-A-C-instruction is true
    ARegister(in=aMUX, load=cInst, out=addressM); // load Ainstruction or wite-to-A-C-instruction 


    //  For C-instruction, a-bit determines if ALU will operate on A register input (0) vs M input (1)
    And(a=instruction[15], b=instruction[12], out=Aselector); // assert that c instruction AND a-bit 
    Mux16(a=addressM, b=inM, sel=Aselector, out=aluMUX); // select A=0 or A=1           
    ALU(x=DregisterOut, y=aluMUX, zx=instruction[11], nx=instruction[10], zy=instruction[9], ny=instruction[8], f=instruction[7], no=instruction[6], zr=zr, ng=ng,out=outM); 

    // The 3 d-bits of “ixxaccccccdddjjj” ALUout determine registers are destinations for for ALUout
    // Whenever there is a C-Instruction and d2 (bit 4) is a 1 the D register is loaded
    And(a=instruction[15], b=instruction[4], out=writeD); // assert that c instruction AND d2-bit
    DRegister(in=outM, load=writeD, out=DregisterOut); // d2 of d-bits for D register destination 

    // Whenever there is a C-Instruction and d3 (bit 3) is a 1 then writeM (aka RAM[A]) is true
    And(a=instruction[15], b=instruction[3], out=writeM); // assert that c instruction AND d3-bit  

    // Programe counter to fetch next instruction
    // PC logic: if (reset==1), then PC = 0
    //           else:
    //                load  = comparison(instruction jump bits, ALU output zr & ng)
    //                if load == 1, PC = A
    //                else: PC ++   
    And(a=instruction[2], b=ng, out=JLT); // J2 test against ng: out < 0
    And(a=instruction[1], b=zr, out=JEQ); // J1 test against zr: out = 0
    Or(a=ng, b=zr, out=JGToutMnot)); // J0 test if ng and zr are both zero
    Not(in=JGToutMnot, out=JGToutM; // J0 test if ng and zr are both zero
    And(a=instruction[0], b=JGToutM, out=JGT);
    Or(a=JLT, b=JEQ, out=JLE); // out <= 0  
    Or(a=JGT, b=JLE, out=JMP); // final jump assertion
    And(a=instruction[15], b=JMP, out=PCload); // C instruction AND JMP assert to get the PC load bit
    // load in all values into the programme counter if load and reset, otherwise continue increasing
    PC(in=addressM, load=PCload, inc=true, reset=reset, out=pc);     

person Kgotso Koete    schedule 21.02.2019    source источник


Ответы (1)


Сложно ответить на такие вопросы, не выполняя работу за вас, что в долгосрочной перспективе не принесет вам пользы.

Некоторые общие мысли.

  • Рассмотрим каждый элемент отдельно (включая круги, где сигналы сходятся).

  • Пометьте каждую строку между элементами именем. Они станут линиями внутреннего контроля. Это помогает снизить вероятность путаницы.

  • Будьте очень осторожны с нежелательными выводами. Если вы не должны помещать действительные данные в outM, используйте Mux для вывода false.

Возможная загвоздка: я, кажется, помню, что использовать выходные данные проекта (например, outM) в качестве входных для чего-то другого — плохая идея. Выходы должны быть только выходами. Прямо сейчас вы отправляете выходные данные АЛУ в outM и используете outM в качестве входных данных для других элементов. Я предлагаю вам попробовать вывести ALU на новый сигнал «ALUout» и использовать его в качестве входа для других элементов и (через мультиплексор с ложным управлением writeM) outM. Но помните, writeM — это выход! Таким образом, блок, генерирующий writeM, должен создать копию самого себя, чтобы использовать его в качестве управления мультиплексором. К счастью, в блоке может быть несколько операторов out!

Например, прямо сейчас вы генерируете outM вот так (я не буду комментировать, неправильно ли это, я просто использую это как иллюстрацию):

And(a=instruction[15], b=instruction[3], out=writeM); 

Вы можете создать второй вывод следующим образом:

And(a=instruction[15], b=instruction[3], out=writeM, out=writeM2)

а затем «очистить» свой outM следующим образом:

Mux16(a=false,b=ALUout,sel=writeM2,out=outM);

Удачи!

person MadOverlord    schedule 21.02.2019
comment
Огромное спасибо. Я должен был указать входной и выходной API для дизайна ЦП, и это облегчило бы вам понимание всех выходов в чипах. Оказывается, самая большая проблема заключалась в том, что окончательный вывод регистра А должен был быть 15-битным вместо 16, в то время как вывод регистра А, который подается на второй мультиплексор, был правильным — 16-битным. Несовпадение размеров шин для выходов регистра А в принципе, и для счетчика программ (ПК) :). - person Kgotso Koete; 21.02.2019