From bd8c4da2d6ac3b998a866c5ca4de59e2bb78e70b Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sat, 8 Sep 2018 09:59:21 -0400 Subject: [PATCH] verilog presets; early exit from jsasm errors --- presets/verilog/cpu16.v | 22 ++--- presets/verilog/cpu8.v | 47 +++++----- presets/verilog/lfsr.v | 2 +- presets/verilog/racing_game_cpu.v | 146 +++++++++++++++++------------- presets/verilog/sprite_bitmap.v | 3 +- presets/verilog/tank.v | 2 +- src/worker/workermain.js | 3 + 7 files changed, 123 insertions(+), 102 deletions(-) diff --git a/presets/verilog/cpu16.v b/presets/verilog/cpu16.v index 68a38cc1..6adb962b 100644 --- a/presets/verilog/cpu16.v +++ b/presets/verilog/cpu16.v @@ -21,14 +21,14 @@ `define OP_SBB 4'hf -module ALU(A, B, Y, aluop, carry); +module ALU(A, B, carry, aluop, Y); - parameter N = 8; - input [N-1:0] A; - input [N-1:0] B; - output [N:0] Y; - input [3:0] aluop; - input carry; + parameter N = 8; // default width = 8 bits + input [N-1:0] A; // A input + input [N-1:0] B; // B input + input carry; // carry input + input [3:0] aluop; // alu operation + output [N:0] Y; // Y output + carry always @(*) case (aluop) @@ -312,8 +312,8 @@ module test_CPU16_top( .org 0x8000 .len 256 mov sp,@$6fff - mov dx,@Fib - jsr dx + mov dx,@Fib + jsr dx reset Fib: mov ax,#1 @@ -322,8 +322,8 @@ Loop: mov cx,ax add ax,bx mov bx,cx - push ax - pop ax + push ax + pop ax mov [42],ax mov ax,[42] bcc Loop diff --git a/presets/verilog/cpu8.v b/presets/verilog/cpu8.v index 8f3d4c59..88e029fd 100644 --- a/presets/verilog/cpu8.v +++ b/presets/verilog/cpu8.v @@ -5,30 +5,30 @@ // ALU operations `define OP_ZERO 4'h0 `define OP_LOAD_A 4'h1 -`define OP_INC 4'h2 -`define OP_DEC 4'h3 -`define OP_ASL 4'h4 -`define OP_LSR 4'h5 -`define OP_ROL 4'h6 -`define OP_ROR 4'h7 -`define OP_OR 4'h8 -`define OP_AND 4'h9 -`define OP_XOR 4'ha +`define OP_INC 4'h2 +`define OP_DEC 4'h3 +`define OP_ASL 4'h4 +`define OP_LSR 4'h5 +`define OP_ROL 4'h6 +`define OP_ROR 4'h7 +`define OP_OR 4'h8 +`define OP_AND 4'h9 +`define OP_XOR 4'ha `define OP_LOAD_B 4'hb -`define OP_ADD 4'hc -`define OP_SUB 4'hd -`define OP_ADC 4'he -`define OP_SBB 4'hf +`define OP_ADD 4'hc +`define OP_SUB 4'hd +`define OP_ADC 4'he +`define OP_SBB 4'hf +// ALU module +module ALU(A, B, carry, aluop, Y); -module ALU(A, B, Y, aluop, carry); - - parameter N = 8; - input [N-1:0] A; - input [N-1:0] B; - output [N:0] Y; - input [3:0] aluop; - input carry; + parameter N = 8; // default width = 8 bits + input [N-1:0] A; // A input + input [N-1:0] B; // B input + input carry; // carry input + input [3:0] aluop; // alu operation + output [N:0] Y; // Y output + carry always @(*) case (aluop) @@ -178,11 +178,6 @@ module CPU(clk, reset, address, data_in, data_out, write); write <= 1; state <= S_SELECT; end - // clear carry - 8'b10001000: begin - carry <= 0; - state <= S_SELECT; - end // swap A,B 8'b10000001: begin A <= B; diff --git a/presets/verilog/lfsr.v b/presets/verilog/lfsr.v index 3664db0d..fd2e7129 100644 --- a/presets/verilog/lfsr.v +++ b/presets/verilog/lfsr.v @@ -17,7 +17,7 @@ module LFSR(clk, reset, enable, lfsr); always @(posedge clk) begin if (reset) - lfsr <= {lfsr[NBITS-2:0], ~lfsr[0]}; + lfsr <= {lfsr[NBITS-2:0], 1'b1}; // reset loads with all 1s else if (enable) lfsr <= {lfsr[NBITS-2:0], 1'b0} ^ (feedback ? TAPS : 0); end diff --git a/presets/verilog/racing_game_cpu.v b/presets/verilog/racing_game_cpu.v index 941ec126..046a8851 100644 --- a/presets/verilog/racing_game_cpu.v +++ b/presets/verilog/racing_game_cpu.v @@ -37,29 +37,31 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, output [3:0] rgb; `endif - parameter PADDLE_X = 0; - parameter PADDLE_Y = 1; - parameter PLAYER_X = 2; - parameter PLAYER_Y = 3; - parameter ENEMY_X = 4; - parameter ENEMY_Y = 5; - parameter ENEMY_DIR = 6; - parameter SPEED = 7; - parameter TRACKPOS_LO = 8; - parameter TRACKPOS_HI = 9; + parameter PADDLE_X = 0; // paddle X coordinate + parameter PADDLE_Y = 1; // paddle Y coordinate + parameter PLAYER_X = 2; // player X coordinate + parameter PLAYER_Y = 3; // player Y coordinate + parameter ENEMY_X = 4; // enemy X coordinate + parameter ENEMY_Y = 5; // enemy Y coordinate + parameter ENEMY_DIR = 6; // enemy direction (1, -1) + parameter SPEED = 7; // player speed + parameter TRACKPOS_LO = 8; // track position (lo byte) + parameter TRACKPOS_HI = 9; // track position (hi byte) - parameter IN_HPOS = 8'h40; - parameter IN_VPOS = 8'h41; + parameter IN_HPOS = 8'h40; // CRT horizontal position + parameter IN_VPOS = 8'h41; // CRT vertical position + // flags: [0, 0, collision, vsync, hsync, vpaddle, hpaddle, display_on] parameter IN_FLAGS = 8'h42; - reg [7:0] ram[0:63]; - reg [7:0] rom[0:127]; + reg [7:0] ram[64]; // 64 bytes of RAM + reg [7:0] rom[128]; // 128 bytes of ROM - output wire [7:0] address_bus; - output reg [7:0] to_cpu; - output wire [7:0] from_cpu; - output wire write_enable; + output wire [7:0] address_bus; // CPU address bus + output reg [7:0] to_cpu; // data bus to CPU + output wire [7:0] from_cpu; // data bus from CPU + output wire write_enable; // write enable bit from CPU + // 8-bit CPU module CPU cpu(.clk(clk), .reset(reset), .address(address_bus), @@ -67,10 +69,12 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, .data_out(from_cpu), .write(write_enable)); + // RAM write from CPU always @(posedge clk) if (write_enable) ram[address_bus[5:0]] <= from_cpu; + // RAM read from CPU always @(*) casez (address_bus) // RAM @@ -84,7 +88,8 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, 8'b1???????: to_cpu = rom[address_bus[6:0]]; default: to_cpu = 8'bxxxxxxxx; endcase - + + // sync generator module hvsync_generator hvsync_gen( .clk(clk), .reset(0), @@ -95,23 +100,28 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, .vpos(vpos) ); + // flags for player sprite renderer module wire player_vstart = {1'0,ram[PLAYER_Y]} == vpos; wire player_hstart = {1'0,ram[PLAYER_X]} == hpos; wire player_gfx; wire player_is_drawing; + // flags for enemy sprite renderer module wire enemy_vstart = {1'0,ram[ENEMY_Y]} == vpos; wire enemy_hstart = {1'0,ram[ENEMY_X]} == hpos; wire enemy_gfx; wire enemy_is_drawing; + // flags shared between sprite renderer modules wire [3:0] car_sprite_yofs; wire [7:0] car_sprite_bits; + // car bitmap ROM car_bitmap car( .yofs(car_sprite_yofs), .bits(car_sprite_bits)); + // player sprite renderer sprite_renderer player_renderer( .clk(clk), .vstart(player_vstart), @@ -122,6 +132,7 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, .gfx(player_gfx), .in_progress(player_is_drawing)); + // enemy sprite renderer sprite_renderer enemy_renderer( .clk(clk), .vstart(enemy_vstart), @@ -132,31 +143,36 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, .gfx(enemy_gfx), .in_progress(player_is_drawing)); + // collision detection logic reg frame_collision; - always @(posedge clk) if (player_gfx && (enemy_gfx || track_gfx)) frame_collision <= 1; else if (vpos==0) frame_collision <= 0; + // track graphics wire track_offside = (hpos[7:5]==0) || (hpos[7:5]==7); wire track_shoulder = (hpos[7:3]==3) || (hpos[7:3]==28); wire track_gfx = (vpos[5:1]!=ram[TRACKPOS_LO][5:1]) && track_offside; + // RGB output wire r = display_on && (player_gfx || enemy_gfx || track_shoulder); wire g = display_on && (player_gfx || track_gfx); wire b = display_on && (enemy_gfx || track_shoulder); assign rgb = {1'b0,b,g,r}; + + //////////// CPU program code `ifdef EXT_INLINE_ASM initial begin rom = '{ __asm -.arch femto8 -.org 128 -.len 128 +.arch femto8 ; FEMTO-8 architecture +.org 128 ; origin = 128 ($80) +.len 128 ; length = 128 ($80) +; define constants .define PADDLE_X 0 .define PADDLE_Y 1 .define PLAYER_X 2 @@ -180,82 +196,88 @@ module racing_game_cpu_top(clk, reset, hsync, vsync, hpaddle, vpaddle, .define F_COLLIDE 32 Start: - lda #128 - sta PLAYER_X - sta ENEMY_X - sta ENEMY_Y + lda #128 ; load initial positions + sta PLAYER_X ; player_x = 128 + sta ENEMY_X ; enemy_x = 128 + sta ENEMY_Y ; enemy_y = 128 lda #180 - sta PLAYER_Y + sta PLAYER_Y ; player_y = 180 zero A - sta SPEED + sta SPEED ; player speed = 0 inc A - sta ENEMY_DIR -; test hpaddle flag + sta ENEMY_DIR ; enemy dir = 1 (right) +; read horizontal paddle position DisplayLoop: - lda #F_HPADDLE - ldb #IN_FLAGS - and none,[B] - bz DisplayLoop -; [vpos] -> paddle_x + lda #F_HPADDLE ; paddle flag -> A + ldb #IN_FLAGS ; addr of IN_FLAGS -> B + and none,[B] ; read B, AND with A + bz DisplayLoop ; loop until paddle flag set ldb #IN_VPOS - mov A,[B] - sta PLAYER_X -; wait for vsync=1 then vsync=0 + mov A,[B] ; load vertical position -> A + sta PLAYER_X ; store player x position +; wait for vsync lda #F_VSYNC ldb #IN_FLAGS WaitForVsyncOn: and none,[B] - bz WaitForVsyncOn + bz WaitForVsyncOn ; wait until VSYNC on WaitForVsyncOff: and none,[B] - bnz WaitForVsyncOff + bnz WaitForVsyncOff ; wait until VSYNC off ; check collision lda #F_COLLIDE ldb #IN_FLAGS - and none,[B] - bz NoCollision -; load slow speed + and none,[B] ; collision flag set? + bz NoCollision ; skip ahead if not lda #16 - sta SPEED + sta SPEED ; speed = 16 NoCollision: ; update speed ldb #SPEED - mov A,[B] - inc A -; don't store if == 0 - bz MaxSpeed - sta SPEED + mov A,[B] ; speed -> A + inc A ; increment speed + bz MaxSpeed ; speed wraps to 0? + sta SPEED ; no, store speed MaxSpeed: - mov A,[B] - lsr A + mov A,[B] ; reload speed -> A lsr A lsr A lsr A + lsr A ; divide speed by 16 ; add to lo byte of track pos ldb #TRACKPOS_LO - add B,[B] - swapab - sta TRACKPOS_LO - swapab + add B,[B] ; B <- speed/16 + trackpos_lo + swapab ; swap A <-> B + sta TRACKPOS_LO ; A -> trackpos_lo + swapab ; swap A <-> B again + bcc NoCarry ; carry flag from earlier add op +; add to hi byte of track pos + ldb #TRACKPOS_HI + mov B,[B] ; B <- trackpos_hi + inc b ; increment B + swapab ; swap A <-> B + sta TRACKPOS_HI ; A -> trackpos_hi + swapab ; swap A <-> B again +NoCarry: ; update enemy vert pos ldb #ENEMY_Y add A,[B] - sta ENEMY_Y + sta ENEMY_Y ; enemy_y = enemy_y + speed/16 ; update enemy horiz pos ldb #ENEMY_X mov A,[B] ldb #ENEMY_DIR add A,[B] - sta ENEMY_X + sta ENEMY_X ; enemy_x = enemy_x + enemy_dir sub A,#64 - and A,#127 - bnz SkipXReverse + and A,#127 ; A <- (enemy_x-64) & 127 + bnz SkipXReverse ; skip if enemy_x is in range ; load ENEMY_DIR and negate zero A sub A,[B] - sta ENEMY_DIR -; back to display loop + sta ENEMY_DIR ; enemy_dir = -enemy_dir SkipXReverse: +; back to display loop jmp DisplayLoop __endasm }; diff --git a/presets/verilog/sprite_bitmap.v b/presets/verilog/sprite_bitmap.v index 98c6c0a5..d0327b10 100644 --- a/presets/verilog/sprite_bitmap.v +++ b/presets/verilog/sprite_bitmap.v @@ -65,13 +65,14 @@ module sprite_bitmap_top(clk, reset, hsync, vsync, rgb); .yofs(car_sprite_yofs), .bits(car_sprite_bits)); + // start Y counter when we hit the top border (player_y) always @(posedge hsync) - // start sprite? if (vpos == player_y) car_sprite_yofs <= 15; else if (car_sprite_yofs != 0) car_sprite_yofs <= car_sprite_yofs - 1; + // restart X counter when we hit the left border (player_x) always @(posedge clk) if (hpos == player_x) car_sprite_xofs <= 15; diff --git a/presets/verilog/tank.v b/presets/verilog/tank.v index a2785a5d..b4f878d1 100644 --- a/presets/verilog/tank.v +++ b/presets/verilog/tank.v @@ -140,7 +140,7 @@ module tank_game_top(clk, reset, hsync, vsync, rgb, switches_p1, switches_p2); ); // multiplex player 1 and 2 load times during hsync - wire p2sel = hpos[3]; + wire p2sel = hpos > 280; // sprite ROM inputs for each player wire [7:0] tank1_sprite_addr; wire [7:0] tank2_sprite_addr; diff --git a/src/worker/workermain.js b/src/worker/workermain.js index 01ce95c4..7b901944 100644 --- a/src/worker/workermain.js +++ b/src/worker/workermain.js @@ -1284,6 +1284,9 @@ function compileVerilator(step) { var errors = []; var asmlines = []; step.code = compileInlineASM(step.code, platform, step, errors, asmlines); + if (errors.length) { + return {errors:errors}; + } var code = step.code; var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4); var verilator_mod = verilator_bin({