diff --git a/chip8.sv b/chip8.sv index ae7c4ee..5f905ad 100644 --- a/chip8.sv +++ b/chip8.sv @@ -5,28 +5,18 @@ module chip8 ( output logic lcd_data, output logic [5:0] led, input wire [3:0] row, - output logic [3:0] col + output logic [3:0] col, + output logic beep ); logic debug_overlay; logic slow_clk; -`ifdef FAST_CLK - assign slow_clk = fpga_clk; -`endif - -`ifndef FAST_CLK - downclocker #(12) dc ( + downclocker #(1) dc ( fpga_clk, slow_clk ); -`endif logic key_clk; -`ifdef FAST_CLK - downclocker #(1) dck ( -`endif -`ifndef FAST_CLK downclocker #(12) dck ( -`endif fpga_clk, key_clk ); @@ -76,6 +66,7 @@ logic debug_overlay; lcd_clk, lcd_data, nc, + beep, row, col, debug_overlay diff --git a/cpu.sv b/cpu.sv index 9b152e6..08aef65 100644 --- a/cpu.sv +++ b/cpu.sv @@ -13,11 +13,14 @@ module cpu ( output logic lcd_clk, output logic lcd_data, output logic [5:0] led, + output logic beep, input wire [3:0] row, input wire [3:0] col, input wire debug_overlay ); +assign beep = sound_timer > 0; + logic [5:0] lcd_led; logic alu_rst; logic [7:0] alu_result; @@ -26,6 +29,8 @@ logic [5:0] lcd_led; logic alu_done; logic compute_of; + logic [4:0] vblank; + assign led = state[5:0]; alu alu ( @@ -64,19 +69,19 @@ logic [5:0] lcd_led; if (vram[`BLP/8][7-(`BLP%8)] == 1) begin registers[15] <= 1; end - vram[`BLP/8][7-(`BLP%8)] = vram[`BLP/8][7-(`BLP%8)] ^ 1; + vram[`BLP/8][7-(`BLP%8)] <= vram[`BLP/8][7-(`BLP%8)] ^ 1; // bottom right `define BRP ((y*128*2) + x*2 +129) - vram[`BRP/8][7-(`BRP%8)] = vram[`BRP/8][7-(`BRP%8)] ^ 1; + vram[`BRP/8][7-(`BRP%8)] <= vram[`BRP/8][7-(`BRP%8)] ^ 1; // top left `define TLP ((y*128*2) + x*2) - vram[`TLP/8][7-(`TLP%8)] = vram[`TLP/8][7-(`TLP%8)] ^ 1; + vram[`TLP/8][7-(`TLP%8)] <= vram[`TLP/8][7-(`TLP%8)] ^ 1; // top right `define TRP ((y*128*2) + x*2+1) - vram[`TRP/8][7-(`TRP%8)] = vram[`TRP/8][7-(`TRP%8)] ^ 1; + vram[`TRP/8][7-(`TRP%8)] <= vram[`TRP/8][7-(`TRP%8)] ^ 1; end endtask @@ -141,6 +146,8 @@ logic [5:0] lcd_led; logic [11:0] dst_addr; } instr; + logic [12:0] wait_key; + initial begin state = ST_FETCH_HI; cycle_counter = 0; @@ -154,16 +161,16 @@ logic [5:0] lcd_led; end always_ff @(posedge clk_in) begin -`ifdef FAST_CLOCK - if (cycle_counter % 100 == 0) begin -`endif + $display("%0d", sound_timer); + if (cycle_counter % 200 == 0) begin + vblank <= 0; if (delay_timer > 0) delay_timer <= delay_timer - 1; if (sound_timer > 0) sound_timer <= sound_timer - 1; -`ifdef FAST_CLOCK + end else begin + vblank <= 1; end -`endif case (state) ST_FETCH_HI: begin rd_memory_address <= program_counter[11:0]; @@ -190,7 +197,6 @@ logic [5:0] lcd_led; instr.op <= CLS; state <= ST_EXEC; clr_cnt <= 0; - program_counter <= program_counter + 2; end else if (opcode == 16'h00EE) begin instr.op <= RET; state <= ST_EXEC; @@ -354,7 +360,7 @@ logic [5:0] lcd_led; instr.dst_reg <= opcode[11:8]; instr.alu_i.op <= structs::SHR; - instr.alu_i.operand_a <= registers[opcode[11:8]]; + instr.alu_i.operand_a <= registers[opcode[7:4]]; instr.alu_i.operand_b <= 1; compute_of <= 1; @@ -384,7 +390,7 @@ logic [5:0] lcd_led; instr.dst_reg <= opcode[11:8]; instr.alu_i.op <= structs::SHL; - instr.alu_i.operand_a <= registers[opcode[11:8]]; + instr.alu_i.operand_a <= registers[opcode[7:4]]; instr.alu_i.operand_b <= 1; compute_of <= 1; @@ -411,7 +417,6 @@ logic [5:0] lcd_led; 16'hB???: begin instr.op <= ALUJ; - instr.op <= CALU; instr.alu_i.op <= structs::ADDL; instr.alu_i.operand_a <= registers[0]; instr.alu_i.operand_b_long <= opcode[11:0]; @@ -455,9 +460,10 @@ logic [5:0] lcd_led; state <= ST_EXEC; end 16'hF?0A: begin - $display("IO waiting"); instr.op <= IOW; + wait_key[12] <= 1; + instr.src <= KEY; instr.dst <= REG; @@ -524,6 +530,7 @@ logic [5:0] lcd_led; end 16'hF?55: begin instr.op <= LDL; + index_reg <= index_reg + 1; instr.src <= REG; instr.src_reg <= opcode[11:8]; //FIXME: need to expand mem? @@ -539,6 +546,7 @@ logic [5:0] lcd_led; end 16'hF?65: begin instr.op <= LDL; + index_reg <= index_reg + 1; instr.src <= MEM; /* verilator lint_off WIDTHEXPAND */ @@ -589,14 +597,16 @@ logic [5:0] lcd_led; ST_DRAW: begin if (draw_state.stage == INIT) begin - draw_state.x <= instr.src_sprite_x; - draw_state.y <= instr.src_sprite_y; + if (vblank == 0) begin + draw_state.x <= instr.src_sprite_x; + draw_state.y <= instr.src_sprite_y; - draw_state.r <= 0; - draw_state.c <= 0; + draw_state.r <= 0; + draw_state.c <= 0; - draw_state.stage <= DRAW; - registers[15] <= 0; + draw_state.stage <= DRAW; + registers[15] <= 0; + end end else begin if (draw_state.r == instr.src_sprite_sz + 1) begin state <= ST_CLEANUP; @@ -700,6 +710,7 @@ logic [5:0] lcd_led; alu_rst <= 0; if (alu_done) begin instr.src <= BYTE; + if (instr.dst == IDX_REG) instr.src_byte <= alu_result_long[11:0]; else if (instr.dst_reg != 15 || !compute_of) begin @@ -709,20 +720,24 @@ logic [5:0] lcd_led; end registers[15] <= compute_of ? alu_overflow : registers[15]; - if (instr.op == ALU) begin + + if (instr.op === ALU) begin state <= ST_WB; program_counter <= program_counter + 2; - end else if (instr.op == CALU) begin + + end else if (instr.op === CALU) begin + state <= ST_CLEANUP; if (|alu_result) begin program_counter <= program_counter + 4; end else begin program_counter <= program_counter + 2; end - end else begin - $display("Untested!"); + end else if (instr.op === ALUJ) begin + state <= ST_CLEANUP; program_counter <= alu_result_long; + end end end @@ -754,12 +769,17 @@ logic [5:0] lcd_led; state <= ST_CLEANUP; end IOW: begin - if (|keymap != 0) begin + if (|keymap != 0 && wait_key[12] == 1) begin $display("IO not waiting"); for(int m = 0; m < 16; m++) begin - if (keymap[m]) - instr.src_byte <= m[11:0]; + if (keymap[m]) begin + wait_key[11:0] <= m[11:0]; + wait_key[12] <= 0; + end end + end + if (keymap[wait_key[3:0]] == 0 && wait_key[12] == 0) begin + instr.src_byte <= wait_key[11:0]; program_counter <= program_counter + 2; state <= ST_WB; instr.src <= BYTE; @@ -771,7 +791,7 @@ logic [5:0] lcd_led; program_counter <= program_counter + 2; end else begin clr_cnt <= clr_cnt + 1; - vram[clr_cnt] <= 0; + vram[clr_cnt] <= 8'h00; end end diff --git a/yayacemu.cpp b/yayacemu.cpp index d87f5d0..869012e 100644 --- a/yayacemu.cpp +++ b/yayacemu.cpp @@ -12,7 +12,7 @@ #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 -#define EMULATION_HZ 50000 +#define EMULATION_HZ 100000 SDL_Window *window; SDL_Renderer *renderer; @@ -29,14 +29,6 @@ void init_screen() { texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, 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); - else - SDL_SetTextureColorMod(texture, 255, 255, 255); } void draw_screen(const svLogicVecVal *vram) { @@ -222,7 +214,11 @@ int main(int argc, char **argv) { dut->fpga_clk ^= 1; dut->eval(); - usleep(1000000 / EMULATION_HZ); + + if (dut->beep == 1) + SDL_SetTextureColorMod(texture, 255, 0, 0); + else + SDL_SetTextureColorMod(texture, 255, 255, 255); if (SDL_QuitRequested()) { std::cout << "INF_EMU: Received Quit from SDL. Goodbye!" << '\n';