Skip to content

Commit

Permalink
add gif and some instruction example and some arduino code
Browse files Browse the repository at this point in the history
  • Loading branch information
ejunjsh committed Dec 15, 2021
1 parent 5b5fcd3 commit 406b213
Show file tree
Hide file tree
Showing 6 changed files with 701 additions and 3 deletions.
68 changes: 65 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

八位cpu, 4个寄存器,16条指令

<img src="https://github.com/ejunjsh/mycpu/raw/main/images/15.gif" width="50%" height="50%">

## 准备

### 材料
Expand Down Expand Up @@ -122,13 +124,73 @@

<img src="https://github.com/ejunjsh/mycpu/raw/main/images/08.jpeg" width="50%" height="50%">

## 视频
## 看视频,开始搭建


### 英文

[https://eater.net/8bit](https://eater.net/8bit)

这里包括了所有相关资料和视频

### 中文

[https://www.bilibili.com/video/BV1BJ411R7s5](https://www.bilibili.com/video/BV1BJ411R7s5)

### 英文
中文配音,背景知识讲解

[https://eater.net/8bit](https://eater.net/8bit)
## 实例代码

下面指令程序都是可以跑在这个cpu上的

### 加法

````
0:LDA 14 0000:0001 1110
1:ADD 15 0001:0010 1111
2:OUT 0010:1110 0000
3:HLT 0011:1111 0000
14:1 1110:0000 0001
15:1 1111:0000 0001
````

上面代码相当于地址14里面的值和15里面的值相加, 然后显示2

### 累加

````
0:LDI 1 0000:0101 0001
1:STA 15 0001:0100 1111
2:LDI 0 0010:0101 0000
3:ADD 15 0011:0010 1111
4:OUT 0100:1110 0000
5:JMP 3 0101:0110 0011
````

上面代码相当于`i++`

### 乘法

````
0:LDA 14 0000:0001 1110
1:SUB 12 0001:0011 1100
2:JC 6 0010:0111 0110
3:LDA 13 0011:0001 1101
4:OUT 0100:1110 0000
5:HLT 0101:1111 0000
6:STA 14 0110:0100 1110
7:LDA 13 0111:0001 1101
8:ADD 15 1000:0010 1111
9:STA 13 1001:0100 1101
10:JMP 0 1010:0110 0000
11:
12:1 1100:0000 0001
13:product 1101:0000 0000
14:x 1110:0000 0010
15:y 1111:0000 0101
````

这里相当于`x = 2 ; y = 5 ; product = x * y`, 并显示`product`,上面动图显示的就是这个例子


EOF
133 changes: 133 additions & 0 deletions eeprom-programmer/eeprom-programmer.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* 用arduino nano 擦写 EEPROM的程序,该程序用来显示7位共阳极数码管
* 您可以访问:benblu.taobao.com获得所有的套件。
*/

#define SHIFT_DATA 2
#define SHIFT_CLK 3
#define SHIFT_LATCH 4
#define EEPROM_D0 5
#define EEPROM_D7 12
#define WRITE_EN 13

/*
* 使用移位寄存器将地址数据输出
*/
void setAddress(int address, bool outputEnable) {
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, (address >> 8) | (outputEnable ? 0x00 : 0x80));
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, address);

digitalWrite(SHIFT_LATCH, LOW);
digitalWrite(SHIFT_LATCH, HIGH);
digitalWrite(SHIFT_LATCH, LOW);
}


/*
* 从指定地址的EEPROM读取一个字节
*/
byte readEEPROM(int address) {
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) {
pinMode(pin, INPUT);
}
setAddress(address, /*outputEnable*/ true);

byte data = 0;
for (int pin = EEPROM_D7; pin >= EEPROM_D0; pin--) {
data = (data << 1) + digitalRead(pin);
}
return data;
}


