diff --git a/cores/mist/blitter.v b/cores/mist/blitter.v index 1969779..9b6706e 100644 --- a/cores/mist/blitter.v +++ b/cores/mist/blitter.v @@ -197,14 +197,7 @@ always @(negedge clk) begin if((addr == 5'h1d) && ~lds) op <= din[3:0]; if((addr == 5'h1e) && ~uds) begin - - // HACK: The tg68 does not have atomic read-modify-write cycles - // and may be interrupted by the blitter in between. We thus don't - // accept changes to the line_number register as long as the blitter - // is running since TOS polls the busy flag in the same register - // using bset which in turn can mess up the line_number - if(!busy) line_number <= din[11:8]; - + line_number <= din[11:8]; smudge <= din[13]; hog <= din[14]; @@ -272,7 +265,7 @@ always @(negedge clk) begin end // advance state machine only if bus is owned - if(br_out && !br_in) begin + if(br_out && !br_in && (y_count != 0)) begin // first extra source read (fxsr) if(state == 2'd3) begin if(src_x_inc[15] == 1'b0) src <= { src[15:0], bm_data_in_latch}; @@ -348,6 +341,11 @@ always @(negedge clk) begin else state <= 2'd0; // normal source read state end end + +// if(busy && (y_count == 0)) begin + // undo last src inc + // src_addr <= src_addr - { {8{src_x_inc[15]}}, src_x_inc }; + // end end end diff --git a/cores/mist/mist_top.v b/cores/mist/mist_top.v index 51f8cae..2f2380c 100644 --- a/cores/mist/mist_top.v +++ b/cores/mist/mist_top.v @@ -346,21 +346,12 @@ wire blitter_master_read; wire blitter_irq; wire [15:0] blitter_master_data_out; -wire blitter_br = blitter_br_out; -wire blitter_bg = 1'b1; - -//wire blitter_bg = blitter_br; - -//reg blitter_br; -//always @(posedge clk_128) begin -// if(blitter_br_out && (tg68_busstate == 2'd0)) -// blitter_br <= 1'b1; - -// else if(!blitter_br_out) -// blitter_br <= 1'b0; -//end - -wire blitter_br_out; +// The bg signal works a little different as usual. The blitter +// will only apply br when bg allows it to do so. Forcing bussatte == 0 +// make sure that the bus is never transferred in the middle of an +// instruction. This is required since some instructions use d to control +// the blitter are atomic on a real ST +wire blitter_bg = (tg68_busstate == 2'd0); blitter blitter ( .bus_cycle (bus_cycle ), @@ -383,7 +374,7 @@ blitter blitter ( .bm_data_in (ram_data_out), .br_in (data_io_br ), - .br_out (blitter_br_out ), + .br_out (blitter_br ), .bg (blitter_bg ), .irq (blitter_irq ), @@ -904,34 +895,30 @@ wire MEM14M = (system_ctrl[3:1] == 3'd5); // rom is also at 0x000000 to 0x000007 wire cpu2lowrom = (tg68_adr[23:3] == 21'd0); -// ram from 0x000000 to 0x400000 +// ordinary ram from 0x000000 to 0x400000, more if enabled wire cpu2ram = (!cpu2lowrom) && ( - (tg68_adr[23:22] == 2'b00) || // ordinary 4MB - ((MEM14M || MEM8M) && (tg68_adr[23:22] == 2'b01)) || // 8MB - (MEM14M && ((tg68_adr[23:22] == 2'b10) || // 12MB - (tg68_adr[23:21] == 3'b110)))); // 14MB - -wire cpu2ram14 = (!cpu2lowrom) && ( - (tg68_adr[23:22] == 2'b00) || // ordinary 4MB - (tg68_adr[23:22] == 2'b01) || // 8MB - (tg68_adr[23:22] == 2'b10) || // 12MB - (tg68_adr[23:21] == 3'b110)); // 14MB + (tg68_adr[23:22] == 2'b00) || // ordinary 4MB + ((MEM14M || MEM8M) && (tg68_adr[23:22] == 2'b01)) || // 8MB + (MEM14M && ((tg68_adr[23:22] == 2'b10) || // 12MB + (tg68_adr[23:21] == 3'b110))) || // 14MB + (steroids && (tg68_adr[23:19] == 5'b11101))); // 512k at $e80000 for STEroids // 256k tos from 0xe00000 to 0xe40000 -wire cpu2tos256k = (tg68_adr[23:18] == 6'b111000) || - cpu2lowrom; +wire cpu2tos256k = (tg68_adr[23:18] == 6'b111000); // 192k tos from 0xfc0000 to 0xff0000 wire cpu2tos192k = (tg68_adr[23:17] == 7'b1111110) || - (tg68_adr[23:16] == 8'b11111110) || - cpu2lowrom; + (tg68_adr[23:16] == 8'b11111110); // 128k cartridge from 0xfa0000 to 0xfbffff wire cpu2cart = (tg68_adr[23:16] == 8'hfa) || ((tg68_adr[23:16] == 8'hfb) && !dongle_present); // include fb0000 only if no dongle present +// all rom areas +wire cpu2rom = cpu2lowrom || cpu2tos192k || cpu2tos256k || cpu2cart; + // cpu to any type of mem (rw on ram, read on rom) -wire cpu2mem = cpu2ram14 || (tg68_rw && (cpu2tos192k || cpu2tos256k || cpu2cart)); +wire cpu2mem = cpu2ram || (tg68_rw && cpu2rom); // io from 0xff0000 wire cpu2io = (tg68_adr[23:16] == 8'hff); diff --git a/cores/mist/video.v b/cores/mist/video.v index 4918014..8faf25c 100644 --- a/cores/mist/video.v +++ b/cores/mist/video.v @@ -194,13 +194,14 @@ wire [9:0] t10_v_border_top = config_string[19:10]; wire [9:0] t11_v_end = config_string[9:0]; // default video mode is monochrome -parameter DEFAULT_MODE = 2'd2; +parameter DEFAULT_MODE = 3'd2; // shiftmode register -reg [1:0] shmode; -wire mono = (shmode == 2'd2); -wire mid = (shmode == 2'd1); -wire low = (shmode == 2'd0); +reg [2:0] shmode; +wire ttmid = (shmode == 3'd4); +wire mono = (shmode == 3'd2); +wire mid = (shmode == 3'd1); +wire low = (shmode == 3'd0); // derive number of planes from shiftmode wire [2:0] planes = mono?3'd1:(mid?3'd2:3'd4); @@ -225,6 +226,8 @@ reg [7:0] line_offset; // number of words to skip at the end of each reg [3:0] pixel_offset; // number of pixels to skip at begin of line reg ste_overscan_enable; // STE has a special 16 bit overscan +wire mistvid = 1'b1; // enable MiST extended video mode(s) + // --------------------------------------------------------------------------- // ----------------------------- CPU register read --------------------------- // --------------------------------------------------------------------------- @@ -269,7 +272,7 @@ always @(reg_sel, reg_rw, reg_uds, reg_lds, reg_addr, _v_bas_ad, shmode, vaddr, end // shift mode register - if(reg_addr == 6'h30) reg_dout <= { 6'h00, shmode, 8'h00 }; + if(reg_addr == 6'h30) reg_dout <= { 5'h00, shmode, 8'h00 }; end end @@ -369,8 +372,9 @@ always @(negedge reg_clk) begin end end end - - if(reg_addr == 6'h30 && !reg_uds) shmode <= reg_din[9:8]; + + // make msb writeable if MiST video modes are enabled + if(reg_addr == 6'h30 && !reg_uds) shmode <= { mistvid?reg_din[10]:1'b0, reg_din[9:8] }; end end end @@ -470,13 +474,19 @@ always @(posedge clk) begin end if(!scan_doubler_enable) begin - // hires mode: shift one plane only and reload - // shift_0 register every 16 clocks - if(vga_hcnt[3:0] == 4'hf) shift_0 <= data_latch[0]; - else shift_0[15:1] <= shift_0[14:0]; - - // TODO: Color modes not using scan doubler - + // hires mode: shift all planes and reload + // shift registers every 16 clocks + if(vga_hcnt[3:0] == 4'hf) begin + shift_0 <= data_latch[0]; + shift_1 <= data_latch[1]; + shift_2 <= data_latch[2]; + shift_3 <= data_latch[3]; + end else begin + shift_0[15:1] <= shift_0[14:0]; + shift_1[15:1] <= shift_1[14:0]; + shift_2[15:1] <= shift_2[14:0]; + shift_3[15:1] <= shift_3[14:0]; + end end end @@ -492,38 +502,40 @@ reg last_syncmode; reg [3:0] bottom_overscan_cnt; reg [3:0] top_overscan_cnt; -wire bottom_overscan = (bottom_overscan_cnt != 0) /* synthesis keep */; -wire top_overscan = (top_overscan_cnt != 0) /* synthesis keep */; +wire bottom_overscan = (bottom_overscan_cnt != 0); +wire top_overscan = (top_overscan_cnt != 0); always @(posedge clk) begin - last_syncmode <= syncmode[1]; // delay syncmode to detect changes + if(reg_reset) begin + top_overscan_cnt <= 4'd0; + bottom_overscan_cnt <= 4'd0; + end else begin + last_syncmode <= syncmode[1]; // delay syncmode to detect changes - // this is the magic used to do "overscan". - // the magic actually involves more than writing zero (60hz) - // within line 200. But this is sufficient for our detection + // this is the magic used to do "overscan". + // the magic actually involves more than writing zero (60hz) + // within line 200. But this is sufficient for our detection - // trigger in line 198/199 - if((vcnt == { 8'd97, 2'b00} ) && (vga_hcnt == 10'd0) && (bottom_overscan_cnt != 0)) - bottom_overscan_cnt <= bottom_overscan_cnt - 4'd1; + // trigger in line 198/199 + if((vcnt == { 8'd97, 2'b00} ) && (vga_hcnt == 10'd0) && (bottom_overscan_cnt != 0)) + bottom_overscan_cnt <= bottom_overscan_cnt - 4'd1; - if((vcnt[9:2] == 8'd98)||(vcnt[9:2] == 8'd99)||(vcnt[9:2] == 8'd100)) begin - // syncmode has changed from 1 to 0 (50 to 60 hz) - if((syncmode[1] == 1'b0) && (last_syncmode == 1'b1)) - bottom_overscan_cnt <= 4'd15; - end + if((vcnt[9:2] == 8'd98)||(vcnt[9:2] == 8'd99)||(vcnt[9:2] == 8'd100)) begin + // syncmode has changed from 1 to 0 (50 to 60 hz) + if((syncmode[1] == 1'b0) && (last_syncmode == 1'b1)) + bottom_overscan_cnt <= 4'd15; + end - // trigger in line 284/285 - if((vcnt == {8'd133, 2'b00 }) && (vga_hcnt == 10'd0) && (top_overscan_cnt != 0)) - top_overscan_cnt <= top_overscan_cnt - 4'd1; + // trigger in line 284/285 + if((vcnt == {8'd133, 2'b00 }) && (vga_hcnt == 10'd0) && (top_overscan_cnt != 0)) + top_overscan_cnt <= top_overscan_cnt - 4'd1; - if((vcnt[9:2] == 8'd134)||(vcnt[9:2] == 8'd135)||(vcnt[9:2] == 8'd136)) begin - // syncmode has changed from 1 to 0 (50 to 60 hz) - if((syncmode[1] == 1'b0) && (last_syncmode == 1'b1)) - top_overscan_cnt <= 4'd15; - end - -// top_overscan <= 1'b1; -// bottom_overscan <= 1'b1; + if((vcnt[9:2] == 8'd134)||(vcnt[9:2] == 8'd135)||(vcnt[9:2] == 8'd136)) begin + // syncmode has changed from 1 to 0 (50 to 60 hz) + if((syncmode[1] == 1'b0) && (last_syncmode == 1'b1)) + top_overscan_cnt <= 4'd15; + end + end end // --------------------------------------------------------------------------- @@ -725,9 +737,13 @@ always @(posedge clk) begin // make sure each line starts with plane 0 if(st_hcnt == de_h_start) plane <= 2'd0; + + // according to hatari the video counter is reloaded 3 lines before + // the vbi occurs. This is right after the display has been painted. + // The video address counter is reloaded right after display ends - // The video address counter is reloaded right before display starts - if((vga_hcnt == t3_h_blank_left) && (vcnt == t7_v_blank_bot)) begin + // TODO: -1 and pacmania works ... + if((vga_hcnt == t3_h_blank_left) && (vcnt == (t7_v_blank_bot-de_v_offset+10'd1))) begin vaddr <= _v_bas_ad; // copy syncmode @@ -739,17 +755,28 @@ always @(posedge clk) begin // read if display enable is active if(de) begin + // move incoming video data into data latch + if(ttmid) begin + // TT mid compatible part fetches all 4 planes at once + data_latch[0] <= data[15: 0]; + data_latch[1] <= data[31:16]; + data_latch[2] <= data[47:32]; + data_latch[3] <= data[63:48]; + + vaddr <= vaddr + 23'd4; + end else begin + + // ST shifter only uses 16 out of possible 64 bits, so select the right word + case(vaddr[1:0]) + 2'd0: data_latch[plane] <= data[15: 0]; + 2'd1: data_latch[plane] <= data[31:16]; + 2'd2: data_latch[plane] <= data[47:32]; + 2'd3: data_latch[plane] <= data[63:48]; + endcase - // ST shifter only uses 16 out of possible 64 bits, so select the right word - case(vaddr[1:0]) - 2'd0: data_latch[plane] <= data[15: 0]; - 2'd1: data_latch[plane] <= data[31:16]; - 2'd2: data_latch[plane] <= data[47:32]; - 2'd3: data_latch[plane] <= data[63:48]; - endcase - - vaddr <= vaddr + 23'd1; + vaddr <= vaddr + 23'd1; + end end // advance plane counter