1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-13 15:17:39 +00:00

Viking/SM194 support

This commit is contained in:
harbaum 2014-04-30 18:29:04 +00:00
parent 5ddcb6fc37
commit 0f686abc5a
7 changed files with 330 additions and 17 deletions

93
cores/mist/io_fifo.v Normal file
View File

@ -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 <till@harbaum.org>
// 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 <http://www.gnu.org/licenses/>.
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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 ),

155
cores/mist/viking.v Normal file
View File

@ -0,0 +1,155 @@
//
// viking.v
//
// Atari ST(E) Viking/SM194
// http://code.google.com/p/mist-board/
//
// Copyright (c) 2013 Till Harbaum <till@harbaum.org>
// 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 <http://www.gnu.org/licenses/>.
// 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

BIN
tools/mist_vhi.st Normal file

Binary file not shown.