/*
* 将字节写入指定地址的EEPROM。
*/
void writeEEPROM(int address, byte data) {
setAddress(address, /*outputEnable*/ false);
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) {
pinMode(pin, OUTPUT);
}

for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) {
digitalWrite(pin, data & 1);
data = data >> 1;
}
digitalWrite(WRITE_EN, LOW);
delayMicroseconds(1);
digitalWrite(WRITE_EN, HIGH);
delay(10);
}


/*
* 读取EEPROM的内容并将其打印到串行监视器。
*/
void printContents() {
for (int base = 0; base <= 255; base += 16) {
byte data[16];
for (int offset = 0; offset <= 15; offset++) {
data[offset] = readEEPROM(base + offset);
}

char buf[80];
sprintf(buf, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
base, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);

Serial.println(buf);
}
}


// 用于共阳极7段显示的4位十六进制解码器
//byte data[] = { 0x81, 0xcf, 0x92, 0x86, 0xcc, 0xa4, 0xa0, 0x8f, 0x80, 0x84, 0x88, 0xe0, 0xb1, 0xc2, 0xb0, 0xb8 };

// 用于共阴极7段显示的4位十六进制解码器
byte data[] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47 };


void setup() {
// put your setup code here, to run once:
pinMode(SHIFT_DATA, OUTPUT);
pinMode(SHIFT_CLK, OUTPUT);
pinMode(SHIFT_LATCH, OUTPUT);
digitalWrite(WRITE_EN, HIGH);
pinMode(WRITE_EN, OUTPUT);
Serial.begin(57600);

// Erase entire EEPROM
Serial.print("擦除 EEPROM");
for (int address = 0; address <= 2047; address ++) {
writeEEPROM(address, 0xff);
if (address % 64 == 0) {
Serial.print(".");
}
}
Serial.println(" done");


// 写入数据
Serial.print("编辑 EEPROM");

for (int address = 0; address < sizeof(data); address ++ ) {
writeEEPROM(address, data[address]);

if (address % 64 == 0) {
writeEEPROM(address, data[address]);
Serial.print(".");
}
}
Serial.println(" 完成");


// 读EEPROM中的值
Serial.println("读.... EEPROM");
printContents();
}


void loop() {
// put your main code here, to run repeatedly:

}
Binary file added images/15.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
163 changes: 163 additions & 0 deletions microcode-eeprom-programmer/microcode-eeprom-programmer.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/**
* 该程序用于写入CPU的控制信号。
* 所有的套件可在benblue.tapbao.com 中获得
*/
#define SHIFT_DATA 2
#define SHIFT_CLK 3
#define SHIFT_LATCH 4
#define EEPROM_D0 5
#define EEPROM_D7 12
#define WRITE_EN 13

#define HLT 0b1000000000000000 // Halt clock HLT信号
#define MI 0b0100000000000000 // Memory address register in 内存地址输入
#define RI 0b0010000000000000 // RAM data in 内存数据输入
#define RO 0b0001000000000000 // RAM data out 内存数据输出
#define IO 0b0000100000000000 // Instruction register out 指令寄存器输出
#define II 0b0000010000000000 // Instruction register in 指令寄存器输入
#define AI 0b0000001000000000 // A register in A寄存器输入
#define AO 0b0000000100000000 // A register out A寄存器输出
#define EO 0b0000000010000000 // ALU out ALU输出
#define SU 0b0000000001000000 // ALU subtract 减法
#define BI 0b0000000000100000 // B register in B寄存器输入
#define OI 0b0000000000010000 // Output register in 输出寄存器输入
#define CE 0b0000000000001000 // Program counter enable 程序计数允许
#define CO 0b0000000000000100 // Program counter out 程序计数器输出
#define J 0b0000000000000010 // Jump (program counter in) 程序计数器输入(JUMP)

