16 位 CPU 设计:实现获取执行周期的问题
16-bit CPU design: Issues with implementing fetch-execute cycle
我正在 Coursera 上开设一门名为
NandtoTetris 并一直在为我的 16 位 CPU 设计而苦苦挣扎。这
课程使用一种叫做 HDL 的语言,它是一种非常简单的 Verilog 之类的
语言。
我花了很多时间尝试迭代我的 CPU 设计基于
下图,我不明白我做错了什么。我
尽我所能来代表获取和执行机制。做
有人对如何解决这个问题有任何建议吗?
这里是设计和控制语法图链接:
CPU IO 高级图:
门级CPU示意图:
控制指令语法:
下面是我的代码:
// 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);
如果不为你做这些工作就回答这类问题是很棘手的,从长远来看这对你没有帮助 运行。
一些一般的想法。
孤立地考虑每个元素(包括信号聚集在一起的圆圈)。
用名称标记元素之间的每一行。这些将成为内部控制线。它有助于减少混淆的机会。
小心垃圾输出。如果您不应该将有效数据放在 outM 上,请使用 Mux 输出 false。
潜在陷阱:我似乎记得使用设计输出(如 outM)作为 输入 是个坏主意别的东西。输出应该只是输出。现在您正在将 ALU 的输出发送到 outM 并将 outM 用作其他元素的输入。我建议您尝试将 ALU 输出到一个新信号 "ALUout",并将其用作其他元素的输入和(通过一个由 writeM 控制的 false 多路复用器)outM。但请记住,writeM 是一个输出!因此,生成 writeM 的块需要生成其自身的 copy 以用作对多路复用器的控制。幸运的是,一个块可以有多个 out 语句!
比如你现在这样生成outM(有没有错我不评论,只是举例说明):
And(a=instruction[15], b=instruction[3], out=writeM);
您可以像这样创建第二个输出:
And(a=instruction[15], b=instruction[3], out=writeM, out=writeM2)
然后 "clean" 你的 outM 是这样的:
Mux16(a=false,b=ALUout,sel=writeM2,out=outM);
祝你好运!
我正在 Coursera 上开设一门名为 NandtoTetris 并一直在为我的 16 位 CPU 设计而苦苦挣扎。这 课程使用一种叫做 HDL 的语言,它是一种非常简单的 Verilog 之类的 语言。
我花了很多时间尝试迭代我的 CPU 设计基于 下图,我不明白我做错了什么。我 尽我所能来代表获取和执行机制。做 有人对如何解决这个问题有任何建议吗?
这里是设计和控制语法图链接:
CPU IO 高级图:
门级CPU示意图:
控制指令语法:
下面是我的代码:
// 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);
如果不为你做这些工作就回答这类问题是很棘手的,从长远来看这对你没有帮助 运行。
一些一般的想法。
孤立地考虑每个元素(包括信号聚集在一起的圆圈)。
用名称标记元素之间的每一行。这些将成为内部控制线。它有助于减少混淆的机会。
小心垃圾输出。如果您不应该将有效数据放在 outM 上,请使用 Mux 输出 false。
潜在陷阱:我似乎记得使用设计输出(如 outM)作为 输入 是个坏主意别的东西。输出应该只是输出。现在您正在将 ALU 的输出发送到 outM 并将 outM 用作其他元素的输入。我建议您尝试将 ALU 输出到一个新信号 "ALUout",并将其用作其他元素的输入和(通过一个由 writeM 控制的 false 多路复用器)outM。但请记住,writeM 是一个输出!因此,生成 writeM 的块需要生成其自身的 copy 以用作对多路复用器的控制。幸运的是,一个块可以有多个 out 语句!
比如你现在这样生成outM(有没有错我不评论,只是举例说明):
And(a=instruction[15], b=instruction[3], out=writeM);
您可以像这样创建第二个输出:
And(a=instruction[15], b=instruction[3], out=writeM, out=writeM2)
然后 "clean" 你的 outM 是这样的:
Mux16(a=false,b=ALUout,sel=writeM2,out=outM);
祝你好运!