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:
@@ -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
324
cores/mist/blitter.v
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user