1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-27 12:21:44 +00:00

Started blitter implementation

This commit is contained in:
harbaum
2013-08-12 08:23:56 +00:00
parent 7e26005f0f
commit f2ca9df08c
8 changed files with 354 additions and 7 deletions

View File

@@ -116,7 +116,8 @@ always @(posedge clk) begin
readPout <= readPout + 4'd1;
end
always @(sel, ds, rw, addr, ikbd_rx_data_available, ikbd_rx_data, midi_rx_data_available, midi_tx_empty) begin
always @(sel, ds, rw, addr, ikbd_rx_data_available, ikbd_rx_data, ikbd_irq,
midi_rx_data, midi_rx_data_available, midi_tx_empty, midi_irq) begin
dout = 8'h00;
if(sel && ~ds && rw) begin

324
cores/mist/blitter.v Normal file
View File

@@ -0,0 +1,324 @@
// blitter docs:
module blitter (
input clk32, // 31.875 MHz
input [3:0] bus_cycle,
// cpu register interface
input clk,
input reset,
input sel,
input [4:0] addr,
input [15:0] din,
output reg [15:0] dout,
input uds,
input lds,
input rw,
output irq
);
assign irq = 1'b0;
// CPU controlled register set
reg [15:0] halftone_ram[15:0];
reg [15:1] src_x_inc;
reg [15:1] src_y_inc;
reg [23:1] src_addr;
reg [15:0] endmask1;
reg [15:0] endmask2;
reg [15:0] endmask3;
reg [15:1] dst_x_inc;
reg [15:1] dst_y_inc;
reg [23:1] dst_addr;
reg [15:0] x_count;
reg [15:0] x_count_latch;
reg [15:0] y_count;
reg [1:0] hop;
reg [3:0] op;
reg [3:0] line_number;
reg smudge;
reg hog;
reg busy;
reg [3:0] skew;
reg nfsr;
reg fxsr;
// ------------------ cpu interface --------------------
// CPU READ
always @(sel, rw, addr, src_y_inc, src_x_inc, src_addr, endmask1, endmask2, endmask3,
dst_x_inc, dst_y_inc, dst_addr, x_count, y_count, hop, op, busy, hog,
smudge, line_number, fxsr, nfsr, skew) begin
dout = 16'h0000;
if(sel && rw) begin
if((addr >= 5'h00) && (addr <= 5'h0f)) dout <= halftone_ram[addr];
if(addr == 5'h10) dout <= { src_x_inc, 1'b0 };
if(addr == 5'h11) dout <= { src_y_inc, 1'b0 };
if(addr == 5'h12) dout <= { 8'h00, src_addr[23:16] };
if(addr == 5'h13) dout <= { src_addr [15:1], 1'b0 };
if(addr == 5'h14) dout <= endmask1;
if(addr == 5'h15) dout <= endmask2;
if(addr == 5'h16) dout <= endmask3;
if(addr == 5'h17) dout <= { dst_x_inc, 1'b0 };
if(addr == 5'h18) dout <= { dst_y_inc, 1'b0 };
if(addr == 5'h19) dout <= { 8'h00, dst_addr[23:16] };
if(addr == 5'h1a) dout <= { dst_addr [15:1], 1'b0 };
if(addr == 5'h1b) dout <= x_count;
if(addr == 5'h1c) dout <= y_count;
// since reading them has not side effect we can return the 8 bit registers
// without caring for uds/lds
if(addr == 5'h1d) dout <= { 6'b000000, hop, 4'b0000, op };
if(addr == 5'h1e) dout <= { busy, hog, smudge, 1'b0, line_number, fxsr, nfsr, 2'b00, skew };
end
end
// CPU WRITE
always @(negedge clk) begin
if(reset) begin
end else begin
if(sel && ~rw) begin
// ------ 16/32 bit registers, not byte adressable ----------
if((addr >= 5'h00) && (addr <= 5'h0f)) halftone_ram[addr] <= din;
if(addr == 5'h10) src_x_inc <= din[15:1];
if(addr == 5'h11) src_y_inc <= din[15:1];
if(addr == 5'h12) src_addr [23:16]<= din[7:0];
if(addr == 5'h13) src_addr [15:1]<= din[15:1];
if(addr == 5'h14) endmask1 <= din;
if(addr == 5'h15) endmask2 <= din;
if(addr == 5'h16) endmask3 <= din;
if(addr == 5'h17) dst_x_inc <= din[15:1];
if(addr == 5'h18) dst_y_inc <= din[15:1];
if(addr == 5'h19) dst_addr [23:16]<= din[7:0];
if(addr == 5'h1a) dst_addr [15:1]<= din[15:1];
if(addr == 5'h1b) begin
x_count <= din;
x_count_latch <= din; // x_count is latched to be reloaded at each end of line
end
if(addr == 5'h1c) y_count <= din;
// ------ 8 bit registers ----------
// uds -> even bytes via d15:d8
// lds -> odd bytes via d7:d0
if(addr == 5'h1d && ~uds) hop <= din[9:8];
if(addr == 5'h1d && ~lds) op <= din[3:0];
if(addr == 5'h1e && ~uds) begin
line_number <= din[11:8];
smudge <= din[13];
hog <= din[14];
busy <= din[15];
// writing busy with 1 starts the blitter
end
if(addr == 5'h1e && ~lds) begin
skew <= din[3:0];
nfsr <= din[6];
fxsr <= din[7];
end
end
end
end
// ----------------- blitter engine -------------------
always @(posedge clk32) begin
if(reset) begin
end else begin
end
end
// wire io = (bus_cycle[3:2] == 0); // blitter does io in cycle 0 which is the same one the cpu uses
// TODO: Also use bus cycle 2 to make a "turbo blitter" being twice as fast
// internal registers
reg [31:0] src; // 32 bit source read buffer
reg [15:0] dest; // 16 bit destination read buffer
// ------- wire up the blitter subcomponent combinatorics --------
wire [15:0] src_skewed;
wire [15:0] src_halftoned;
wire [15:0] result;
// select current halftone line
wire [15:0] halftone_line = halftone_ram[line_number];
// shift/select 16 bits of source
shift shift (
.skew (skew),
.in (src),
.out (src_skewed)
);
// apply halftone operation
halftone_op halftone_op (
.op (hop),
.in0 (halftone_line),
.in1 (src_skewed),
.out (src_halftoned)
);
// apply blitter operation
blitter_op blitter_op (
.op (op),
.in0 (src_halftoned),
.in1 (dest),
.out (result)
);
wire first_word_in_row = (x_count == x_count_latch);
wire last_word_in_row = (x_count == 16'h0001);
wire [15:0] data_to_write;
// apply masks
masking masking (
.endmask1 (endmask1),
.endmask2 (endmask2),
.endmask3 (endmask3),
.first (first_word_in_row),
.last (last_word_in_row),
.in0 (result),
.in1 (dest),
.out (data_to_write)
);
endmodule // blitter
// the blitter operations
module blitter_op (
input [3:0] op,
input [15:0] in0,
input [15:0] in1,
output reg [15:0] out
);
always @(op, in0, in1) begin
case(op)
0: out = 8'h00;
1: out = in0 & in1;
2: out = in0 & ~in1;
3: out = in0;
4: out = ~in0 & in1;
5: out = in1;
6: out = in0 ^ in1;
7: out = in0 | in1;
8: out = ~in0 & ~in1;
9: out = ~in0 ^ in1;
10: out = ~in1;
11: out = in0 | ~in1;
12: out = ~in0;
13: out = ~in0 | in1;
14: out = ~in0 | ~in1;
15: out = 8'hff;
endcase; // case (op)
end
endmodule // blitter_op
// the blitter barrel shifter
module shift (
input [3:0] skew,
input [31:0] in,
output reg [15:0] out
);
always @(skew, in) begin
out = 16'h00;
// out = in[skew+15:skew];
case(skew)
0: out = in[15:0];
1: out = in[16:1];
2: out = in[17:2];
3: out = in[18:3];
4: out = in[19:4];
5: out = in[20:5];
6: out = in[21:6];
7: out = in[22:7];
8: out = in[23:8];
9: out = in[24:9];
10: out = in[25:10];
11: out = in[26:11];
12: out = in[27:12];
13: out = in[28:13];
14: out = in[29:14];
15: out = in[30:15];
endcase; // case (skew)
end
endmodule // shift
// the halftone operations
module halftone_op (
input [1:0] op,
input [15:0] in0,
input [15:0] in1,
output reg [15:0] out
);
always @(op, in0, in1) begin
case(op)
0: out = 8'hff;
1: out = in0;
2: out = in1;
3: out = in0 & in1;
endcase; // case (op)
end
endmodule // halftone_op
// masking
module masking (
input [15:0] endmask1,
input [15:0] endmask2,
input [15:0] endmask3,
input first,
input last,
input [15:0] in0,
input [15:0] in1,
output reg [15:0] out
);
always @(endmask1, endmask2, endmask3, first, last, in0, in1) begin
// neither first nor last: endmask2
out = (in0 & endmask2) | (in1 & ~endmask2);
// first (last may also be applied): endmask1
if(first) out = (in0 & endmask1) | (in1 & ~endmask1);
// last and not first: endmask3
else if(last) out = (in0 & endmask3) | (in1 & ~endmask3);
end
endmodule // masking

View File

@@ -30,7 +30,7 @@ module dma (
// ------------- data_io (arm controller) interface ------
always @(dio_idx, base, scnt, fdc_cmd, fdc_track, fdc_sector,
fdc_data, drv_sel, drv_side, fdc_busy) begin
fdc_data, drv_sel, drv_side, fdc_busy, acsi_busy, acsi_target, acsi_cmd) begin
dio_data = 8'h00;
case (dio_idx)

View File

@@ -203,7 +203,9 @@ assign gpip_cpu_out = (gpip_in & ~ddr) | (gpip & ddr);
// cpu read interface
always @(iack, sel, ds, rw, addr, gpip_cpu_out, aer, ddr, ier, ipr, isr, imr,
vr, irq_vec) begin
vr, irq_vec, serial_data_out_fifo_full, timera_dat_o, timerb_dat_o,
timerc_dat_o, timerd_dat_o, timera_ctrl_o, timerb_ctrl_o, timerc_ctrl_o,
timerd_ctrl_o) begin
dout = 8'd0;
if(sel && ~ds && rw) begin

View File

@@ -464,6 +464,7 @@ set_global_assignment -name VERILOG_FILE mfp_timer.v
set_global_assignment -name VHDL_FILE vol_table_array.vhd
set_global_assignment -name VHDL_FILE YM2149_volmix.vhd
set_global_assignment -name VERILOG_FILE acia.v
set_global_assignment -name VERILOG_FILE blitter.v
set_global_assignment -name VHDL_FILE TG68K.vhd
set_global_assignment -name VHDL_FILE TG68K_ALU.vhd
set_global_assignment -name VHDL_FILE TG68K_Pack.vhd

View File

@@ -52,7 +52,7 @@ wire [1:0] buttons;
// generate dtack for all implemented peripherals
wire io_dtack = vreg_sel || mmu_sel || mfp_sel || mfp_iack ||
acia_sel || psg_sel || dma_sel || auto_iack;
acia_sel || psg_sel || dma_sel || auto_iack || blitter_sel;
// the original tg68k did not contain working support for bus fault exceptions. While earlier
// TOS versions cope with that, TOS versions with blitter support need this to work as this is
@@ -160,6 +160,11 @@ wire [7:0] mfp_data_out;
wire acia_sel = io_sel && ({tg68_adr[15:8], 8'd0} == 16'hfc00);
wire [7:0] acia_data_out;
// blitter 16 bit interface at $ff8a00 - $ff8a3f
// wire blitter_sel = io_sel && ({tg68_adr[15:8], 8'd0} == 16'h8a00);
wire blitter_sel = 1'b0;
wire [15:0] blitter_data_out;
// psg 8 bit interface at $ff8800 - $ff8803
wire psg_sel = io_sel && ({tg68_adr[15:8], 8'd0} == 16'h8800);
wire [7:0] psg_data_out;
@@ -171,7 +176,7 @@ wire [15:0] dma_data_out;
// de-multiplex the various io data output ports into one
wire [7:0] io_data_out_8u = acia_data_out | psg_data_out;
wire [7:0] io_data_out_8l = mmu_data_out | mfp_data_out | auto_vector;
wire [15:0] io_data_out = vreg_data_out | dma_data_out |
wire [15:0] io_data_out = vreg_data_out | dma_data_out | blitter_data_out |
{8'h00, io_data_out_8l} | {io_data_out_8u, 8'h00};
wire init = ~pll_locked;
@@ -276,6 +281,20 @@ acia acia (
.ikbd_data_in (ikbd_data_to_acia)
);
blitter blitter (
// cpu interface
.clk (clk_8 ),
.reset (reset ),
.din (tg68_dat_out ),
.sel (blitter_sel ),
.addr (tg68_adr[5:1] ),
.uds (tg68_uds ),
.lds (tg68_uds ),
.rw (tg68_rw ),
.dout (blitter_data_out ),
.irq ( )
);
//// ym2149 sound chip ////
reg [1:0] sclk;

View File

@@ -11,7 +11,7 @@ module mmu (
reg [7:0] memconfig;
always @(sel, ds, rw) begin
always @(sel, ds, rw, memconfig) begin
dout = 8'd0;
if(sel && ~ds && rw)
dout = memconfig;

View File

@@ -199,7 +199,7 @@ reg [2:0] palette_r[15:0];
reg [2:0] palette_g[15:0];
reg [2:0] palette_b[15:0];
always @(reg_sel, reg_rw, reg_uds, reg_lds, reg_addr, _v_bas_ad, shmode, vaddr) begin
always @(reg_sel, reg_rw, reg_uds, reg_lds, reg_addr, _v_bas_ad, shmode, vaddr, syncmode) begin
reg_dout = 16'h0000;
// read registers