From f715709942341c13e31f9243177241cb96f74e6f Mon Sep 17 00:00:00 2001 From: Nicholas Orlowsky Date: Wed, 31 Jan 2024 21:04:52 -0600 Subject: [PATCH] run formatter --- beeper.sv | 10 +- chip8.sv | 166 +++++++++++---- cpu.sv | 552 +++++++++++++++++++++++++------------------------- gpu.sv | 20 +- keyboard.sv | 18 +- makefile | 6 + rng.sv | 22 +- rom_loader.sv | 27 +-- yayacemu.cpp | 198 +++++++++--------- 9 files changed, 550 insertions(+), 469 deletions(-) diff --git a/beeper.sv b/beeper.sv index e88680f..ddb82e2 100644 --- a/beeper.sv +++ b/beeper.sv @@ -1,10 +1,10 @@ module beeper ( input wire [7:0] sound_timer - ); +); - import "DPI-C" function void set_beep(bit beep); + import "DPI-C" function void set_beep(bit beep); - always_comb begin - set_beep(sound_timer > 0); - end + always_comb begin + set_beep(sound_timer > 0); + end endmodule diff --git a/chip8.sv b/chip8.sv index e0bcc98..d0017ab 100644 --- a/chip8.sv +++ b/chip8.sv @@ -1,54 +1,136 @@ module chip8 ( input wire clk_in - ); +); - bit [31:0] vram [0:2047]; - bit [7:0] memory [0:4095]; + bit [31:0] vram[0:2047]; + bit [7:0] memory[0:4095]; - bit keyboard [15:0]; + bit keyboard[15:0]; - bit [7:0] sound_timer; - bit [15:0] program_counter; - int cycle_counter; + bit [7:0] sound_timer; + bit [15:0] program_counter; + int cycle_counter; - bit [7:0] random_number; + bit [7:0] random_number; - beeper beeper (sound_timer); - cpu cpu (memory, clk_in, keyboard, random_number, cycle_counter, program_counter, vram, sound_timer); - gpu gpu (vram); - keyboard kb (clk_in, keyboard); - rng randy (clk_in, program_counter, keyboard, cycle_counter, random_number); - rom_loader loader (memory); + beeper beeper (sound_timer); + cpu cpu ( + memory, + clk_in, + keyboard, + random_number, + cycle_counter, + program_counter, + vram, + sound_timer + ); + gpu gpu (vram); + keyboard kb ( + clk_in, + keyboard + ); + rng randy ( + clk_in, + program_counter, + keyboard, + cycle_counter, + random_number + ); + rom_loader loader (memory); - initial begin - bit [7:0] fontset [79:0] = { - 8'hF0, 8'h90, 8'h90, 8'h90, 8'hF0, // 0 - 8'h20, 8'h60, 8'h20, 8'h20, 8'h70, // 1 - 8'hF0, 8'h10, 8'hF0, 8'h80, 8'hF0, // 2 - 8'hF0, 8'h10, 8'hF0, 8'h10, 8'hF0, // 3 - 8'h90, 8'h90, 8'hF0, 8'h10, 8'h10, // 4 - 8'hF0, 8'h80, 8'hF0, 8'h10, 8'hF0, // 5 - 8'hF0, 8'h80, 8'hF0, 8'h90, 8'hF0, // 6 - 8'hF0, 8'h10, 8'h20, 8'h40, 8'h40, // 7 - 8'hF0, 8'h90, 8'hF0, 8'h90, 8'hF0, // 8 - 8'hF0, 8'h90, 8'hF0, 8'h10, 8'hF0, // 9 - 8'hF0, 8'h90, 8'hF0, 8'h90, 8'h90, // A - 8'hE0, 8'h90, 8'hE0, 8'h90, 8'hE0, // B - 8'hF0, 8'h80, 8'h80, 8'h80, 8'hF0, // C - 8'hE0, 8'h90, 8'h90, 8'h90, 8'hE0, // D - 8'hF0, 8'h80, 8'hF0, 8'h80, 8'hF0, // E - 8'hF0, 8'h80, 8'hF0, 8'h80, 8'h80 // F - }; + initial begin + bit [7:0] fontset[79:0] = { + 8'hF0, + 8'h90, + 8'h90, + 8'h90, + 8'hF0, // 0 + 8'h20, + 8'h60, + 8'h20, + 8'h20, + 8'h70, // 1 + 8'hF0, + 8'h10, + 8'hF0, + 8'h80, + 8'hF0, // 2 + 8'hF0, + 8'h10, + 8'hF0, + 8'h10, + 8'hF0, // 3 + 8'h90, + 8'h90, + 8'hF0, + 8'h10, + 8'h10, // 4 + 8'hF0, + 8'h80, + 8'hF0, + 8'h10, + 8'hF0, // 5 + 8'hF0, + 8'h80, + 8'hF0, + 8'h90, + 8'hF0, // 6 + 8'hF0, + 8'h10, + 8'h20, + 8'h40, + 8'h40, // 7 + 8'hF0, + 8'h90, + 8'hF0, + 8'h90, + 8'hF0, // 8 + 8'hF0, + 8'h90, + 8'hF0, + 8'h10, + 8'hF0, // 9 + 8'hF0, + 8'h90, + 8'hF0, + 8'h90, + 8'h90, // A + 8'hE0, + 8'h90, + 8'hE0, + 8'h90, + 8'hE0, // B + 8'hF0, + 8'h80, + 8'h80, + 8'h80, + 8'hF0, // C + 8'hE0, + 8'h90, + 8'h90, + 8'h90, + 8'hE0, // D + 8'hF0, + 8'h80, + 8'hF0, + 8'h80, + 8'hF0, // E + 8'hF0, + 8'h80, + 8'hF0, + 8'h80, + 8'h80 // F + }; - // Load fontset into memory - for(int i = 0; i < 80; i++) begin - memory[i] = fontset[79-i]; - end - - // Initialize keyboard bits - for(int i = 0; i < 15; i++) begin - keyboard[i] = 0; - end + // Load fontset into memory + for (int i = 0; i < 80; i++) begin + memory[i] = fontset[79-i]; end + + // Initialize keyboard bits + for (int i = 0; i < 15; i++) begin + keyboard[i] = 0; + end + end endmodule diff --git a/cpu.sv b/cpu.sv index 6a24591..ae6db50 100644 --- a/cpu.sv +++ b/cpu.sv @@ -1,301 +1,299 @@ -module cpu( - output bit [7:0] memory [0:4095], - input wire clk_in, - input wire keyboard [15:0], - input wire [7:0] random_number, +module cpu ( + output bit [7:0] memory[0:4095], + input wire clk_in, + input wire keyboard[15:0], + input wire [7:0] random_number, output int cycle_counter, output wire [15:0] program_counter, - output wire [31:0] vram [0:2047], + output wire [31:0] vram[0:2047], output wire [7:0] sound_timer - ); +); - bit halt; - int watch_key; + bit halt; + int watch_key; - logic [15:0] stack [0:15]; - logic [15:0] index_reg; - logic [3:0] stack_pointer; - logic [7:0] registers [0:15]; - logic [15:0] opcode; - logic [7:0] delay_timer; + logic [15:0] stack[0:15]; + logic [15:0] index_reg; + logic [3:0] stack_pointer; + logic [7:0] registers[0:15]; + logic [15:0] opcode; + logic [7:0] delay_timer; - logic [15:0] scratch; - logic [15:0] scratch2; + logic [15:0] scratch; + logic [15:0] scratch2; - logic [7:0] scratch_8; - logic [7:0] scratch_82; + logic [7:0] scratch_8; + logic [7:0] scratch_82; - logic [31:0] x_cord; - logic [31:0] y_cord; - logic [7:0] size; - logic [31:0] screen_pixel; - logic [7:0] sprite_pixel; + logic [31:0] x_cord; + logic [31:0] y_cord; + logic [7:0] size; + logic [31:0] screen_pixel; + logic [7:0] sprite_pixel; - // Initialize CPU - initial begin - halt = 0; - watch_key = 255; - sound_timer = 0; - delay_timer = 0; - cycle_counter = 0; - program_counter = 'h200; - stack_pointer = 4'b0000; + // Initialize CPU + initial begin + halt = 0; + watch_key = 255; + sound_timer = 0; + delay_timer = 0; + cycle_counter = 0; + program_counter = 'h200; + stack_pointer = 4'b0000; + end + + always_ff @(posedge clk_in) begin + opcode = {memory[program_counter+0], memory[program_counter+1]}; + $display("HW : opcode is 0x%h (%b)", opcode, opcode); + $display("HW : PC %0d 0x%h", program_counter, program_counter); + + if (cycle_counter % 20 == 0) begin + if (delay_timer > 0) delay_timer--; + if (sound_timer > 0) sound_timer--; end - always_ff @(posedge clk_in) begin - opcode = {memory[program_counter+0], memory[program_counter+1]}; - $display("HW : opcode is 0x%h (%b)", opcode, opcode); - $display("HW : PC %0d 0x%h", program_counter, program_counter); - - if (cycle_counter % 20 == 0) begin - if (delay_timer > 0) - delay_timer--; - if (sound_timer > 0) - sound_timer--; + casez (opcode) + 'h00E0: begin + $display("HW : INSTR CLS"); + for (int i = 0; i < 2048; i++) begin + vram[i] = 0; end + end + 'h00EE: begin + $display("HW : INSTR RET"); + stack_pointer--; + program_counter = stack[stack_pointer]; + end + 'h0???: $display("HW : INSTR SYS addr (Treating as NOP)"); + 'h1???: begin + $display("HW : INSTR JP addr"); + program_counter = (opcode & 'h0FFF) - 2; + end + 'h2???: begin + $display("HW : INSTR CALL addr"); + stack[stack_pointer] = program_counter; + stack_pointer++; + program_counter = (opcode & 'h0FFF) - 2; + end + 'h3???: begin + $display("HW : INSTR SE Vx, byte"); + scratch = (opcode & 'h00FF); + if (scratch[7:0] == registers[(opcode&'h0F00)>>8]) begin + program_counter += 2; + end + end + 'h4???: begin + $display("HW : INSTR SNE Vx, byte"); + scratch = (opcode & 'h00FF); + if (scratch[7:0] != registers[(opcode&'h0F00)>>8]) begin + program_counter += 2; + end + end + 'h5??0: begin + $display("HW : INSTR SE Vx, Vy"); + if (registers[(opcode&'h00F0)>>4] == registers[(opcode&'h0F00)>>8]) begin + program_counter += 2; + end + end + 'h6???: begin + $display("HW : INSTR LD Vx, byte"); + scratch = (opcode & 'h00FF); + registers[(opcode&'h0F00)>>8] = scratch[7:0]; + end + 'h7???: begin + $display("HW : INSTR ADD Vx, byte"); + scratch = (opcode & 'h00FF); + registers[(opcode&'h0F00)>>8] += scratch[7:0]; + end + 'h8??0: begin + $display("HW : INSTR LD Vx, Vy"); + registers[(opcode&'h0F00)>>8] = registers[(opcode&'h00F0)>>4]; + end + 'h8??1: begin + $display("HW : INSTR OR Vx, Vy"); + registers[(opcode&'h0F00)>>8] |= registers[(opcode&'h00F0)>>4]; + registers[15] = 0; + end + 'h8??2: begin + $display("HW : INSTR AND Vx, Vy"); + registers[(opcode&'h0F00)>>8] &= registers[(opcode&'h00F0)>>4]; + registers[15] = 0; + end + 'h8??3: begin + $display("HW : INSTR XOR Vx, Vy"); + registers[(opcode&'h0F00)>>8] ^= registers[(opcode&'h00F0)>>4]; + registers[15] = 0; + end + 'h8??4: begin + $display("HW : INSTR ADD Vx, Vy"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + registers[(opcode&'h0F00)>>8] += registers[(opcode&'h00F0)>>4]; + registers[15] = {7'b0000000, scratch_8 > registers[(opcode&'h0F00)>>8]}; + end + 'h8??5: begin + $display("HW : INSTR SUB Vx, Vy"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + registers[(opcode&'h0F00)>>8] -= registers[(opcode&'h00F0)>>4]; + registers[15] = {7'b0000000, scratch_8 >= registers[(opcode&'h0F00)>>8]}; + end + 'h8??6: begin + $display("HW : INSTR SHR Vx {, Vy}"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + registers[(opcode&'h0F00)>>8] = registers[(opcode&'h00F0)>>4] >> 1; + registers[15] = {7'b0000000, ((scratch_8 & 8'h01) == 8'h01)}; + end + 'h8??7: begin + $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[15] = {7'b0000000, (scratch_8 >= scratch_82)}; + end + 'h8??E: begin + $display("HW : INSTR SHL Vx {, Vy}"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + registers[(opcode&'h0F00)>>8] = registers[(opcode&'h00F0)>>4] << 1; - casez(opcode) - 'h00E0: begin - $display("HW : INSTR CLS"); - for(int i = 0; i < 2048; i++) begin - vram[i] = 0; - end - end - 'h00EE: begin - $display("HW : INSTR RET"); - stack_pointer--; - program_counter = stack[stack_pointer]; - end - 'h0???: $display("HW : INSTR SYS addr (Treating as NOP)"); - 'h1???: begin - $display("HW : INSTR JP addr"); - program_counter = (opcode & 'h0FFF) - 2; - end - 'h2???: begin - $display("HW : INSTR CALL addr"); - stack[stack_pointer] = program_counter; - stack_pointer++; - program_counter = (opcode & 'h0FFF) - 2; - end - 'h3???: begin - $display("HW : INSTR SE Vx, byte"); - scratch = (opcode & 'h00FF); - if (scratch[7:0] == registers[(opcode & 'h0F00) >> 8]) begin - program_counter += 2; - end - end - 'h4???: begin - $display("HW : INSTR SNE Vx, byte"); - scratch = (opcode & 'h00FF); - if (scratch[7:0] != registers[(opcode & 'h0F00) >> 8]) begin - program_counter += 2; - end - end - 'h5??0: begin - $display("HW : INSTR SE Vx, Vy"); - if (registers[(opcode & 'h00F0) >> 4] == registers[(opcode & 'h0F00) >> 8]) begin - program_counter += 2; - end - end - 'h6???: begin - $display("HW : INSTR LD Vx, byte"); - scratch = (opcode & 'h00FF); - registers[(opcode & 'h0F00) >> 8] = scratch[7:0]; - end - 'h7???: begin - $display("HW : INSTR ADD Vx, byte"); - scratch = (opcode & 'h00FF); - registers[(opcode & 'h0F00) >> 8] += scratch[7:0]; - end - 'h8??0: begin - $display("HW : INSTR LD Vx, Vy"); - registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]; - end - 'h8??1: begin - $display("HW : INSTR OR Vx, Vy"); - registers[(opcode & 'h0F00) >> 8] |= registers[(opcode & 'h00F0) >> 4]; - registers[15] = 0; - end - 'h8??2: begin - $display("HW : INSTR AND Vx, Vy"); - registers[(opcode & 'h0F00) >> 8] &= registers[(opcode & 'h00F0) >> 4]; - registers[15] = 0; - end - 'h8??3: begin - $display("HW : INSTR XOR Vx, Vy"); - registers[(opcode & 'h0F00) >> 8] ^= registers[(opcode & 'h00F0) >> 4]; - registers[15] = 0; - end - 'h8??4: begin - $display("HW : INSTR ADD Vx, Vy"); - scratch_8 = registers[(opcode & 'h0F00) >> 8]; - registers[(opcode & 'h0F00) >> 8] += registers[(opcode & 'h00F0) >> 4]; - registers[15] = {7'b0000000, scratch_8 > registers[(opcode & 'h0F00) >> 8]}; - end - 'h8??5: begin - $display("HW : INSTR SUB Vx, Vy"); - scratch_8 = registers[(opcode & 'h0F00) >> 8]; - registers[(opcode & 'h0F00) >> 8] -= registers[(opcode & 'h00F0) >> 4]; - registers[15] = {7'b0000000, scratch_8 >= registers[(opcode & 'h0F00) >> 8]}; - end - 'h8??6: begin - $display("HW : INSTR SHR Vx {, Vy}"); - scratch_8 = registers[(opcode & 'h0F00) >> 8]; - registers[(opcode & 'h0F00) >> 8] = registers[(opcode & 'h00F0) >> 4]>> 1; - registers[15] = {7'b0000000, ((scratch_8 & 8'h01) == 8'h01)}; - end - 'h8??7: begin - $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[15] = {7'b0000000, (scratch_8 >= scratch_82)}; - end - 'h8??E: begin - $display("HW : INSTR SHL Vx {, Vy}"); - scratch_8 = registers[(opcode & 'h0F00) >> 8]; - 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 + 'hA???: begin + $display("HW : INSTR LD I, addr"); + index_reg = (opcode & 'h0FFF); + 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 = {8'h00, random_number} % 16'h0100; + scratch2 = (opcode & 'h00FF); + registers[(opcode&'h0F00)>>8] = scratch[7:0] & scratch2[7:0]; + end + 'hD???: begin + $display("HW : INSTR DRW Vx, Vy, nibble"); + if (cycle_counter % 20 != 0) begin + halt = 1; + end else begin + halt = 0; + x_cord = {24'h000000, registers[(opcode&'h0F00)>>8]}; + y_cord = {24'h000000, registers[(opcode&'h00F0)>>4]}; - 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 - 'hA???: begin - $display("HW : INSTR LD I, addr"); - index_reg = (opcode & 'h0FFF); - 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 = {8'h00, random_number} % 16'h0100; - scratch2 = (opcode & 'h00FF); - registers[(opcode & 'h0F00) >> 8] = scratch[7:0] & scratch2[7:0]; - end - 'hD???: begin - $display("HW : INSTR DRW Vx, Vy, nibble"); - if (cycle_counter % 20 != 0) begin - halt = 1; - end else begin - halt = 0; - x_cord = {24'h000000, registers[(opcode & 'h0F00) >> 8]}; - y_cord = {24'h000000, registers[(opcode & 'h00F0) >> 4]}; + x_cord %= 64; + y_cord %= 32; - x_cord %= 64; - y_cord %= 32; + scratch = (opcode & 'h000F); + size = scratch[7:0]; + registers[15] = 0; - scratch = (opcode & 'h000F); - size = scratch[7:0]; - registers[15] = 0; + for (int r = 0; r < size; r++) begin + for (int c = 0; c < 8; c++) begin + if (r + y_cord >= 32 || x_cord + c >= 64) continue; + screen_pixel = vram[((r+y_cord)*64)+(x_cord+c)]; + sprite_pixel = memory[{16'h0000, index_reg}+r] & ('h80 >> c); - for (int r = 0; r < size; r++) begin - for (int c = 0; c < 8; c++) begin - if (r + y_cord >= 32 || x_cord + c >= 64) - continue; - screen_pixel = vram[((r + y_cord) * 64) + (x_cord + c)]; - sprite_pixel = memory[{16'h0000, index_reg} + r] & ('h80 >> c); - - if (|sprite_pixel) begin - if (screen_pixel == 32'hFFFFFFFF) begin - registers[15] = 1; - end - vram[((r + y_cord) * 64) + (x_cord + c)] ^= 32'hFFFFFFFF; - end - end - end + if (|sprite_pixel) begin + if (screen_pixel == 32'hFFFFFFFF) begin + registers[15] = 1; end + vram[((r+y_cord)*64)+(x_cord+c)] ^= 32'hFFFFFFFF; + end end - 'hE?9E: begin - $display("HW : INSTR SKP Vx"); - if (keyboard[{registers[(opcode & 'h0F00) >> 8]}[3:0]] == 1) begin - program_counter += 2; - end + end + end + end + 'hE?9E: begin + $display("HW : INSTR SKP Vx"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + if (keyboard[scratch_8[3:0]] == 1) begin + program_counter += 2; + end + end + 'hE?A1: begin + $display("HW : INSTR SNE Vx"); + scratch_8 = registers[(opcode&'h0F00)>>8]; + if (keyboard[scratch_8[3:0]] != 1) begin + program_counter += 2; + end + end + 'hF?07: begin + $display("HW : INSTR LD Vx, DT"); + registers[(opcode&'h0F00)>>8] = delay_timer; + end + 'hF?0A: begin + $display("HW : INSTR LD Vx, K"); + halt = 1; + for (int i = 0; i < 16; i++) begin + if (watch_key == 255) begin + if (keyboard[i]) begin + watch_key = i; end - 'hE?A1: begin - $display("HW : INSTR SNE Vx"); - if (keyboard[{registers[(opcode & 'h0F00) >> 8]}[3:0]] != 1) begin - program_counter += 2; - end + end else begin + if (!keyboard[watch_key]) begin + halt = 0; + watch_key = 255; end - 'hF?07: begin - $display("HW : INSTR LD Vx, DT"); - registers[(opcode & 'h0F00) >> 8] = delay_timer; - end - 'hF?0A: begin - $display("HW : INSTR LD Vx, K"); - halt = 1; - for(int i = 0; i < 16; i++) begin - if (watch_key == 255) begin - if (keyboard[i]) begin - watch_key = i; - end - end else begin - if (!keyboard[watch_key]) begin - halt = 0; - watch_key = 255; - end - end - end - end - 'hF?15: begin - $display("HW : INSTR LD DT, Vx"); - delay_timer = registers[(opcode & 'h0F00) >> 8]; - end - 'hF?18: begin - $display("HW : INSTR LD ST, Vx"); - sound_timer = registers[(opcode & 'h0F00) >> 8]; - end - 'hF?1E: begin - $display("HW : INSTR ADD I, Vx"); - index_reg = index_reg + {8'h00, registers[(opcode & 'h0F00) >> 8]}; - end - 'hF?29: begin - $display("HW : INSTR LDL F, Vx"); - index_reg = registers[(opcode & 'h0F00) >> 8] * 5; - end - 'hF?33: begin - $display("HW : INSTR LD B, Vx"); - scratch = {8'h00, registers[(opcode & 'h0F00) >> 8]}; - scratch2 = scratch % 10; - memory[index_reg + 2] = scratch2[7:0]; - scratch /= 10; - scratch2 = scratch % 10; - memory[index_reg + 1] = scratch2[7:0]; - scratch /= 10; - scratch2 = scratch % 10; - memory[index_reg + 0] = scratch2[7:0]; - end - 'hF?55: begin - $display("HW : INSTR LD [I], Vx"); - scratch = (opcode & 'h0F00) >> 8; - for (bit [7:0] i8 = 0; i8 <= scratch[7:0]; i8++) begin - scratch2 = index_reg + {8'h00, i8}; - 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 (bit [7:0] 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"); - endcase + end + end + end + 'hF?15: begin + $display("HW : INSTR LD DT, Vx"); + delay_timer = registers[(opcode&'h0F00)>>8]; + end + 'hF?18: begin + $display("HW : INSTR LD ST, Vx"); + sound_timer = registers[(opcode&'h0F00)>>8]; + end + 'hF?1E: begin + $display("HW : INSTR ADD I, Vx"); + index_reg = index_reg + {8'h00, registers[(opcode&'h0F00)>>8]}; + end + 'hF?29: begin + $display("HW : INSTR LDL F, Vx"); + index_reg = registers[(opcode&'h0F00)>>8] * 5; + end + 'hF?33: begin + $display("HW : INSTR LD B, Vx"); + scratch = {8'h00, registers[(opcode&'h0F00)>>8]}; + scratch2 = scratch % 10; + memory[index_reg+2] = scratch2[7:0]; + scratch /= 10; + scratch2 = scratch % 10; + memory[index_reg+1] = scratch2[7:0]; + scratch /= 10; + scratch2 = scratch % 10; + memory[index_reg+0] = scratch2[7:0]; + end + 'hF?55: begin + $display("HW : INSTR LD [I], Vx"); + scratch = (opcode & 'h0F00) >> 8; + for (bit [7:0] i8 = 0; i8 <= scratch[7:0]; i8++) begin + scratch2 = index_reg + {8'h00, i8}; + 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 (bit [7:0] 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"); + endcase - if (!halt) - program_counter += 2; + if (!halt) program_counter += 2; - cycle_counter++; - end + cycle_counter++; + end endmodule diff --git a/gpu.sv b/gpu.sv index 045b3e2..4ebbd8f 100644 --- a/gpu.sv +++ b/gpu.sv @@ -1,15 +1,15 @@ module gpu ( - input wire [31:0] vram [0:2047] - ); + input wire [31:0] vram[0:2047] +); - import "DPI-C" function void init_screen(); - import "DPI-C" function void draw_screen(logic [31:0] vram [0:2047]); + import "DPI-C" function void init_screen(); + import "DPI-C" function void draw_screen(logic [31:0] vram[0:2047]); - initial begin - init_screen(); - end + initial begin + init_screen(); + end - always_comb begin - draw_screen(vram); - end + always_comb begin + draw_screen(vram); + end endmodule diff --git a/keyboard.sv b/keyboard.sv index 4d80cea..0131148 100644 --- a/keyboard.sv +++ b/keyboard.sv @@ -1,15 +1,15 @@ module keyboard ( - input wire clk_in, - output bit keyboard [15:0] - ); + input wire clk_in, + output bit keyboard[15:0] +); - import "DPI-C" function bit [7:0] get_key(); + import "DPI-C" function bit [7:0] get_key(); - always_ff @(posedge clk_in) begin - bit[7:0] keyval = get_key(); - if (&keyval != 1) begin - keyboard[keyval[3:0]] = keyval[7]; - end + always_ff @(posedge clk_in) begin + bit [7:0] keyval = get_key(); + if (&keyval != 1) begin + keyboard[keyval[3:0]] = keyval[7]; end + end endmodule diff --git a/makefile b/makefile index 20a8f79..6c8603b 100644 --- a/makefile +++ b/makefile @@ -1,3 +1,5 @@ +.PHONY: run clean format + SDL_CFLAGS = `sdl2-config --cflags` SDL_LDFLAGS = `sdl2-config --libs` @@ -13,4 +15,8 @@ run: build clean: rm -rf obj_dir +format: + verible-verilog-format *.sv --inplace && clang-format *.cpp -i + + diff --git a/rng.sv b/rng.sv index 2a4963e..69def70 100644 --- a/rng.sv +++ b/rng.sv @@ -1,19 +1,19 @@ module rng ( input wire clk_in, input wire [15:0] pc, - input bit keyboard [15:0], + input bit keyboard[15:0], input int cycle_counter, output bit [7:0] rand_bit - ); +); - bit [7:0] last; - - always_ff @(posedge clk_in) begin - for (int i = 0; i < 8; i++) begin - rand_bit[i] ^= ~keyboard[i] ? cycle_counter[i] : cycle_counter[7-i]; - rand_bit[i] ^= (cycle_counter % 7) == 0 ? pc[i] : ~pc[i]; - rand_bit[i] ^= keyboard[i+7] ? ~last[i] : last[i]; - end - last = rand_bit; + bit [7:0] last; + + always_ff @(posedge clk_in) begin + for (int i = 0; i < 8; i++) begin + rand_bit[i] ^= ~keyboard[i] ? cycle_counter[i] : cycle_counter[7-i]; + rand_bit[i] ^= (cycle_counter % 7) == 0 ? pc[i] : ~pc[i]; + rand_bit[i] ^= keyboard[i+7] ? ~last[i] : last[i]; end + last = rand_bit; + end endmodule diff --git a/rom_loader.sv b/rom_loader.sv index 821d36e..5bdf540 100644 --- a/rom_loader.sv +++ b/rom_loader.sv @@ -1,18 +1,19 @@ module rom_loader ( - output bit [7:0] memory [0:4095] - ); + output bit [7:0] memory[0:4095] +); - import "DPI-C" function int load_rom(); - import "DPI-C" function bit [7:0] get_next_instr(); - import "DPI-C" function void close_rom(); + import "DPI-C" function int load_rom(); + import "DPI-C" function bit [7:0] get_next_instr(); + import "DPI-C" function void close_rom(); - initial begin - int rom_size = load_rom(); - $display("HW : ROM size is %0d bytes (%0d bits) (%0d instructions)", rom_size, rom_size * 8, rom_size / 2); - for (int i = 0; i < rom_size; i++) begin - memory['h200 + i] = get_next_instr(); - end - close_rom(); - $display("HW : ROM loaded successfully"); + initial begin + int rom_size = load_rom(); + $display("HW : ROM size is %0d bytes (%0d bits) (%0d instructions)", rom_size, + rom_size * 8, rom_size / 2); + for (int i = 0; i < rom_size; i++) begin + memory['h200+i] = get_next_instr(); end + close_rom(); + $display("HW : ROM loaded successfully"); + end endmodule diff --git a/yayacemu.cpp b/yayacemu.cpp index ac231b7..e695987 100644 --- a/yayacemu.cpp +++ b/yayacemu.cpp @@ -1,14 +1,14 @@ -#include "svdpi.h" -#include "Vchip8__Dpi.h" -#include -#include #include "Vchip8.h" +#include "Vchip8__Dpi.h" +#include "svdpi.h" #include "verilated.h" #include #include #include #include #include +#include +#include #define SCREEN_WIDTH 64 #define SCREEN_HEIGHT 32 @@ -18,34 +18,33 @@ FILE *rom_file; SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *texture; -char* rom_name; +char *rom_name; void init_screen() { SDL_Init(SDL_INIT_EVERYTHING); - window = - SDL_CreateWindow("Yet Another Yet Another Chip-8 Emulator", // creates a window - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - SCREEN_WIDTH * 10, SCREEN_HEIGHT * 10, 0); - renderer = - SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + window = SDL_CreateWindow( + "Yet Another Yet Another Chip-8 Emulator", // creates a window + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH * 10, + SCREEN_HEIGHT * 10, 0); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, - SDL_TEXTUREACCESS_STREAMING, - SCREEN_WIDTH, SCREEN_HEIGHT); + SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, + SCREEN_HEIGHT); std::cout << "INF_EMU: Screen initialized" << '\n'; } void set_beep(const svBit beep) { if (beep == 1) - SDL_SetTextureColorMod(texture, 255, 0, 0); + SDL_SetTextureColorMod(texture, 255, 0, 0); else - SDL_SetTextureColorMod(texture, 255, 255, 255); + SDL_SetTextureColorMod(texture, 255, 255, 255); } -void draw_screen(const svLogicVecVal* vram) { - uint32_t *screen = (uint32_t*) malloc(SCREEN_WIDTH*SCREEN_HEIGHT*32); - for(int i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) { - screen[i] = vram[i].aval; +void draw_screen(const svLogicVecVal *vram) { + uint32_t *screen = (uint32_t *)malloc(SCREEN_WIDTH * SCREEN_HEIGHT * 32); + for (int i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) { + screen[i] = vram[i].aval; } SDL_UpdateTexture(texture, NULL, screen, sizeof(screen[0]) * SCREEN_WIDTH); SDL_RenderClear(renderer); @@ -56,12 +55,12 @@ void draw_screen(const svLogicVecVal* vram) { } int load_rom() { - std::cout << "INF_EMU: Loading ROM " << rom_name << '\n'; + std::cout << "INF_EMU: Loading ROM " << rom_name << '\n'; rom_file = fopen(rom_name, "r"); if (rom_file == NULL) { - std::cout << "INF_EMU: Error reading ROM file. Panicing." << '\n'; - exit(1); + std::cout << "INF_EMU: Error reading ROM file. Panicing." << '\n'; + exit(1); } fseek(rom_file, 0L, SEEK_END); @@ -72,93 +71,88 @@ int load_rom() { return rom_size; } -svBitVecVal get_next_instr() { - return (uint8_t) fgetc(rom_file); -} +svBitVecVal get_next_instr() { return (uint8_t)fgetc(rom_file); } -void close_rom() { - fclose(rom_file); -} +void close_rom() { fclose(rom_file); } svBitVecVal get_key() { - SDL_Event event; - uint8_t down = 0; + SDL_Event event; + uint8_t down = 0; - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_KEYDOWN: - down = 128; - case SDL_KEYUP: - switch(event.key.keysym.sym) { - case SDLK_0: - return down | (uint8_t) 0; - case SDLK_1: - return down | (uint8_t) 1; - case SDLK_2: - return down | (uint8_t) 2; - case SDLK_3: - return down | (uint8_t) 3; - case SDLK_4: - return down | (uint8_t) 4; - case SDLK_5: - return down | (uint8_t) 5; - case SDLK_6: - return down | (uint8_t) 6; - case SDLK_7: - return down | (uint8_t) 7; - case SDLK_8: - return down | (uint8_t) 8; - case SDLK_9: - return down | (uint8_t) 9; - case SDLK_a: - return down | (uint8_t) 10; - case SDLK_b: - return down | (uint8_t) 11; - case SDLK_c: - return down | (uint8_t) 12; - case SDLK_d: - return down | (uint8_t) 13; - case SDLK_e: - return down | (uint8_t) 14; - case SDLK_f: - return down | (uint8_t) 15; - default: - return 255; - } - - - default: - return 255; - } + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + down = 128; + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_0: + return down | (uint8_t)0; + case SDLK_1: + return down | (uint8_t)1; + case SDLK_2: + return down | (uint8_t)2; + case SDLK_3: + return down | (uint8_t)3; + case SDLK_4: + return down | (uint8_t)4; + case SDLK_5: + return down | (uint8_t)5; + case SDLK_6: + return down | (uint8_t)6; + case SDLK_7: + return down | (uint8_t)7; + case SDLK_8: + return down | (uint8_t)8; + case SDLK_9: + return down | (uint8_t)9; + case SDLK_a: + return down | (uint8_t)10; + case SDLK_b: + return down | (uint8_t)11; + case SDLK_c: + return down | (uint8_t)12; + case SDLK_d: + return down | (uint8_t)13; + case SDLK_e: + return down | (uint8_t)14; + case SDLK_f: + return down | (uint8_t)15; + default: + return 255; + } + + default: + return 255; } - return 255; + } + return 255; } -int main(int argc, char** argv) { - if (argc < 2) { - std::cout << "Use: yayacemu [ROM_NAME]" << '\n'; - exit(1); +int main(int argc, char **argv) { + if (argc < 2) { + std::cout << "Use: yayacemu [ROM_NAME]" << '\n'; + exit(1); + } + + rom_name = argv[1]; + + VerilatedContext *contextp = new VerilatedContext; + contextp->commandArgs(argc, argv); + + Vchip8 *dut = new Vchip8{contextp}; + + while (true) { + dut->clk_in ^= 1; + dut->eval(); + usleep(1000000 / EMULATION_HZ); + if (SDL_QuitRequested()) { + std::cout << "INF_EMU: Received Quit from SDL. Goodbye!" << '\n'; + break; } + } - rom_name = argv[1]; - - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - - Vchip8* dut = new Vchip8{contextp}; - - while (true) { - dut->clk_in ^= 1; - dut->eval(); - usleep(1000000/EMULATION_HZ); - if (SDL_QuitRequested()) { - std::cout << "INF_EMU: Received Quit from SDL. Goodbye!" << '\n'; - break; - } - } - - fflush(stdout); - delete dut; - delete contextp; - return 0; + fflush(stdout); + delete dut; + delete contextp; + return 0; }