uint16_t data[] = {
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 0000 - NOP
MI|CO, RO|II|CE, IO|MI, RO|AI, 0, 0, 0, 0, // 0001 - LDA
MI|CO, RO|II|CE, IO|MI, RO|BI, EO|AI, 0, 0, 0, // 0010 - ADD
MI|CO, RO|II|CE, IO|MI, RO|BI, EO|AI|SU, 0, 0, 0, // 0011 - SUB
MI|CO, RO|II|CE, IO|MI, AO|RI, 0, 0, 0, 0, // 0100 - STA
MI|CO, RO|II|CE, IO|AI, 0, 0, 0, 0, 0, // 0101 - LDI
MI|CO, RO|II|CE, IO|J, 0, 0, 0, 0, 0, // 0110 - JMP
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 0111
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1000
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1001
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1010
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1011
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1100
MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0, // 1101
MI|CO, RO|II|CE, AO|OI, 0, 0, 0, 0, 0, // 1110 - OUT
MI|CO, RO|II|CE, HLT, 0, 0, 0, 0, 0, // 1111 - HLT
};


/*
*使用移位寄存器输出地址位和outputEnable信号。
*/
void setAddress(int address, bool outputEnable) {
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, (address >> 8) | (outputEnable ? 0x00 : 0x80));
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, address);

digitalWrite(SHIFT_LATCH, LOW);
digitalWrite(SHIFT_LATCH, HIGH);
digitalWrite(SHIFT_LATCH, LOW);

}


/*
* 从指定地址的EEPROM读取一个字节。
*/
byte readEEPROM(int address) {
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin += 1) {
pinMode(pin, INPUT);
}
setAddress(address, /*outputEnable*/ true);

byte data = 0;
for (int pin = EEPROM_D7; pin >= EEPROM_D0; pin -= 1) {
data = (data << 1) + digitalRead(pin);
}
return data;
}


/*
* 将字节写入指定地址的EEPROM。
*/
void writeEEPROM(int address, byte data) {
setAddress(address, /*outputEnable*/ false);
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin += 1) {
pinMode(pin, OUTPUT);
}

for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin += 1) {
digitalWrite(pin, data & 1);
data = data >> 1;
}
digitalWrite(WRITE_EN, LOW);
delayMicroseconds(1);
digitalWrite(WRITE_EN, HIGH);
delay(10);
}


/*
* 读取EEPROM的内容并将其打印到串行监视器。
*/
void printContents() {
for (int base = 0; base <= 255; base += 16) {
byte data[16];
for (int offset = 0; offset <= 15; offset += 1) {
data[offset] = readEEPROM(base + offset);
}

char buf[80];
sprintf(buf, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
base, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);

Serial.println(buf);
}
}


void setup() {
// put your setup code here, to run once:
pinMode(SHIFT_DATA, OUTPUT);
pinMode(SHIFT_CLK, OUTPUT);
pinMode(SHIFT_LATCH, OUTPUT);
digitalWrite(WRITE_EN, HIGH);
pinMode(WRITE_EN, OUTPUT);
Serial.begin(57600);

// 写数据
Serial.print("写 EEPROM");
writeEEPROM(0, 0);
// 将微码的8个高位写到EEPROM的前128个字节中
for (int address = 0; address < sizeof(data)/sizeof(data[0]); address += 1) {
writeEEPROM(address, data[address] >> 8);

if (address % 64 == 0) {
writeEEPROM(address, data[address] >> 8);
Serial.print(".");
}
}

// 将微码的8个低位写到EEPROM的前128个字节中
for (int address = 0; address < sizeof(data)/sizeof(data[0]); address += 1) {
writeEEPROM(address + 128, data[address]);

if (address % 64 == 0) {
writeEEPROM(address + 128, data[address]);
Serial.print(".");
}
}

Serial.println(" done");


// 读并打印出EERPROM的内容
Serial.println("读 EEPROM");
printContents();
}


void loop() {
// put your main code here, to run repeatedly:

}
Loading

0 comments on commit 406b213

Please sign in to comment.