works on simulation

This commit is contained in:
Nicholas Orlowsky 2024-04-15 10:32:43 -05:00
parent 4855bbc42d
commit 2b3647cbb1
Signed by: nickorlow
GPG key ID: 838827D8C4611687
3 changed files with 58 additions and 51 deletions

View file

@ -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
View file

@ -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

View file

@ -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';