added v2.0
BIN
05_Computer_Architecture/01_CPU/CPU.dia
Normal file
BIN
05_Computer_Architecture/01_CPU/CPU.png
Normal file
After Width: | Height: | Size: 23 KiB |
48
05_Computer_Architecture/01_CPU/CPU_tb.gtkw
Normal file
@@ -0,0 +1,48 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Fri Dec 23 09:59:16 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/01_CPU/CPU_tb.vcd"
|
||||
[dumpfile_mtime] "Fri Dec 23 09:58:03 2022"
|
||||
[dumpfile_size] 3204741
|
||||
[savefile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/01_CPU/CPU_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1866 600
|
||||
[pos] -1 -1
|
||||
*-3.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] CPU_tb.
|
||||
[sst_width] 281
|
||||
[signals_width] 210
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 132
|
||||
@28
|
||||
CPU_tb.clk
|
||||
@200
|
||||
-IN
|
||||
@22
|
||||
CPU_tb.inM[15:0]
|
||||
CPU_tb.instruction[15:0]
|
||||
@28
|
||||
CPU_tb.reset
|
||||
@200
|
||||
-OUT
|
||||
@22
|
||||
CPU_tb.addressM[15:0]
|
||||
CPU_tb.outM[15:0]
|
||||
CPU_tb.pc[15:0]
|
||||
@28
|
||||
CPU_tb.writeM
|
||||
@200
|
||||
-CMP
|
||||
@22
|
||||
CPU_tb.addressM_cmp[15:0]
|
||||
CPU_tb.out_cmp[15:0]
|
||||
CPU_tb.pc_cmp[15:0]
|
||||
@28
|
||||
CPU_tb.writeM_cmp
|
||||
@200
|
||||
-Test
|
||||
@28
|
||||
CPU_tb.fail
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
86
05_Computer_Architecture/01_CPU/CPU_tb.v
Normal file
@@ -0,0 +1,86 @@
|
||||
`default_nettype none
|
||||
module CPU_tb();
|
||||
|
||||
// IN,OUT
|
||||
reg clk=1;
|
||||
reg [15:0] inM=0;
|
||||
reg [15:0] instruction=0;
|
||||
reg reset=1;
|
||||
wire [15:0] outM;
|
||||
wire writeM;
|
||||
wire [15:0] addressM;
|
||||
wire [15:0] pc;
|
||||
|
||||
// Part
|
||||
CPU CPU(
|
||||
.clk(clk),
|
||||
.inM(inM),
|
||||
.instruction(instruction),
|
||||
.reset(reset),
|
||||
.outM(outM),
|
||||
.writeM(writeM),
|
||||
.addressM(addressM),
|
||||
.pc(pc)
|
||||
);
|
||||
|
||||
// Simulation
|
||||
always #1 clk=~clk;
|
||||
always @(posedge clk) begin
|
||||
inM <= $random;
|
||||
reset <= (n<=10) || ((n>20) && (n<40));
|
||||
instruction <= $random;
|
||||
end
|
||||
|
||||
// Compare
|
||||
reg [15:0] addressM_cmp=0;
|
||||
reg [15:0] regD=0;
|
||||
reg [15:0] pc_cmp=0;
|
||||
reg zx,nx,zy,ny,f,no;
|
||||
wire [15:0] out_cmp;
|
||||
wire [15:0] x,y;
|
||||
wire zr,ng;
|
||||
assign x = instruction[10]?(instruction[11]?~0:~regD):(instruction[11]?0:regD);
|
||||
assign y = instruction[8]?(instruction[9]?~0:~(instruction[12]?inM:addressM_cmp)):(instruction[9]?0:(instruction[12]?inM:addressM_cmp));
|
||||
assign out_cmp = instruction[6]?(instruction[7]?~(x+y):~(x&y)):(instruction[7]?(x+y):(x&y));
|
||||
wire comp;
|
||||
wire jmp;
|
||||
assign comp = instruction[15] && instruction[14] && instruction[13];
|
||||
assign zr = (out_cmp==0);
|
||||
assign ng = out_cmp[15];
|
||||
assign jmp = comp && ((ng&&instruction[2])||(zr&&instruction[1])||(~(ng|zr)&&instruction[0]));
|
||||
always @(posedge clk) begin
|
||||
addressM_cmp <= comp?(instruction[5]?out_cmp:addressM_cmp) : instruction;
|
||||
regD <= comp?(instruction[4]?out_cmp:regD) : regD;
|
||||
pc_cmp <= reset?0 : (jmp?addressM_cmp:pc_cmp+1);
|
||||
end
|
||||
wire writeM_cmp;
|
||||
assign writeM_cmp = comp?instruction[3]:0;
|
||||
|
||||
reg fail = 0;
|
||||
reg [15:0] n = 0;
|
||||
task check;
|
||||
#1
|
||||
if ((pc != pc_cmp) || (addressM != addressM_cmp) || (outM != out_cmp) || (writeM != writeM_cmp))
|
||||
begin
|
||||
$display("FAIL: clk=%1b, inM=%16b, instruction=%16b, reset=%1b, outM=%16b, writeM=%1b, addressM=%16b, pc=%16b",clk,inM,instruction,reset,outM,writeM,addressM,pc);
|
||||
fail=1;
|
||||
end
|
||||
endtask
|
||||
|
||||
// Test
|
||||
initial begin
|
||||
$dumpfile("CPU_tb.vcd");
|
||||
$dumpvars(0, CPU_tb);
|
||||
|
||||
$display("------------------------");
|
||||
$display("Testbench: CPU");
|
||||
|
||||
for (n=0; n<1000;n=n+1)
|
||||
check();
|
||||
|
||||
if (fail==0) $display("passed");
|
||||
$display("------------------------");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
33
05_Computer_Architecture/01_CPU/Include.v
Normal file
@@ -0,0 +1,33 @@
|
||||
`include "../../01_Boolean_Logic/Nand.v"
|
||||
`include "../../01_Boolean_Logic/Not.v"
|
||||
`include "../../01_Boolean_Logic/Buffer.v"
|
||||
`include "../../01_Boolean_Logic/And.v"
|
||||
`include "../../01_Boolean_Logic/Or.v"
|
||||
`include "../../01_Boolean_Logic/Xor.v"
|
||||
`include "../../01_Boolean_Logic/Mux.v"
|
||||
`include "../../01_Boolean_Logic/DMux.v"
|
||||
`include "../../01_Boolean_Logic/Not16.v"
|
||||
`include "../../01_Boolean_Logic/Buffer16.v"
|
||||
`include "../../01_Boolean_Logic/And16.v"
|
||||
`include "../../01_Boolean_Logic/Or16.v"
|
||||
`include "../../01_Boolean_Logic/Mux16.v"
|
||||
`include "../../01_Boolean_Logic/Or8Way.v"
|
||||
`include "../../01_Boolean_Logic/Mux4Way16.v"
|
||||
`include "../../01_Boolean_Logic/Mux8Way16.v"
|
||||
`include "../../01_Boolean_Logic/DMux4Way.v"
|
||||
`include "../../01_Boolean_Logic/DMux8Way.v"
|
||||
|
||||
`include "../../02_Boolean_Arithmetic/HalfAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/FullAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/Add16.v"
|
||||
`include "../../02_Boolean_Arithmetic/Inc16.v"
|
||||
`include "../../02_Boolean_Arithmetic/ALU.v"
|
||||
|
||||
`include "../../03_Sequential_Logic/DFF.v"
|
||||
`include "../../03_Sequential_Logic/Bit.v"
|
||||
`include "../../03_Sequential_Logic/Register.v"
|
||||
`include "../../03_Sequential_Logic/PC.v"
|
||||
`include "../../03_Sequential_Logic/BitShift9R.v"
|
||||
`include "../../03_Sequential_Logic/BitShift8L.v"
|
||||
|
||||
`include "../../05_Computer_Architecture/CPU.v"
|
3
05_Computer_Architecture/01_CPU/apio.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[env]
|
||||
board = iCE40-HX1K-EVB
|
||||
|
34
05_Computer_Architecture/02_Memory/Include.v
Normal file
@@ -0,0 +1,34 @@
|
||||
`include "../../01_Boolean_Logic/Nand.v"
|
||||
`include "../../01_Boolean_Logic/Not.v"
|
||||
`include "../../01_Boolean_Logic/Buffer.v"
|
||||
`include "../../01_Boolean_Logic/And.v"
|
||||
`include "../../01_Boolean_Logic/Or.v"
|
||||
`include "../../01_Boolean_Logic/Xor.v"
|
||||
`include "../../01_Boolean_Logic/Mux.v"
|
||||
`include "../../01_Boolean_Logic/DMux.v"
|
||||
`include "../../01_Boolean_Logic/Not16.v"
|
||||
`include "../../01_Boolean_Logic/Buffer16.v"
|
||||
`include "../../01_Boolean_Logic/And16.v"
|
||||
`include "../../01_Boolean_Logic/Or16.v"
|
||||
`include "../../01_Boolean_Logic/Mux16.v"
|
||||
`include "../../01_Boolean_Logic/Or8Way.v"
|
||||
`include "../../01_Boolean_Logic/Mux4Way16.v"
|
||||
`include "../../01_Boolean_Logic/Mux8Way16.v"
|
||||
`include "../../01_Boolean_Logic/DMux4Way.v"
|
||||
`include "../../01_Boolean_Logic/DMux8Way.v"
|
||||
|
||||
`include "../../02_Boolean_Arithmetic/HalfAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/FullAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/Add16.v"
|
||||
`include "../../02_Boolean_Arithmetic/Inc16.v"
|
||||
`include "../../02_Boolean_Arithmetic/ALU.v"
|
||||
|
||||
`include "../../03_Sequential_Logic/DFF.v"
|
||||
`include "../../03_Sequential_Logic/Bit.v"
|
||||
`include "../../03_Sequential_Logic/Register.v"
|
||||
`include "../../03_Sequential_Logic/PC.v"
|
||||
`include "../../03_Sequential_Logic/BitShift9R.v"
|
||||
`include "../../03_Sequential_Logic/BitShift8L.v"
|
||||
|
||||
`include "../../05_Computer_Architecture/CPU.v"
|
||||
`include "../../05_Computer_Architecture/Memory.v"
|
67
05_Computer_Architecture/02_Memory/Memory_tb.gtkw
Normal file
@@ -0,0 +1,67 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Tue Nov 22 10:53:14 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/02_Memory/Memory_tb.vcd"
|
||||
[dumpfile_mtime] "Tue Nov 22 10:50:29 2022"
|
||||
[dumpfile_size] 15133403
|
||||
[savefile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/02_Memory/Memory_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1920 963
|
||||
[pos] -1 -1
|
||||
*0.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 281
|
||||
[signals_width] 160
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 258
|
||||
@200
|
||||
-IN
|
||||
@22
|
||||
Memory_tb.address[15:0]
|
||||
Memory_tb.inRAM[15:0]
|
||||
Memory_tb.inIO0[15:0]
|
||||
Memory_tb.inIO1[15:0]
|
||||
Memory_tb.inIO2[15:0]
|
||||
Memory_tb.inIO3[15:0]
|
||||
Memory_tb.inIO4[15:0]
|
||||
Memory_tb.inIO5[15:0]
|
||||
Memory_tb.inIO6[15:0]
|
||||
Memory_tb.inIO7[15:0]
|
||||
Memory_tb.inIO8[15:0]
|
||||
Memory_tb.inIO9[15:0]
|
||||
Memory_tb.inIOA[15:0]
|
||||
Memory_tb.inIOB[15:0]
|
||||
Memory_tb.inIOC[15:0]
|
||||
Memory_tb.inIOD[15:0]
|
||||
Memory_tb.inIOE[15:0]
|
||||
Memory_tb.inIOF[15:0]
|
||||
@28
|
||||
Memory_tb.load
|
||||
@200
|
||||
-OUT
|
||||
@22
|
||||
Memory_tb.out[15:0]
|
||||
@28
|
||||
Memory_tb.loadRAM
|
||||
Memory_tb.loadIO0
|
||||
Memory_tb.loadIO1
|
||||
Memory_tb.loadIO2
|
||||
Memory_tb.loadIO3
|
||||
Memory_tb.loadIO4
|
||||
Memory_tb.loadIO5
|
||||
Memory_tb.loadIO6
|
||||
Memory_tb.loadIO7
|
||||
Memory_tb.loadIO8
|
||||
Memory_tb.loadIO9
|
||||
Memory_tb.loadIOA
|
||||
Memory_tb.loadIOB
|
||||
Memory_tb.loadIOC
|
||||
Memory_tb.loadIOD
|
||||
Memory_tb.loadIOE
|
||||
Memory_tb.loadIOF
|
||||
@200
|
||||
-Test
|
||||
@29
|
||||
Memory_tb.fail
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
180
05_Computer_Architecture/02_Memory/Memory_tb.v
Normal file
@@ -0,0 +1,180 @@
|
||||
`default_nettype none
|
||||
module Memory_tb();
|
||||
|
||||
// IN,OUT
|
||||
reg [15:0] address;
|
||||
reg load;
|
||||
wire [15:0] out;
|
||||
wire loadRAM;
|
||||
wire loadIO0;
|
||||
wire loadIO1;
|
||||
wire loadIO2;
|
||||
wire loadIO3;
|
||||
wire loadIO4;
|
||||
wire loadIO5;
|
||||
wire loadIO6;
|
||||
wire loadIO7;
|
||||
wire loadIO8;
|
||||
wire loadIO9;
|
||||
wire loadIOA;
|
||||
wire loadIOB;
|
||||
wire loadIOC;
|
||||
wire loadIOD;
|
||||
wire loadIOE;
|
||||
wire loadIOF;
|
||||
reg [15:0] inRAM;
|
||||
reg [15:0] inIO0;
|
||||
reg [15:0] inIO1;
|
||||
reg [15:0] inIO2;
|
||||
reg [15:0] inIO3;
|
||||
reg [15:0] inIO4;
|
||||
reg [15:0] inIO5;
|
||||
reg [15:0] inIO6;
|
||||
reg [15:0] inIO7;
|
||||
reg [15:0] inIO8;
|
||||
reg [15:0] inIO9;
|
||||
reg [15:0] inIOA;
|
||||
reg [15:0] inIOB;
|
||||
reg [15:0] inIOC;
|
||||
reg [15:0] inIOD;
|
||||
reg [15:0] inIOE;
|
||||
reg [15:0] inIOF;
|
||||
|
||||
// Part
|
||||
Memory MEMORY(
|
||||
.address(address),
|
||||
.load(load),
|
||||
.out(out),
|
||||
.loadRAM(loadRAM),
|
||||
.loadIO0(loadIO0),
|
||||
.loadIO1(loadIO1),
|
||||
.loadIO2(loadIO2),
|
||||
.loadIO3(loadIO3),
|
||||
.loadIO4(loadIO4),
|
||||
.loadIO5(loadIO5),
|
||||
.loadIO6(loadIO6),
|
||||
.loadIO7(loadIO7),
|
||||
.loadIO8(loadIO8),
|
||||
.loadIO9(loadIO9),
|
||||
.loadIOA(loadIOA),
|
||||
.loadIOB(loadIOB),
|
||||
.loadIOC(loadIOC),
|
||||
.loadIOD(loadIOD),
|
||||
.loadIOE(loadIOE),
|
||||
.loadIOF(loadIOF),
|
||||
.inRAM(inRAM),
|
||||
.inIO0(inIO0),
|
||||
.inIO1(inIO1),
|
||||
.inIO2(inIO2),
|
||||
.inIO3(inIO3),
|
||||
.inIO4(inIO4),
|
||||
.inIO5(inIO5),
|
||||
.inIO6(inIO6),
|
||||
.inIO7(inIO7),
|
||||
.inIO8(inIO8),
|
||||
.inIO9(inIO9),
|
||||
.inIOA(inIOA),
|
||||
.inIOB(inIOB),
|
||||
.inIOC(inIOC),
|
||||
.inIOD(inIOD),
|
||||
.inIOE(inIOE),
|
||||
.inIOF(inIOF)
|
||||
);
|
||||
|
||||
// Compare
|
||||
reg fail = 0;
|
||||
wire [15:0] out_cmp;
|
||||
assign out_cmp = ((address==4096)?inIO0:
|
||||
(address==4097)?inIO1:
|
||||
(address==4098)?inIO2:
|
||||
(address==4099)?inIO3:
|
||||
(address==4100)?inIO4:
|
||||
(address==4101)?inIO5:
|
||||
(address==4102)?inIO6:
|
||||
(address==4103)?inIO7:
|
||||
(address==4104)?inIO8:
|
||||
(address==4105)?inIO9:
|
||||
(address==4106)?inIOA:
|
||||
(address==4107)?inIOB:
|
||||
(address==4108)?inIOC:
|
||||
(address==4109)?inIOD:
|
||||
(address==4110)?inIOE:
|
||||
(address==4111)?inIOF:
|
||||
inRAM);
|
||||
wire loadRAM_cmp,loadIO0_cmp,loadIO1_cmp,loadIO2_cmp,loadIO3_cmp,loadIO4_cmp,loadIO5_cmp,loadIO6_cmp,loadIO7_cmp,
|
||||
loadIO8_cmp,loadIO9_cmp,loadIOA_cmp,loadIOB_cmp,loadIOC_cmp,loadIOD_cmp,loadIOE_cmp,loadIOF_cmp;
|
||||
assign loadRAM_cmp = (address<=3839)?load:0;
|
||||
assign loadIO0_cmp = (address==4096)?load:0;
|
||||
assign loadIO1_cmp = (address==4097)?load:0;
|
||||
assign loadIO2_cmp = (address==4098)?load:0;
|
||||
assign loadIO3_cmp = (address==4099)?load:0;
|
||||
assign loadIO4_cmp = (address==4100)?load:0;
|
||||
assign loadIO5_cmp = (address==4101)?load:0;
|
||||
assign loadIO6_cmp = (address==4102)?load:0;
|
||||
assign loadIO7_cmp = (address==4103)?load:0;
|
||||
assign loadIO8_cmp = (address==4104)?load:0;
|
||||
assign loadIO9_cmp = (address==4105)?load:0;
|
||||
assign loadIOA_cmp = (address==4106)?load:0;
|
||||
assign loadIOB_cmp = (address==4107)?load:0;
|
||||
assign loadIOC_cmp = (address==4108)?load:0;
|
||||
assign loadIOD_cmp = (address==4109)?load:0;
|
||||
assign loadIOE_cmp = (address==4110)?load:0;
|
||||
assign loadIOF_cmp = (address==4111)?load:0;
|
||||
|
||||
task check;
|
||||
#1
|
||||
if ((out!=out_cmp)||(loadRAM!=loadRAM_cmp)||
|
||||
(loadIO0!=loadIO0_cmp)||(loadIO1!=loadIO1_cmp)||(loadIO2!=loadIO2_cmp)||(loadIO3!=loadIO3_cmp)||
|
||||
(loadIO4!=loadIO4_cmp)||(loadIO5!=loadIO5_cmp)||(loadIO6!=loadIO6_cmp)||(loadIO7!=loadIO7_cmp)||
|
||||
(loadIO8!=loadIO8_cmp)||(loadIO9!=loadIO9_cmp)||(loadIOA!=loadIOA_cmp)||(loadIOB!=loadIOB_cmp)||
|
||||
(loadIOC!=loadIOC_cmp)||(loadIOD!=loadIOD_cmp)||(loadIOE!=loadIOE_cmp)||(loadIOF!=loadIOF_cmp))
|
||||
begin
|
||||
$display("FAIL: address=%16b, load=%1b, out=%16b, loadRAM=%1b, loadIO0=%1b, loadIO1=%1b, ... ",address,load,out,loadRAM,loadIO0,loadIO1);
|
||||
fail=1;
|
||||
end
|
||||
endtask
|
||||
|
||||
// Test
|
||||
initial begin
|
||||
$dumpfile("Memory_tb.vcd");
|
||||
$dumpvars(0, Memory_tb);
|
||||
|
||||
$display("------------------------");
|
||||
$display("Testbench: Memory");
|
||||
|
||||
inRAM=$random;
|
||||
inIO0=$random;
|
||||
inIO1=$random;
|
||||
inIO2=$random;
|
||||
inIO3=$random;
|
||||
inIO4=$random;
|
||||
inIO5=$random;
|
||||
inIO6=$random;
|
||||
inIO7=$random;
|
||||
inIO8=$random;
|
||||
inIO9=$random;
|
||||
inIOA=$random;
|
||||
inIOB=$random;
|
||||
inIOC=$random;
|
||||
inIOD=$random;
|
||||
inIOE=$random;
|
||||
inIOF=$random;
|
||||
for (address=4096; address<4112;address=address+1)
|
||||
begin
|
||||
load=0;check();
|
||||
load=1;check();
|
||||
end
|
||||
for (address=0; address<3840;address=address+1)
|
||||
begin
|
||||
inRAM=$random;
|
||||
load=0;check();
|
||||
load=1;check();
|
||||
end
|
||||
|
||||
if (fail==0) $display("passed");
|
||||
$display("------------------------");
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
3
05_Computer_Architecture/02_Memory/apio.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[env]
|
||||
board = iCE40-HX1K-EVB
|
||||
|
@@ -0,0 +1,23 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Thu Dec 29 21:52:20 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris-fpga/05_Computer_Architecture/03_Clock_Reset/Clock25_Reset20_tb.vcd"
|
||||
[dumpfile_mtime] "Thu Dec 29 21:51:50 2022"
|
||||
[dumpfile_size] 2320447
|
||||
[savefile] "/home/micha/gitlab/nand2tetris-fpga/05_Computer_Architecture/03_Clock_Reset/Clock25_Reset20_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1636 438
|
||||
[pos] -1 -1
|
||||
*-17.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 281
|
||||
[signals_width] 80
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 76
|
||||
@28
|
||||
Clock25_Reset20_tb.CLK
|
||||
Clock25_Reset20_tb.clk
|
||||
@29
|
||||
Clock25_Reset20_tb.reset
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
@@ -0,0 +1,32 @@
|
||||
`timescale 10ns/1ns
|
||||
`default_nettype none
|
||||
module Clock25_Reset20_tb();
|
||||
|
||||
// IN,OUT
|
||||
reg CLK=1;
|
||||
wire clk;
|
||||
wire reset;
|
||||
|
||||
// Part
|
||||
Clock25_Reset20 CLOCK25_RESET20(
|
||||
.CLK(CLK),
|
||||
.clk(clk),
|
||||
.reset(reset)
|
||||
);
|
||||
|
||||
// Simulation
|
||||
always #0.5 CLK=~CLK;
|
||||
|
||||
// Test
|
||||
initial begin
|
||||
$dumpfile("Clock25_Reset20_tb.vcd");
|
||||
$dumpvars(0, Clock25_Reset20_tb);
|
||||
|
||||
$display("------------------------");
|
||||
$display("Testbench: Clock25_Reset10");
|
||||
|
||||
#4000
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
33
05_Computer_Architecture/03_Clock25_Reset20/Include.v
Normal file
@@ -0,0 +1,33 @@
|
||||
`include "../../01_Boolean_Logic/Nand.v"
|
||||
`include "../../01_Boolean_Logic/Not.v"
|
||||
`include "../../01_Boolean_Logic/Buffer.v"
|
||||
`include "../../01_Boolean_Logic/And.v"
|
||||
`include "../../01_Boolean_Logic/Or.v"
|
||||
`include "../../01_Boolean_Logic/Xor.v"
|
||||
`include "../../01_Boolean_Logic/Mux.v"
|
||||
`include "../../01_Boolean_Logic/DMux.v"
|
||||
`include "../../01_Boolean_Logic/Not16.v"
|
||||
`include "../../01_Boolean_Logic/Buffer16.v"
|
||||
`include "../../01_Boolean_Logic/And16.v"
|
||||
`include "../../01_Boolean_Logic/Or16.v"
|
||||
`include "../../01_Boolean_Logic/Mux16.v"
|
||||
`include "../../01_Boolean_Logic/Or8Way.v"
|
||||
`include "../../01_Boolean_Logic/Mux4Way16.v"
|
||||
`include "../../01_Boolean_Logic/Mux8Way16.v"
|
||||
`include "../../01_Boolean_Logic/DMux4Way.v"
|
||||
`include "../../01_Boolean_Logic/DMux8Way.v"
|
||||
|
||||
`include "../../02_Boolean_Arithmetic/HalfAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/FullAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/Add16.v"
|
||||
`include "../../02_Boolean_Arithmetic/Inc16.v"
|
||||
`include "../../02_Boolean_Arithmetic/ALU.v"
|
||||
|
||||
`include "../../03_Sequential_Logic/DFF.v"
|
||||
`include "../../03_Sequential_Logic/Bit.v"
|
||||
`include "../../03_Sequential_Logic/Register.v"
|
||||
`include "../../03_Sequential_Logic/PC.v"
|
||||
`include "../../03_Sequential_Logic/BitShift9R.v"
|
||||
`include "../../03_Sequential_Logic/BitShift8L.v"
|
||||
|
||||
`include "../../05_Computer_Architecture/Clock25_Reset20.v"
|
3
05_Computer_Architecture/03_Clock25_Reset20/apio.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[env]
|
||||
board = iCE40-HX1K-EVB
|
||||
|
BIN
05_Computer_Architecture/03_Clock25_Reset20/clock.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
05_Computer_Architecture/03_Clock25_Reset20/reset.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
05_Computer_Architecture/04_HACK/CPU.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
05_Computer_Architecture/04_HACK/HACK.dia
Normal file
BIN
05_Computer_Architecture/04_HACK/HACK.png
Normal file
After Width: | Height: | Size: 48 KiB |
42
05_Computer_Architecture/04_HACK/HACK_tb.gtkw
Normal file
@@ -0,0 +1,42 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Mon Dec 12 16:41:42 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/04_HACK/HACK_tb.vcd"
|
||||
[dumpfile_mtime] "Mon Dec 12 16:41:24 2022"
|
||||
[dumpfile_size] 5432004
|
||||
[savefile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/04_HACK/HACK_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1673 487
|
||||
[pos] 118 133
|
||||
*-23.000000 50 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] HACK_tb.
|
||||
[sst_width] 281
|
||||
[signals_width] 180
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 98
|
||||
@200
|
||||
-IN
|
||||
@28
|
||||
HACK_tb.CLK
|
||||
HACK_tb.BUT[1:0]
|
||||
@200
|
||||
-OUT
|
||||
@28
|
||||
HACK_tb.LED[1:0]
|
||||
@200
|
||||
-DEBUG
|
||||
@28
|
||||
HACK_tb.HACK.loadDEBUG0
|
||||
@24
|
||||
HACK_tb.HACK.outDEBUG0[15:0]
|
||||
@28
|
||||
HACK_tb.HACK.loadDEBUG1
|
||||
@24
|
||||
HACK_tb.HACK.outDEBUG1[15:0]
|
||||
@28
|
||||
HACK_tb.HACK.loadDEBUG2
|
||||
@24
|
||||
HACK_tb.HACK.outDEBUG2[15:0]
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
30
05_Computer_Architecture/04_HACK/HACK_tb.v
Normal file
@@ -0,0 +1,30 @@
|
||||
`timescale 10ns/1ns
|
||||
`default_nettype none
|
||||
module HACK_tb();
|
||||
|
||||
// IN,OUT
|
||||
reg CLK = 1;
|
||||
reg [1:0] BUT = 0;
|
||||
wire [1:0] LED;
|
||||
|
||||
// Part
|
||||
HACK HACK(
|
||||
.CLK(CLK),
|
||||
.BUT(BUT),
|
||||
.LED(LED)
|
||||
);
|
||||
|
||||
// Simulate
|
||||
always #500 BUT <= BUT+1;
|
||||
|
||||
// Test
|
||||
always #0.5 CLK = ~CLK;
|
||||
initial begin
|
||||
$dumpfile("HACK_tb.vcd");
|
||||
$dumpvars(0, HACK_tb);
|
||||
|
||||
#4000
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
68
05_Computer_Architecture/04_HACK/Hack_tb.gtkw
Normal file
@@ -0,0 +1,68 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Mon Nov 28 10:58:53 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/03_HACK/Hack_tb.vcd"
|
||||
[dumpfile_mtime] "Mon Nov 28 10:58:25 2022"
|
||||
[dumpfile_size] 3140780
|
||||
[savefile] "/home/micha/gitlab/nand2tetris/05_Computer_Architecture/03_HACK/Hack_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1920 963
|
||||
[pos] -1 -1
|
||||
*-8.420643 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] Hack_tb.
|
||||
[treeopen] Hack_tb.HACK.
|
||||
[sst_width] 281
|
||||
[signals_width] 200
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 261
|
||||
@28
|
||||
Hack_tb.HACK.clk
|
||||
@200
|
||||
-IN
|
||||
@28
|
||||
Hack_tb.RST
|
||||
Hack_tb.BUT
|
||||
@200
|
||||
-CPU
|
||||
@22
|
||||
Hack_tb.HACK.pc[15:0]
|
||||
Hack_tb.HACK.instruction[15:0]
|
||||
Hack_tb.HACK.CPU.regA[15:0]
|
||||
Hack_tb.HACK.CPU.regD[15:0]
|
||||
@200
|
||||
-MEM
|
||||
@22
|
||||
Hack_tb.HACK.MEMORY.address[15:0]
|
||||
@28
|
||||
Hack_tb.HACK.MEMORY.load
|
||||
@22
|
||||
Hack_tb.HACK.MEMORY.out[15:0]
|
||||
@200
|
||||
-OUT
|
||||
@28
|
||||
Hack_tb.LED[1:0]
|
||||
@200
|
||||
-DEBUG
|
||||
@28
|
||||
Hack_tb.HACK.loadDEBUG0
|
||||
@24
|
||||
Hack_tb.HACK.outDEBUG0[15:0]
|
||||
@28
|
||||
Hack_tb.HACK.loadDEBUG1
|
||||
@24
|
||||
Hack_tb.HACK.outDEBUG1[15:0]
|
||||
@28
|
||||
Hack_tb.HACK.loadDEBUG2
|
||||
@25
|
||||
Hack_tb.HACK.outDEBUG2[15:0]
|
||||
@28
|
||||
Hack_tb.HACK.loadDEBUG3
|
||||
@22
|
||||
Hack_tb.HACK.outDEBUG3[15:0]
|
||||
@28
|
||||
Hack_tb.HACK.loadDEBUG4
|
||||
@22
|
||||
Hack_tb.HACK.outDEBUG4[15:0]
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
40
05_Computer_Architecture/04_HACK/Include.v
Normal file
@@ -0,0 +1,40 @@
|
||||
`include "../../01_Boolean_Logic/Nand.v"
|
||||
`include "../../01_Boolean_Logic/Not.v"
|
||||
`include "../../01_Boolean_Logic/Buffer.v"
|
||||
`include "../../01_Boolean_Logic/And.v"
|
||||
`include "../../01_Boolean_Logic/Or.v"
|
||||
`include "../../01_Boolean_Logic/Xor.v"
|
||||
`include "../../01_Boolean_Logic/Mux.v"
|
||||
`include "../../01_Boolean_Logic/DMux.v"
|
||||
`include "../../01_Boolean_Logic/Not16.v"
|
||||
`include "../../01_Boolean_Logic/Buffer16.v"
|
||||
`include "../../01_Boolean_Logic/And16.v"
|
||||
`include "../../01_Boolean_Logic/Or16.v"
|
||||
`include "../../01_Boolean_Logic/Mux16.v"
|
||||
`include "../../01_Boolean_Logic/Or8Way.v"
|
||||
`include "../../01_Boolean_Logic/Mux4Way16.v"
|
||||
`include "../../01_Boolean_Logic/Mux8Way16.v"
|
||||
`include "../../01_Boolean_Logic/DMux4Way.v"
|
||||
`include "../../01_Boolean_Logic/DMux8Way.v"
|
||||
|
||||
`include "../../02_Boolean_Arithmetic/HalfAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/FullAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/Add16.v"
|
||||
`include "../../02_Boolean_Arithmetic/Inc16.v"
|
||||
`include "../../02_Boolean_Arithmetic/ALU.v"
|
||||
|
||||
`include "../../03_Sequential_Logic/DFF.v"
|
||||
`include "../../03_Sequential_Logic/Bit.v"
|
||||
`include "../../03_Sequential_Logic/Register.v"
|
||||
`include "../../03_Sequential_Logic/PC.v"
|
||||
`include "../../03_Sequential_Logic/RAM256.v"
|
||||
`include "../../03_Sequential_Logic/RAM512.v"
|
||||
`include "../../03_Sequential_Logic/RAM3840.v"
|
||||
`include "../../03_Sequential_Logic/BitShift9R.v"
|
||||
`include "../../03_Sequential_Logic/BitShift8L.v"
|
||||
|
||||
`include "../../05_Computer_Architecture/CPU.v"
|
||||
`include "../../05_Computer_Architecture/Memory.v"
|
||||
`include "../../05_Computer_Architecture/ROM.v"
|
||||
`include "../../05_Computer_Architecture/Clock25_Reset20.v"
|
||||
`include "../../05_Computer_Architecture/HACK.v"
|
3
05_Computer_Architecture/04_HACK/apio.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[env]
|
||||
board = iCE40-HX1K-EVB
|
||||
|
11
05_Computer_Architecture/04_HACK/iCE40HX1K.pcf
Normal file
@@ -0,0 +1,11 @@
|
||||
# physical constrain file
|
||||
# assign io-pins to pin numbering of iCE40-HX1K on olimex board iCE40-HX1K-EVB
|
||||
# compare to the schematic of the board and the datasheet of fpga
|
||||
|
||||
set_io CLK 15
|
||||
set_io BUT[0] 41
|
||||
set_io BUT[1] 42
|
||||
|
||||
set_io LED[0] 40
|
||||
set_io LED[1] 51
|
||||
|
BIN
05_Computer_Architecture/04_HACK/leds.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
05_Computer_Architecture/04_HACK/mult.png
Normal file
After Width: | Height: | Size: 82 KiB |
40
05_Computer_Architecture/CPU.v
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* The Hack CPU (Central Processing unit), consisting of an ALU,
|
||||
* two registers named A and D, and a program counter named PC.
|
||||
* The CPU is designed to fetch and execute instructions written in
|
||||
* the Hack machine language. In particular, functions as follows:
|
||||
* Executes the inputted instruction according to the Hack machine
|
||||
* language specification. The D and A in the language specification
|
||||
* refer to CPU-resident registers, while M refers to the external
|
||||
* memory location addressed by A, i.e. to Memory[A]. The inM input
|
||||
* holds the value of this location. If the current instruction needs
|
||||
* to write a value to M, the value is placed in outM, the address
|
||||
* of the target location is placed in the addressM output, and the
|
||||
* writeM control bit is asserted. (When writeM==0, any value may
|
||||
* appear in outM). The outM and writeM outputs are combinational:
|
||||
* they are affected instantaneously by the execution of the current
|
||||
* instruction. The addressM and pc outputs are clocked: although they
|
||||
* are affected by the execution of the current instruction, they commit
|
||||
* to their new values only in the next time step. If reset==1 then the
|
||||
* CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather
|
||||
* than to the address resulting from executing the current instruction.
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
module CPU(
|
||||
input clk,
|
||||
input [15:0] inM, // M value input (M = contents of RAM[A])
|
||||
input [15:0] instruction, // Instruction for execution
|
||||
input reset, // Signals whether to re-start the current
|
||||
// program (reset==1) or continue executing
|
||||
// the current program (reset==0).
|
||||
|
||||
output [15:0] outM, // M value output
|
||||
output writeM, // Write to M?
|
||||
output [15:0] addressM, // Address in data memory (of M) to read
|
||||
output [15:0] pc // address of next instruction
|
||||
);
|
||||
|
||||
// Put your code here:
|
||||
|
||||
endmodule
|
15
05_Computer_Architecture/Clock25_Reset20.v
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Uses CLK of 100MHz to generate:
|
||||
* internal clock signal clk with 25MHz and
|
||||
* a reset signal of approx. 20us length
|
||||
*/
|
||||
`default_nettype none
|
||||
module Clock25_Reset20(
|
||||
input CLK, // external clock 100 MHz
|
||||
output clk, // internal clock 25 Mhz
|
||||
output reset // reset signal approx. 20us
|
||||
);
|
||||
|
||||
// Put your code here:
|
||||
|
||||
endmodule
|
19
05_Computer_Architecture/HACK.v
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* The HACK computer, including CPU, ROM, RAM and the generator for
|
||||
* reset and clk (25MHz) signal. For approx. 20us HACK CPU resets.
|
||||
* From this point onward the user is at the mercy of the software.
|
||||
* In particular, depending on the program's code, the LED may show
|
||||
* some output and the user may be able to interact with the computer
|
||||
* via the BUT.
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
module HACK(
|
||||
input CLK, // external clock 100 MHz
|
||||
input [1:0] BUT, // user button (0 if pressed, 1 if released)
|
||||
output [1:0] LED // leds (0 off, 1 on)
|
||||
);
|
||||
|
||||
// Put your code here:
|
||||
|
||||
endmodule
|
60
05_Computer_Architecture/Memory.v
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* The complete address space of the Hack computer's memory,
|
||||
* including RAM and memory-mapped I/O.
|
||||
* The chip facilitates read and write operations, as follows:
|
||||
* Read: out(t) = Memory[address(t)](t)
|
||||
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
|
||||
* In words: the chip always outputs the value stored at the memory
|
||||
* location specified by address. If load==1, the in value is loaded
|
||||
* into the memory location specified by address. This value becomes
|
||||
* available through the out output from the next time step onward.
|
||||
* Address space rules:
|
||||
* RAM 0x0000 - 0x0EFF (3840 words)
|
||||
* IO 0x1000 - 0x100F (maps to 16 different devices)
|
||||
* The behavior of IO addresses is described in 06_IO-Devices
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
module Memory(
|
||||
input [15:0] address,
|
||||
input load,
|
||||
output [15:0] out,
|
||||
output loadRAM,
|
||||
output loadIO0,
|
||||
output loadIO1,
|
||||
output loadIO2,
|
||||
output loadIO3,
|
||||
output loadIO4,
|
||||
output loadIO5,
|
||||
output loadIO6,
|
||||
output loadIO7,
|
||||
output loadIO8,
|
||||
output loadIO9,
|
||||
output loadIOA,
|
||||
output loadIOB,
|
||||
output loadIOC,
|
||||
output loadIOD,
|
||||
output loadIOE,
|
||||
output loadIOF,
|
||||
input [15:0] inRAM,
|
||||
input [15:0] inIO0,
|
||||
input [15:0] inIO1,
|
||||
input [15:0] inIO2,
|
||||
input [15:0] inIO3,
|
||||
input [15:0] inIO4,
|
||||
input [15:0] inIO5,
|
||||
input [15:0] inIO6,
|
||||
input [15:0] inIO7,
|
||||
input [15:0] inIO8,
|
||||
input [15:0] inIO9,
|
||||
input [15:0] inIOA,
|
||||
input [15:0] inIOB,
|
||||
input [15:0] inIOC,
|
||||
input [15:0] inIOD,
|
||||
input [15:0] inIOE,
|
||||
input [15:0] inIOF
|
||||
);
|
||||
|
||||
// Put your code here:
|
||||
|
||||
endmodule
|
26
05_Computer_Architecture/ROM.v
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* instruction memory at boot time
|
||||
* The instruction memory is read only (ROM) and
|
||||
* preloaded with 256 x 16bit of Hackcode holding the bootloader.
|
||||
*
|
||||
* instruction = ROM[pc]
|
||||
*/
|
||||
|
||||
`default_nettype none
|
||||
module ROM(
|
||||
input [15:0] pc,
|
||||
output [15:0] instruction
|
||||
);
|
||||
|
||||
// No need to implement this chip
|
||||
// The file ROM.BIN holds the hack code
|
||||
parameter ROMFILE = "ROM.hack";
|
||||
|
||||
reg [15:0] mem [0:255];
|
||||
assign instruction = mem[pc[7:0]];
|
||||
|
||||
initial begin
|
||||
$readmemb(ROMFILE,mem);
|
||||
end
|
||||
|
||||
endmodule
|
122
05_Computer_Architecture/Readme.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 05 Computer Architecture
|
||||
|
||||
Build the `HACK` computer system consisting of the chips `CPU`, `Memory`, `Clock25_Reset20`, `RAM` and `ROM`. `ROM` uses a block ram structure (256 words) of iCE40HX1K and can be considered primitive. It can be preloaded with the instructions of the assembler programs implemented in `04_Machine_Language` .
|
||||
|
||||
### 01 CPU
|
||||
|
||||
The `CPU` corresponds to the proposed implementation of nand2tetris course.
|
||||
|
||||
**Attention:** In the original specification of HACK all C instruction have the binary form: 111xxxxxxxxxxxxx and A instruction have the form 0xxxxxxxxxxxxxxx. In order to use HACK with instruction memory ROM >32K (to play tetris), we will also interpret the machine language instructions starting with 000-110 as A-instructions, allowing the following jumps for all labels up to 56K!
|
||||
|
||||
```
|
||||
@label
|
||||
0;JMP
|
||||
```
|
||||
|
||||
### 02 Memory
|
||||
|
||||
The chip `Memory.v` maps all addresses 0 - 0x0FFF to RAM and the addresses 0x1000-0x100F to the 16 special function registers used for memory mapped IO-Devices and debugging.
|
||||
|
||||
### 03 Clock25_Reset20
|
||||
|
||||
The 100 MHz (CLK) of the clock generator on the iCE40HX1K-EVB is to fast to drive our HACK design. Therefore we must scale down the external clock (CLK) of 100 MHz to the internal clock (clk) of 25Mhz using a counter `PC` .
|
||||
|
||||
HACK CPU needs a reset signal to have a proper start of the complete computer system. The fpga chip nees some time delay to preload the ROM with ROM.hack code. Therefore the reset signal at startup should have a minimal length of approximately 20us.
|
||||
|
||||
### 04 HACK
|
||||
|
||||
The chip `HACK.v` is the top level module, that connects to the outer world.
|
||||
|
||||

|
||||
|
||||
The signals wires `CLK`, `RST`, `BUT[1:0]` and `LED[1:0]` (by convention written in capital letters) connect to the outer pins of the fpga chip iCE40HX1K according to the file `iCE40HX1K.pcf`. The board iCE40-HX1K-EVB comes with a clock generator of 100 MHz, two buttons and two leds connected to FPGA (refer to [datasheets/iCE40HX1K-EVB](../datasheets/iCE40HX1K-EVB_Rev_B.pdf)).
|
||||
|
||||
| wire | iCE40HX1K (FPGA) | board iCE40HX1K-EVB |
|
||||
| ------ | ---------------- | ----------------------- |
|
||||
| CLK | 15 | 100 Mhz clock generator |
|
||||
| BUT[0] | 41 | BUT1 |
|
||||
| BUT[1] | 42 | BUT2 |
|
||||
| LED[0] | 40 | LED1 |
|
||||
| LED[1] | 51 | LED2 |
|
||||
|
||||
To add IO capability we add 7 more special function registers mapped to the following addresses:
|
||||
|
||||
| address | I/O dev | function |
|
||||
| ----------- | ------- | ---------------------------------------------------- |
|
||||
| 0 - 3839 | RAM | |
|
||||
| 4096 | LED | 0 = led off, 1 = led on |
|
||||
| 4097 | BUT | 0 = button pressed "down", 1 = button released |
|
||||
| 4098 - 4106 | | reserved for IO devices (see. project 06_IO_Devices) |
|
||||
| 4107 - 4111 | DEBUG | used for debugging |
|
||||
|
||||
The HACK simulation needs a valid file `ROM.hack` (created in project `04_Machine_Language`) with the machine language instructions to perform.
|
||||
|
||||
The test bench of `04_HACK` will:
|
||||
|
||||
1. occasionally press the user buttons BUT1/2
|
||||
2. show the result of LED1/2
|
||||
3. show the content of DEBUG0-DEBUG5
|
||||
|
||||
***
|
||||
|
||||
### Project
|
||||
|
||||
- Implement the chips `CPU` , `Memory` and `Clock25__Reset20` and simulate with the corresponding test benches:
|
||||
|
||||
```
|
||||
$ cd 0X_<chipname>
|
||||
$ apio clean
|
||||
$ apio sim
|
||||
```
|
||||
|
||||
- Check the frequency of the internal clk signal to be 25MHz. So one clock cylce takes 40us.
|
||||
|
||||

|
||||
|
||||
- Check the reset signal of HACK. You should see a reset signal of approximately 20 us.
|
||||
|
||||

|
||||
* Implement `HACK` and test with `leds.asm`:
|
||||
|
||||
```
|
||||
$ cd ../04_Machine_Language
|
||||
$ make leds
|
||||
$ cd ../05_Computer_Architecture/04_HACK
|
||||
$ apio clean
|
||||
$ apio sim
|
||||
```
|
||||
|
||||
* Check, if LEDs change state accoring to BUT:
|
||||
|
||||

|
||||
|
||||
* Test `HACK` with `mult.asm`.
|
||||
|
||||
```
|
||||
$ cd ../04_Machine_Language
|
||||
$ make mult
|
||||
$ cd ../05_Computer_Architecture/04_HACK
|
||||
$ apio clean
|
||||
$ apio sim
|
||||
```
|
||||
|
||||
* You should see the result 715 of the multiplication 13*55 in the debug register `DEBUG2`! You can change the number format to decimal.
|
||||
|
||||

|
||||
|
||||
* finally upload the complete HACK design with `leds.asm` preloaded into instruction ROM and run in real hardware!
|
||||
|
||||
```
|
||||
$ cd ../04_Machine_Language/01_leds
|
||||
$ make
|
||||
$ cd ../05_Computer_Architecture/04_HACK
|
||||
$ apio clean
|
||||
$ apio build
|
||||
$ apio upload
|
||||
```
|
||||
|
||||
* press the user buttons BUT1/BUT2 and see if the LED change pattern accordingly.
|
||||
|
||||
* Repeat the test with the second machine language programm `mult.asm`.
|
||||
|
||||
**Attention:** remember to run `apio clean`, after changing the file `ROM.hack`!
|