flag handling
This commit is contained in:
parent
4c8a4a7ddf
commit
9277a1c3fd
|
@ -32,7 +32,7 @@ yayacemu [PATH_TO_YOUR_ROM]
|
||||||
### Todo
|
### Todo
|
||||||
- [x] Graphics
|
- [x] Graphics
|
||||||
- [x] Corax+ Required Instructions
|
- [x] Corax+ Required Instructions
|
||||||
- [ ] Proper Flag Handling
|
- [x] Proper Flag Handling
|
||||||
- [ ] Working Input
|
- [ ] Working Input
|
||||||
- [ ] More Instructions
|
- [ ] More Instructions
|
||||||
- [ ] Tetris Working Running
|
- [ ] Tetris Working Running
|
||||||
|
@ -46,3 +46,4 @@ yayacemu [PATH_TO_YOUR_ROM]
|
||||||
![Chip 8 Logo Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/chip8-logo.png?raw=true)
|
![Chip 8 Logo Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/chip8-logo.png?raw=true)
|
||||||
![IBM Logo Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/ibm-logo.png?raw=true)
|
![IBM Logo Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/ibm-logo.png?raw=true)
|
||||||
![CORAX+ Test Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/corax.png?raw=true)
|
![CORAX+ Test Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/corax.png?raw=true)
|
||||||
|
![Flag Test Demo](https://github.com/nickorlow/yayacemu/blob/main/screenshots/flags.png?raw=true)
|
||||||
|
|
BIN
screenshots/flags.png
Normal file
BIN
screenshots/flags.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
BIN
tests/4-flags.ch8
Normal file
BIN
tests/4-flags.ch8
Normal file
Binary file not shown.
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#define SCREEN_WIDTH 64
|
#define SCREEN_WIDTH 64
|
||||||
#define SCREEN_HEIGHT 32
|
#define SCREEN_HEIGHT 32
|
||||||
|
#define EMULATION_HZ 480
|
||||||
|
|
||||||
FILE *rom_file;
|
FILE *rom_file;
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
@ -89,10 +90,10 @@ int main(int argc, char** argv) {
|
||||||
contextp->commandArgs(argc, argv);
|
contextp->commandArgs(argc, argv);
|
||||||
Vyayacemu* top = new Vyayacemu{contextp};
|
Vyayacemu* top = new Vyayacemu{contextp};
|
||||||
//while (!contextp->gotFinish()) {
|
//while (!contextp->gotFinish()) {
|
||||||
for (int i = 0; i < 20000; i++) {
|
for (int i = 0; i < 2000; i++) {
|
||||||
top->clk_in ^= 1;
|
top->clk_in ^= 1;
|
||||||
top->eval();
|
top->eval();
|
||||||
usleep(500);
|
usleep(1000000/EMULATION_HZ);
|
||||||
}
|
}
|
||||||
printf("TB : Testbench has reached end of simulation. Pausing for 10 seconds before exiting");
|
printf("TB : Testbench has reached end of simulation. Pausing for 10 seconds before exiting");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
135
yayacemu.sv
135
yayacemu.sv
|
@ -8,16 +8,22 @@ module yayacemu (
|
||||||
wire [7:0] registers [0:15];
|
wire [7:0] registers [0:15];
|
||||||
logic [3:0] stack_pointer;
|
logic [3:0] stack_pointer;
|
||||||
wire [15:0] stack [0:15];
|
wire [15:0] stack [0:15];
|
||||||
|
logic [7:0] delay_timer;
|
||||||
|
logic [7:0] sound_timer;
|
||||||
|
int cycle_counter;
|
||||||
|
|
||||||
logic [15:0] index_reg;
|
logic [15:0] index_reg;
|
||||||
logic rom_ready;
|
logic rom_ready;
|
||||||
logic [15:0] program_counter;
|
logic [15:0] program_counter;
|
||||||
|
|
||||||
rom_loader rl (memory, rom_ready);
|
rom_loader rl (memory, rom_ready);
|
||||||
chip8_cpu cpu (memory, clk_in, vram, stack, index_reg, stack_pointer, registers, program_counter);
|
chip8_cpu cpu (memory, clk_in, vram, stack, index_reg, stack_pointer, registers, delay_timer, sound_timer, cycle_counter, program_counter);
|
||||||
chip8_gpu gpu (vram);
|
chip8_gpu gpu (vram);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
sound_timer = 0;
|
||||||
|
delay_timer = 0;
|
||||||
|
cycle_counter = 0;
|
||||||
program_counter = 'h200;
|
program_counter = 'h200;
|
||||||
stack_pointer = 4'b0000;
|
stack_pointer = 4'b0000;
|
||||||
init_screen();
|
init_screen();
|
||||||
|
@ -33,13 +39,20 @@ module chip8_cpu(
|
||||||
output wire [15:0] index_reg,
|
output wire [15:0] index_reg,
|
||||||
output wire [3:0] stack_pointer,
|
output wire [3:0] stack_pointer,
|
||||||
output wire [7:0] registers [0:15],
|
output wire [7:0] registers [0:15],
|
||||||
|
output logic [7:0] delay_timer,
|
||||||
|
output logic [7:0] sound_timer,
|
||||||
|
output int cycle_counter,
|
||||||
output wire [15:0] program_counter
|
output wire [15:0] program_counter
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [15:0] opcode;
|
logic [15:0] opcode;
|
||||||
|
|
||||||
logic [15:0] scratch;
|
logic [15:0] scratch;
|
||||||
logic [15:0] scratch2;
|
logic [15:0] scratch2;
|
||||||
|
|
||||||
|
logic [7:0] scratch_8;
|
||||||
|
logic [7:0] scratch_82;
|
||||||
|
|
||||||
logic [31:0] x_cord;
|
logic [31:0] x_cord;
|
||||||
logic [31:0] y_cord;
|
logic [31:0] y_cord;
|
||||||
logic [7:0] size;
|
logic [7:0] size;
|
||||||
|
@ -56,6 +69,14 @@ module chip8_cpu(
|
||||||
$display("HW : opcode is 0x%h (%b)", opcode, opcode);
|
$display("HW : opcode is 0x%h (%b)", opcode, opcode);
|
||||||
$display("HW : PC %0d 0x%h", program_counter, program_counter);
|
$display("HW : PC %0d 0x%h", program_counter, program_counter);
|
||||||
|
|
||||||
|
// 480Hz / 8 = 60 Hz
|
||||||
|
if (cycle_counter % 8 == 0) begin
|
||||||
|
if (delay_timer > 0)
|
||||||
|
delay_timer--;
|
||||||
|
if (sound_timer > 0)
|
||||||
|
sound_timer--;
|
||||||
|
end
|
||||||
|
|
||||||
casez(opcode)
|
casez(opcode)
|
||||||
'h00E0: begin
|
'h00E0: begin
|
||||||
$display("HW : INSTR CLS");
|
$display("HW : INSTR CLS");
|
||||||
|
@ -127,28 +148,57 @@ module chip8_cpu(
|
||||||
end
|
end
|
||||||
'h8??4: begin
|
'h8??4: begin
|
||||||
$display("HW : INSTR ADD Vx, Vy");
|
$display("HW : INSTR ADD Vx, Vy");
|
||||||
|
scratch_8 = registers[(opcode & 'h0F00) >> 8];
|
||||||
registers[(opcode & 'h0F00) >> 8] += registers[(opcode & 'h00F0) >> 4];
|
registers[(opcode & 'h0F00) >> 8] += registers[(opcode & 'h00F0) >> 4];
|
||||||
|
registers[15] = {7'b0000000, scratch_8 > registers[(opcode & 'h0F00) >> 8]};
|
||||||
end
|
end
|
||||||
'h8??5: begin
|
'h8??5: begin
|
||||||
$display("HW : INSTR SUB Vx, Vy");
|
$display("HW : INSTR SUB Vx, Vy");
|
||||||
|
scratch_8 = registers[(opcode & 'h0F00) >> 8];
|
||||||
registers[(opcode & 'h0F00) >> 8] -= registers[(opcode & 'h00F0) >> 4];
|
registers[(opcode & 'h0F00) >> 8] -= registers[(opcode & 'h00F0) >> 4];
|
||||||
|
registers[15] = {7'b0000000, scratch_8 >= registers[(opcode & 'h0F00) >> 8]};
|
||||||
end
|
end
|
||||||
'h8??6: begin
|
'h8??6: begin
|
||||||
$display("HW : INSTR SHR Vx {, Vy}");
|
$display("HW : INSTR SHR Vx {, Vy}");
|
||||||
|
scratch_8 = registers[(opcode & 'h0F00) >> 8];
|
||||||
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]>> 1;
|
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]>> 1;
|
||||||
|
registers[15] = {7'b0000000, ((scratch_8 & 8'h01) == 8'h01)};
|
||||||
end
|
end
|
||||||
'h8??7: begin
|
'h8??7: begin
|
||||||
$display("HW : INSTR SUBN Vx, Vy");
|
$display("HW : INSTR SUBN Vx, Vy");
|
||||||
|
scratch_8 = registers[(opcode & 'h00F0) >> 4];
|
||||||
|
scratch_82 = registers[(opcode & 'h0F00) >> 8];
|
||||||
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4] - registers[(opcode & 'h0F00) >> 8];
|
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4] - registers[(opcode & 'h0F00) >> 8];
|
||||||
|
registers[15] = {7'b0000000, (scratch_8 >= scratch_82)};
|
||||||
end
|
end
|
||||||
'h8??E: begin
|
'h8??E: begin
|
||||||
$display("HW : INSTR SHL Vx {, Vy}");
|
$display("HW : INSTR SHL Vx {, Vy}");
|
||||||
|
scratch_8 = registers[(opcode & 'h0F00) >> 8];
|
||||||
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]<< 1;
|
registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]<< 1;
|
||||||
|
|
||||||
|
registers[15] = {7'b0000000, (scratch_8[7]) };
|
||||||
|
end
|
||||||
|
'h9??0: begin
|
||||||
|
$display("HW : INSTR SNE Vx, Vy");
|
||||||
|
if (registers[(opcode & 'h00F0) >> 4] != registers[(opcode & 'h0F00) >> 8]) begin
|
||||||
|
program_counter += 2;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
'hA???: begin
|
'hA???: begin
|
||||||
$display("HW : INSTR LD I, addr");
|
$display("HW : INSTR LD I, addr");
|
||||||
index_reg = (opcode & 'h0FFF);
|
index_reg = (opcode & 'h0FFF);
|
||||||
end
|
end
|
||||||
|
'hb???: begin
|
||||||
|
$display("HW : INSTR JP V0, addr");
|
||||||
|
program_counter = {8'h00, registers[0]} + (opcode & 'h0FFF) - 2;
|
||||||
|
end
|
||||||
|
'hc???: begin
|
||||||
|
$display("HW : RND Vx, addr");
|
||||||
|
// TODO: use a real RNG module, this is not synthesizeable
|
||||||
|
scratch = {$urandom()%256}[15:0];
|
||||||
|
scratch2 = (opcode & 'h00FF);
|
||||||
|
registers[(opcode & 'h0F00) >> 8] = scratch[7:0] & scratch2[7:0];
|
||||||
|
end
|
||||||
'hD???: begin
|
'hD???: begin
|
||||||
$display("HW : INSTR DRW Vx, Vy, nibble");
|
$display("HW : INSTR DRW Vx, Vy, nibble");
|
||||||
x_cord = {24'h000000, registers[(opcode & 'h0F00) >> 8]};
|
x_cord = {24'h000000, registers[(opcode & 'h0F00) >> 8]};
|
||||||
|
@ -174,45 +224,58 @@ module chip8_cpu(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
'hF?33: begin
|
'hF?07: begin
|
||||||
$display("HW : INSTR LD B, Vx");
|
$display("HW : INSTR LD Vx, DT");
|
||||||
scratch = {8'h00, registers[(opcode & 'h0F00) >> 8]};
|
registers[(opcode & 'h0F00) >> 8] = delay_timer;
|
||||||
scratch2 = scratch % 10;
|
end
|
||||||
memory[index_reg + 2] = scratch2[7:0];
|
'hF?15: begin
|
||||||
scratch /= 10;
|
$display("HW : INSTR LD DT, Vx");
|
||||||
scratch2 = scratch % 10;
|
delay_timer = registers[(opcode & 'h0F00) >> 8];
|
||||||
memory[index_reg + 1] = scratch2[7:0];
|
end
|
||||||
scratch /= 10;
|
'hF?18: begin
|
||||||
scratch2 = scratch % 10;
|
$display("HW : INSTR LD ST, Vx");
|
||||||
memory[index_reg + 0] = scratch2[7:0];
|
sound_timer = registers[(opcode & 'h0F00) >> 8];
|
||||||
end
|
end
|
||||||
'hF?55: begin
|
'hF?1E: begin
|
||||||
$display("HW : INSTR LD [I], Vx");
|
$display("HW : INSTR ADD I, Vx");
|
||||||
scratch = (opcode & 'h0F00) >> 8;
|
index_reg = index_reg + {8'h00, registers[(opcode & 'h0F00) >> 8]};
|
||||||
for (i8 = 0; i8 <= scratch[7:0]; i8++) begin
|
end
|
||||||
scratch2 = index_reg + {8'h00, i8};
|
'hF?33: begin
|
||||||
memory[scratch2[11:0]] = registers[i8[3:0]];
|
$display("HW : INSTR LD B, Vx");
|
||||||
end
|
scratch = {8'h00, registers[(opcode & 'h0F00) >> 8]};
|
||||||
index_reg++;
|
scratch2 = scratch % 10;
|
||||||
end
|
memory[index_reg + 2] = scratch2[7:0];
|
||||||
'hF?65: begin
|
scratch /= 10;
|
||||||
$display("HW : INSTR LD Vx, [I]");
|
scratch2 = scratch % 10;
|
||||||
scratch = (opcode & 'h0F00) >> 8;
|
memory[index_reg + 1] = scratch2[7:0];
|
||||||
for (i8 = 0; i8 <= scratch[7:0]; i8++) begin
|
scratch /= 10;
|
||||||
scratch2 = index_reg + {8'h00, i8};
|
scratch2 = scratch % 10;
|
||||||
registers[i8[3:0]] = memory[scratch2[11:0]];
|
memory[index_reg + 0] = scratch2[7:0];
|
||||||
end
|
end
|
||||||
index_reg++;
|
'hF?55: begin
|
||||||
end
|
$display("HW : INSTR LD [I], Vx");
|
||||||
'hF?1E: begin
|
scratch = (opcode & 'h0F00) >> 8;
|
||||||
$display("HW : INSTR ADD I, Vx");
|
for (i8 = 0; i8 <= scratch[7:0]; i8++) begin
|
||||||
index_reg = index_reg + {8'h00, registers[(opcode & 'h0F00) >> 8]};
|
scratch2 = index_reg + {8'h00, i8};
|
||||||
end
|
memory[scratch2[11:0]] = registers[i8[3:0]];
|
||||||
|
end
|
||||||
|
index_reg++;
|
||||||
|
end
|
||||||
|
'hF?65: begin
|
||||||
|
$display("HW : INSTR LD Vx, [I]");
|
||||||
|
scratch = (opcode & 'h0F00) >> 8;
|
||||||
|
for (i8 = 0; i8 <= scratch[7:0]; i8++) begin
|
||||||
|
scratch2 = index_reg + {8'h00, i8};
|
||||||
|
registers[i8[3:0]] = memory[scratch2[11:0]];
|
||||||
|
end
|
||||||
|
index_reg++;
|
||||||
|
end
|
||||||
default: $display("HW : ILLEGAL INSTRUCTION");
|
default: $display("HW : ILLEGAL INSTRUCTION");
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
program_counter += 2;
|
program_counter += 2;
|
||||||
|
cycle_counter++;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue