From 0f686abc5ab7d627cbc4b5f802c3012a1b68e3cc Mon Sep 17 00:00:00 2001 From: harbaum Date: Wed, 30 Apr 2014 18:29:04 +0000 Subject: [PATCH] Viking/SM194 support --- cores/mist/io_fifo.v | 93 +++++++++++++++++++++++++ cores/mist/mist.qsf | 2 + cores/mist/mist_top.v | 89 ++++++++++++++++++++---- cores/mist/osd.v | 3 +- cores/mist/video.v | 5 +- cores/mist/viking.v | 155 ++++++++++++++++++++++++++++++++++++++++++ tools/mist_vhi.st | Bin 0 -> 737280 bytes 7 files changed, 330 insertions(+), 17 deletions(-) create mode 100644 cores/mist/io_fifo.v create mode 100644 cores/mist/viking.v create mode 100644 tools/mist_vhi.st diff --git a/cores/mist/io_fifo.v b/cores/mist/io_fifo.v new file mode 100644 index 0000000..a3dbc45 --- /dev/null +++ b/cores/mist/io_fifo.v @@ -0,0 +1,93 @@ +// +// io_fifo.v +// +// Atari ST(E) io controller FIFO for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2013 Till Harbaum +// Modified by Juan Carlos González Amestoy. +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +module io_fifo #( + parameter DATA_WIDTH = 8, + parameter DEPTH = 4 +)( + input reset, + + input [DATA_WIDTH-1:0] in, + input in_clk, + input in_strobe, + input in_enable, + + input out_clk, + output [DATA_WIDTH-1:0] out, + input out_strobe, + input out_enable, + + output empty, + output data_available, + output full +); + +localparam FIFO_ADDR_BITS = DEPTH; +localparam FIFO_DEPTH = (1 << FIFO_ADDR_BITS); + +reg [DATA_WIDTH-1:0] fifo [FIFO_DEPTH-1:0]; +reg [FIFO_ADDR_BITS-1:0] writeP, readP; + +assign full = (readP == (writeP + 1)); +assign empty = (readP == writeP); +assign data_available = (readP != writeP); + +// the strobes may not be in the right clock domain, so bring them into the +// local clock domain +reg in_strobeD, in_strobeD2; +reg out_strobeD, out_strobeD2; + +// present current value. If fifo is empty show last value +assign out = data_available?fifo[readP]:fifo[readP-1]; + +always @(posedge out_clk) begin + // bring strobes in local clock domain + out_strobeD <= out_strobe; + out_strobeD2 <= out_strobeD; + + if(reset) + readP <= 0; + else begin + // rising edge on fifo read strobe from io controller + if((out_strobeD && !out_strobeD2) || out_enable) + readP <= readP + 1; + end +end + +always @(posedge in_clk) begin + // bring strobes in local clock domain + in_strobeD <= in_strobe; + in_strobeD2 <= in_strobeD; + + if(reset) + writeP <= 0; + else begin + // rising edge on strobe signal causes write + // or in_enable being true + if((in_strobeD && !in_strobeD2) || in_enable) begin + fifo[writeP] <= in; + writeP <= writeP + 1; + end + end +end + +endmodule \ No newline at end of file diff --git a/cores/mist/mist.qsf b/cores/mist/mist.qsf index 16a82e2..2e54cee 100644 --- a/cores/mist/mist.qsf +++ b/cores/mist/mist.qsf @@ -323,7 +323,9 @@ set_global_assignment -name VERILOG_FILE clock.v set_global_assignment -name VERILOG_FILE mist_top.v set_global_assignment -name VERILOG_FILE user_io.v set_global_assignment -name VERILOG_FILE video.v +set_global_assignment -name VERILOG_FILE viking.v set_global_assignment -name VERILOG_FILE video_modes.v +set_global_assignment -name VERILOG_FILE io_fifo.v set_global_assignment -name VERILOG_FILE osd.v set_global_assignment -name VERILOG_FILE data_io.v set_global_assignment -name VERILOG_FILE mfp.v diff --git a/cores/mist/mist_top.v b/cores/mist/mist_top.v index 2f9fd41..43053e6 100644 --- a/cores/mist/mist_top.v +++ b/cores/mist/mist_top.v @@ -46,6 +46,8 @@ wire ste = system_ctrl[23] || system_ctrl[24]; wire mste = system_ctrl[24]; wire steroids = system_ctrl[23] && system_ctrl[24]; // a STE on steroids +// ethernec is enabled by the io controller whenever a USB +// ethernet interface is detected wire ethernec_present = system_ctrl[25]; // usb target port on io controller is used for redirection of @@ -213,6 +215,60 @@ wire [15:0] io_data_out = vreg_data_out | dma_data_out | blitter_data_out | wire init = ~pll_locked; +/* -------------------------- Viking video card -------------------- */ + +// viking/sm194 is enabled and max 8MB memory may be enabled +wire viking_mem_ok = MEM512K || MEM1M || MEM2M || MEM4M || MEM8M; +wire viking_enable = system_ctrl[28] && viking_mem_ok; + +// check for cpu access to 0xcxxxxx with viking enabled to switch video +// output once the driver loads +reg viking_in_use; +always @(negedge clk_128) begin + if(reset) + viking_in_use <= 1'b0; + else + if(clkena && viking_enable && (tg68_adr[23:18] == 6'b110000)) + viking_in_use <= 1'b1; +end + +// video output multiplexer to switch between shifter and viking +wire viking_active = viking_in_use && !osd_enable; +assign VGA_HS = viking_active?viking_hs:shifter_hs; +assign VGA_VS = viking_active?viking_vs:shifter_vs; +assign VGA_R = viking_active?viking_r:shifter_r; +assign VGA_G = viking_active?viking_g:shifter_g; +assign VGA_B = viking_active?viking_b:shifter_b; + +wire viking_hs, viking_vs; +wire [5:0] viking_r, viking_g, viking_b; + +wire [22:0] viking_address; +wire viking_read; + +viking viking ( + .reset (reset ), + .pclk (clk_128 ), // pixel + .bus_cycle (bus_cycle ), + + // memory interface + .bclk (clk_8 ), // system bus clock = 8Mhz + .addr (viking_address ), + .data (ram_data_out_64), + .read (viking_read ), + + // video output + .hs (viking_hs ), + .vs (viking_vs ), + .r (viking_r ), + .g (viking_g ), + .b (viking_b ) +); + +wire osd_enable; +wire shifter_hs, shifter_vs; +wire [5:0] shifter_r, shifter_g, shifter_b; + video video ( .clk (clk_32 ), .clk27 (CLOCK_27[0]), @@ -222,6 +278,7 @@ video video ( .sdi (SPI_DI ), .sck (SPI_SCK ), .ss (SPI_SS3 ), + .osd_enable (osd_enable ), // cpu register interface .reg_clk (clk_8 ), @@ -238,11 +295,11 @@ video video ( .data (ram_data_out_64), .read (video_read ), - .hs (VGA_HS ), - .vs (VGA_VS ), - .video_r (VGA_R ), - .video_g (VGA_G ), - .video_b (VGA_B ), + .hs (shifter_hs ), + .vs (shifter_vs ), + .video_r (shifter_r ), + .video_g (shifter_g ), + .video_b (shifter_b ), // configuration signals .adjust (video_adj ), @@ -955,14 +1012,16 @@ wire MEM14M = (system_ctrl[3:1] == 3'd5); // rom is also at 0x000000 to 0x000007 wire cpu2lowrom = (tg68_adr[23:3] == 21'd0); - + // 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 - (steroids && (tg68_adr[23:19] == 5'b11101))); // 512k at $e80000 for STEroids + (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 + (viking_enable && (tg68_adr[23:18] == 6'b110000)) // 256k at 0xc00000 for viking card +); // 256k tos from 0xe00000 to 0xe40000 wire cpu2tos256k = (tg68_adr[23:18] == 6'b111000); @@ -1001,23 +1060,23 @@ wire second_cpu_slot = (mste && enable_16mhz) || steroids; // cpu, DMA and Blitter. A third is optionally being used for faster CPU wire video_cycle = (bus_cycle == 0); wire cpu_cycle = (bus_cycle == 1) || (second_cpu_slot && (bus_cycle == 3)); +wire viking_cycle = (bus_cycle == 2); // ----------------- RAM address -------------- wire [22:0] video_cycle_addr = (st_hs && ste)?ste_dma_snd_addr:video_address; wire [22:0] cpu_cycle_addr = data_io_br?data_io_addr:(blitter_br?blitter_master_addr:tg68_adr[23:1]); -wire [22:0] ram_address = video_cycle?video_cycle_addr:cpu_cycle_addr; +wire [22:0] ram_address = viking_cycle?viking_address:(video_cycle?video_cycle_addr:cpu_cycle_addr); // ----------------- RAM read ----------------- // memory access during the video cycle is shared between video and ste_dma_snd wire video_cycle_oe = (st_hs && ste)?ste_dma_snd_read:video_read; // memory access during the cpu cycle is shared between blitter and cpu wire cpu_cycle_oe = data_io_br?data_io_read:(blitter_br?blitter_master_read:(cpu_cycle && tg68_as && tg68_rw && cpu2mem)); -wire ram_oe = video_cycle?video_cycle_oe:(cpu_cycle?cpu_cycle_oe:1'b0); +wire ram_oe = viking_cycle?viking_read:(video_cycle?video_cycle_oe:(cpu_cycle?cpu_cycle_oe:1'b0)); // ----------------- RAM write ----------------- -wire video_cycle_wr = 1'b0; wire cpu_cycle_wr = data_io_br?data_io_write:(blitter_br?blitter_master_write:(cpu_cycle && tg68_as && ~tg68_rw && cpu2ram)); -wire ram_wr = video_cycle?video_cycle_wr:(cpu_cycle?cpu_cycle_wr:1'b0); +wire ram_wr = (viking_cycle||video_cycle)?1'b0:(cpu_cycle?cpu_cycle_wr:1'b0); wire [15:0] ram_data_out; wire [15:0] system_data_out = cpu2mem?ram_data_out:io_data_out; diff --git a/cores/mist/osd.v b/cores/mist/osd.v index a679ebb..0cd0970 100644 --- a/cores/mist/osd.v +++ b/cores/mist/osd.v @@ -28,6 +28,8 @@ module osd ( input ss, input sdi, + output reg osd_enable, + // current video beam position input [9:0] hcnt, input [9:0] vcnt, @@ -57,7 +59,6 @@ reg [7:0] cmd; reg [4:0] cnt; reg [10:0] bcnt; -reg osd_enable; reg [7:0] osd_buffer [2047:0]; // the OSD buffer itself // the OSD has its own SPI interface to the io controller diff --git a/cores/mist/video.v b/cores/mist/video.v index 20dca83..c013a8c 100644 --- a/cores/mist/video.v +++ b/cores/mist/video.v @@ -59,7 +59,8 @@ module video ( input [1:0] scanlines, // scanlines (00-none 01-25% 10-50% 11-100%) input [15:0] adjust, // hor/ver video adjust input ste, // enable STE featurss - + output osd_enable, + // signals not affected by scan doubler for internal use like irqs output st_de, output reg st_vs, @@ -374,6 +375,8 @@ osd osd ( .sdi (sdi ), .sck (sck ), .ss (ss ), + + .osd_enable (osd_enable ), // feed ST video signal into OSD .clk (clk ), diff --git a/cores/mist/viking.v b/cores/mist/viking.v new file mode 100644 index 0000000..674cf00 --- /dev/null +++ b/cores/mist/viking.v @@ -0,0 +1,155 @@ +// +// viking.v +// +// Atari ST(E) Viking/SM194 +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2013 Till Harbaum +// Modified by Juan Carlos González Amestoy. +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// The viking card does not have its own CPU interface as it is not +// configurable in any way. It just etches data from ram and displays +// it on screen. + +module viking ( + input reset, + input pclk, // 128 MHz pixel clock + + // memory interface + input bclk, // 8 MHz bus clock + input [1:0] bus_cycle, // bus-cycle for bus access sync + output reg [22:0] addr, // video word address + output read, // video read cycle + input [63:0] data, // video data read + + // VGA output (multiplexed with sm124 output in top level) + output hs, + output vs, + output [5:0] r, + output [5:0] g, + output [5:0] b +); + +localparam BASE = 23'h600000; // c00000 + +// total width must be multiple of 64, so video runs synchronous +// to main bus + +// Horizontal timing +// HBP1 | H | HFP | HS | HBP2 +// -----|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|-----|____|----- +// HBP1 is used for prefetch + +// 1280x +localparam H = 1280; +localparam HFP = 88; +localparam HS = 136; +localparam HBP1 = 32; +localparam HBP2 = 192; + +// Vertical timing +// V | VFP | VS | VBP +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|-----|____|----- + +// x1024 +localparam V = 1024; +localparam VFP = 9; +localparam VS = 4; +localparam VBP = 9; + +assign read = (bus_cycle == 2) && me; // memory enable can directly be used as a ram read signal + +// --------------------------------------------------------------------------- +// --------------------------- internal state counter ------------------------ +// --------------------------------------------------------------------------- + +reg [3:0] t /* synthesis noprune */; +always @(posedge pclk) begin + // 128 Mhz counter synchronous to 8 Mhz clock + // force counter to pass state 0 exactly after the rising edge of clk_reg (8Mhz) + if(((t == 4'd15) && ( bclk == 0)) || + ((t == 4'd0) && ( bclk == 1)) || + ((t != 4'd15) && (t != 4'd0))) + t <= t + 4'd1; +end + +// create internal bus_cycle signal which is stable on the positive clock +// edge and extends the previous state by half a 128 Mhz clock cycle +reg [5:0] bus_cycle_L /* synthesis noprune */ ; +always @(negedge pclk) + bus_cycle_L <= { bus_cycle, t }; + + +// --------------- horizontal timing ------------- +reg[10:0] h_cnt; // 0..2047 +assign hs = ((h_cnt >= HBP1+H+HFP) && (h_cnt < HBP1+H+HFP+HS))?0:1; +always@(posedge pclk) begin + if(h_cnt==HBP1+H+HFP+HS+HBP2-1) begin + // make sure a line starts with the "viking" bus cyle (2) + // shifter has cycle 0, cpu has cycles 1 and 3 + if(bus_cycle_L == { 2'd1, 4'd15 }) + h_cnt<=0; + end else + h_cnt <= h_cnt + 1; +end + +// --------------- vertical timing ------------- +reg[10:0] v_cnt; // 0..2047 +assign vs = ((v_cnt >= V+VFP) && (v_cnt < V+VFP+VS))?0:1; +always@(posedge pclk) begin + if(h_cnt==HBP1+H+HFP+HS+HBP2-1) begin + if(v_cnt==V+VFP+VS+VBP-1) v_cnt <= 0; + else v_cnt <= v_cnt+1; + end +end + +// reorder words 1:2:3:4 -> 4:3:2:1 +wire [63:0] data_reorder = { data[15:0], data[31:16], data[47:32], data[63:48] }; + +reg [63:0] input_latch; +reg [63:0] shift_register; + +// ---------------- memory timing ---------------- +always@(posedge pclk) begin + // last line on screen + if(v_cnt == V+VFP+VS+VBP-2) + addr <= BASE; + else if(me && bus_cycle_L == 6'h30) // directly after read + addr <= addr + 23'd4; // advance 4 words (64 bits) + + if(me && (bus_cycle_L == 6'h2f)) + input_latch <= data_reorder; + + if(bus_cycle_L == 6'h3f) + shift_register <= input_latch; + else + shift_register[63:1] <= shift_register[62:0]; +end + +// memory enable (data is being read from memory) +wire me = (v_cnt < V)&&(h_cnt < H) /* synthesis keep */; +// display enable (data is being displayed) +wire de = (v_cnt < V)&&(h_cnt >= HBP1)&&(h_cnt < HBP1+H) /* synthesis keep */; + +wire pix = de?(!shift_register[63]):1'b0; + +// drive all 18 rgb bits from the data bit +wire [5:0] pix6 = { pix, pix, pix, pix, pix, pix }; +assign r = pix6; +assign g = pix6; +assign b = pix6; + +endmodule diff --git a/tools/mist_vhi.st b/tools/mist_vhi.st new file mode 100644 index 0000000000000000000000000000000000000000..7a4a93a6980086501228d2920dbaaccdefe82466 GIT binary patch literal 737280 zcmeI&PiWiM9RTnrSuT#Mq)90qG-EtFUD#kamKR0{VyTprsloZhv%PGGz^o*SEn-`q zWQ97IF-9r5rIa2^2b)N@% zfArq>``-IVVE>Fi4B1Y3^X2(aEEYm>J=_}oWHjsv#h`rk1wP4#<*R>BHzYuS009C7 z2oSg@;P*e@1OfyI5FkK+!2g#({YMLD+}c^ z`0o=~d@6*ISHJjNi=pt$Pa1Re)vL>$;fm%5Vf*%0=wB|!`owJIhoP`kp83;AIC4CH zKO0Oehf;cP&)VNkKR9}dV>gsizEEhq zbUhh`G+)i?JMGT8q14C=528|A$m$C>QX7VCJQl_#9vi=#;?}@zjgQN|U$m z3`gB3huKHInGGiEJ2Poid@CCq`Z!!qN2&~C!~SqRjo(PUKkkg*3vV2_8;Yfw^^gsk zn<@J%X~)A^cK${>bMHhg&yS?nupaJ_=0>yZ>_0-~Ryg!_T77(?6UGkxI`zIk-U&1L zU#p#PIRAU9pUyu@^=$sn^nNq{cPo7Mo$;+*CK--W`MC zDGok+a6QH|o%w}Wojx}8e06I2Xgt@s)b7Spz0TEkFUEsE+gpxr#_6f*(Rg7qE_7B_ zVzbq|&>F0!pJ#i^;n}&lvvbE|){R$p0$1Cs-QH%r+#Rf4nvAn6?N+}XS6f%wu|Mdw z_m({FEVq;>uA-7OZn-MBiqxE#}Q zd#%+6ai4F}YhM~%Ogr44-sr|-XBx5Fi!1GZ|3UWtW`Co-8Xr#I>}