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