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

Video/shifter closer to original ST timing. User adjustable video centering

This commit is contained in:
harbaum
2013-10-01 08:32:38 +00:00
parent 0115333c67
commit 1170810028
4 changed files with 204 additions and 156 deletions

View File

@@ -1,4 +1,5 @@
// SPI data client (rom, floppy, harddisk io)
module data_io (
// clocks
input clk_8,
@@ -16,8 +17,10 @@ module data_io (
output [4:0] dma_idx,
input [7:0] dma_data,
output reg dma_ack,
output reg br,
// horizontal and vertical screen adjustments
output reg [15:0] video_adj,
// ram interface
output reg [2:0] state, // state bits required to drive the sdram host
@@ -160,11 +163,15 @@ always@(posedge sck, posedge ss) begin
// set control register (32 bits written in 2 * 16 bits)
if((cmd == 4) && (cnt == 5'd23)) begin
if(bcnt < 2)
ctrl_out[31:16] <= { sbuf, sdi };
else
ctrl_out[15:0] <= { sbuf, sdi };
if(bcnt < 2)
ctrl_out[31:16] <= { sbuf, sdi };
else
ctrl_out[15:0] <= { sbuf, sdi };
end
// set video offsets
if((cmd == 9) && (cnt == 5'd23))
video_adj <= { sbuf, sdi };
end
end
end

View File

@@ -45,7 +45,8 @@ module mist_top (
wire [15:0] video_data;
wire video_read;
wire [22:0] video_address;
wire video_de, video_hs;
wire st_de, st_hs, st_vs;
wire [15:0] video_adj;
// on-board io
wire [1:0] buttons;
@@ -180,7 +181,6 @@ wire [15:0] io_data_out = vreg_data_out | dma_data_out | blitter_data_out |
wire init = ~pll_locked;
video video (
.reset (init ), // reset input
.clk (clk_32 ),
.clk27 (CLOCK_27[0]),
.bus_cycle (bus_cycle ),
@@ -207,15 +207,19 @@ video video (
.hs (VGA_HS ),
.vs (VGA_VS ),
.video_r (VGA_R ),
.video_g (VGA_G ),
.video_b (VGA_B ),
.video_r (VGA_R ),
.video_g (VGA_G ),
.video_b (VGA_B ),
.adjust (video_adj ),
.pal56 (~system_ctrl[9]),
.scanlines (system_ctrl[21:20]),
.hsO (video_hs ),
.deO (video_de )
// signals not affected by scan doubler required for
// irq generation
.st_hs (st_hs ),
.st_vs (st_vs ),
.st_de (st_de )
);
mmu mmu (
@@ -251,7 +255,7 @@ mfp mfp (
// input signals
.clk_ext (clk_mfp ),
.de (video_de ),
.de (st_de ),
.dma_irq (dma_irq ),
.acia_irq (acia_irq ),
.blitter_irq (blitter_irq ),
@@ -354,10 +358,11 @@ YM2149 ym2149 (
.I_BC1 ( psg_sel && !tg68_adr[1]),
.I_SEL_L ( 1'b1 ),
.O_AUDIO_L (audio_out_l),
.O_AUDIO_R (audio_out_r),
.O_AUDIO_L (audio_out_l ),
.O_AUDIO_R (audio_out_r ),
.stereo (system_ctrl[29]),
.stereo (system_ctrl[22] ),
// port a
.I_IOA ( 8'd0 ),
.O_IOA ( port_a_out ),
@@ -506,7 +511,7 @@ assign vbi_ack = cpu2iack && address_strobe && (tg68_adr[3:1] == 3'b100);
reg vsD, vsD2, vsI, vbi;
always @(negedge clk_8)
vsD <= VGA_VS;
vsD <= st_vs;
always @(posedge clk_8) begin
vsD2 <= vsD; // delay by one
@@ -524,7 +529,7 @@ assign hbi_ack = cpu2iack && address_strobe && (tg68_adr[3:1] == 3'b010);
reg hsD, hsD2, hsI, hbi;
always @(negedge clk_8)
hsD <= video_hs;
hsD <= st_hs;
always @(posedge clk_8) begin
hsD2 <= hsD; // delay by one
@@ -771,12 +776,13 @@ data_io data_io (
.ss (SPI_SS2 ),
.sdo (data_io_sdo ),
.br (data_io_br ),
.video_adj (video_adj ),
// dma status interface
.dma_idx (dma_dio_idx ),
.dma_data (dma_dio_data ),
.dma_ack (dma_dio_ack ),
.br (data_io_br ),
// ram interface
.state (host_state ),

View File

@@ -1,5 +1,5 @@
//
// video.v - new version
// video.v
//
// Atari ST shifter implementation for the MiST board
// http://code.google.com/p/mist-board/
@@ -20,33 +20,19 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// original atari video timing
// mono color
// pclk 32MHz 16/8MHz
// hfreq 35.7kHz 15.75kHz
// vfreq 71.2Hz 50/60Hz
//
// avg. values derived from frequencies:
// hdisp 640 640/320
// htot 896 1015/507
// vdisp 400 200
// vtot 501 315/262
// TODO:
// - async timing
// Overscan:
// http://codercorner.com/fullscrn.txt
// Examples: automation 000 + 001: bottom border
// automation 097: top+ bottom border
// Examples: automation 000 + 001 + 097: bottom border
// automation 196: top + bottom border
module video (
// system interface
input clk, // 31.875 MHz
input clk27, // 27.000 Mhz
input reset, // reset
input [3:0] bus_cycle, // bus-cycle for sync
// SPI interface for OSD
@@ -78,25 +64,34 @@ module video (
output reg [5:0] video_b, // Blue[5:0]
// system config
input pal56, // use VGA compatible 56hz for PAL
input [1:0] scanlines, // scanlines (00-none 01-25% 10-50% 11-100%)
input pal56, // use VGA compatible 56hz for PAL
input [1:0] scanlines, // scanlines (00-none 01-25% 10-50% 11-100%)
input [15:0] adjust, // hor/ver video adjust
// for internal use
output deO,
output hsO
// signals not affected by scan doubler for internal use like irqs
output st_de,
output st_vs,
output st_hs
);
localparam LINE_WIDTH = 10'd640;
localparam LINE_BORDER = 10'd80; // width of left and right screen border
// ---------------------------------------------------------------------------
// ------------------------------ internal signals ---------------------------
// ---------------------------------------------------------------------------
// deO is the internal display enable signal as used by the mfp. This is used
// st_de is the internal display enable signal as used by the mfp. This is used
// by software to generate a line interrupt and to e.g. do 512 color effects.
// deO is active low
assign deO = ~me; // ~(scan_doubler_enable?sd_de:de);
// st_de is active low. Using memory enable (me) for this makes sure the cpu has
// plenty of time before data for the next line is starting to be fetched
assign st_de = ~me;
// similar for hsync
assign hsO = (st_h_state == 2'd0);
// hsync irq is generated at the rising edge of st_hs
assign st_hs = (st_h_state == 2'd0);
// vsync irq is generated at the rising edge of st_vs
assign st_vs = (v_state == 2'd0);
// ---------------------------------------------------------------------------
// -------------------------------- video mode -------------------------------
@@ -154,11 +149,6 @@ wire low = (shmode == 2'd0);
// derive number of planes from shiftmode
wire [2:0] planes = mono?3'd1:(mid?3'd2:3'd4);
// scandoubler is used for the mid and low rez mode
wire scan_doubler_enable = mid || low;
// line buffer for two lines of 640 pixels rgb data
reg [8:0] sd_buffer [1279:0];
reg [1:0] syncmode;
reg [1:0] syncmode_latch;
@@ -302,10 +292,10 @@ wire [2:0] mono_rgb = de?{mono_bit, mono_bit, mono_bit}:3'b100;
// ------------------------- colour video signal -----------------------------
reg [8:0] color, border_color;
wire [2:0] color_r = de?color[8:6]:border_color[8:6];
wire [2:0] color_g = de?color[5:3]:border_color[5:3];
wire [2:0] color_b = de?color[2:0]:border_color[2:0];
reg [8:0] color;
wire [2:0] color_r = color[8:6];
wire [2:0] color_g = color[5:3];
wire [2:0] color_b = color[2:0];
// --------------- de-multiplex color and mono into one vga signal -----------
wire [2:0] stvid_r = mono?mono_rgb:color_r;
@@ -316,19 +306,21 @@ wire [2:0] stvid_b = mono?mono_rgb:color_b;
reg [15:0] shift_0, shift_1, shift_2, shift_3;
// this line is to be displayed darker in scanline mode
wire scanline = scan_doubler_enable && vcnt[0];
wire scanline = scan_doubler_enable && sd_vcnt[0];
// reading the scan doubler ram results in one extra delay and thus
// reading it has to look one vga_hcnt cycle into the future
wire [9:0] vga_hcnt_next = (vga_hcnt == t5_h_end)?10'd0:(vga_hcnt+10'd1);
wire [9:0] border_width = t5_h_end - t4_h_border_left;
wire [9:0] vga_hcnt_next =
(vga_hcnt == t5_h_end)?(t5_h_end - t4_h_border_left):
((vga_hcnt >= t4_h_border_left)?(vga_hcnt-t4_h_border_left):(vga_hcnt+LINE_BORDER+10'd1));
always @(posedge clk) begin
hs <= h_sync_pol ^ ((vga_h_state == 2'd0)?1'b0:1'b1);
vs <= v_sync_pol ^ ((v_state == 2'd0)?1'b0:1'b1);
hs <= h_sync_pol ^ ~vga_h_sync;
vs <= v_sync_pol ^ ~vga_v_sync;
// color data is permanently read from the scan doubler buffers
color <= sd_buffer[{vga_hcnt_next, !sd_toggle}];
border_color <= sd_border_color[!sd_toggle];
// drive video output and apply scanline effect if enabled
if(!scanline || scanlines == 2'b00) begin //if no scanlines or not a scanline
@@ -402,26 +394,41 @@ end
// ------------------------------- scan doubler ------------------------------
// ---------------------------------------------------------------------------
// scandoubler is used for the mid and low rez mode
wire scan_doubler_enable = mid || low;
// scan doubler signale indicating first or second buffer used
wire sd_toggle = vcnt[1];
wire sd_toggle = sd_vcnt[1];
// four scan doubler shift registers for up to 4 planes
reg [15:0] sd_shift_0, sd_shift_1, sd_shift_2, sd_shift_3;
// register to save the border color for delayed output through scan doubler
reg [8:0] sd_border_color[2];
// msb of the shift registers is the index used to access the palette registers.
// Return border color index (0) if outside display area
wire [3:0] sd_index = (!me_v)?4'd0:
{ sd_shift_3[15], sd_shift_2[15], sd_shift_1[15], sd_shift_0[15]};
// msb of the shift registers is the index used to access the palette registers
wire [3:0] sd_index = { sd_shift_3[15], sd_shift_2[15],
sd_shift_1[15], sd_shift_0[15]};
// line buffer for two lines of 720 pixels (640 + 2 * 40 border) 3 * 3 bit rgb data
reg [8:0] sd_buffer [(2*(LINE_WIDTH+2*LINE_BORDER))-1:0];
// the scan doubler needs to know which border (left or right) is currently being displayed
reg sd_border_side;
// line counter used to create scan doubler states
reg [1:0] sd_vcnt;
always @(posedge clk) begin
// save border color to cope with only line delay imposed by scan doubler
if(st_hcnt == t4_h_border_left)
sd_border_color[sd_toggle] <= {palette_r[0], palette_g[0], palette_b[0]};
// permanently move data from data_latch into scan doublers shift registers
// vertical state changes at end of hsync (begin of left blank)
if(vga_hcnt == v_event) begin
// reset state counter two vga lines before screen start since scan doubler
// starts prefetching data two vga lines before
if(vcnt == (t11_v_end-10'd2)) sd_vcnt <= 2'd0;
else sd_vcnt <= sd_vcnt + 2'd1;
end
// permanently move data from data_latch into scan doublers shift registers
if((bus_cycle == 4'd15) && (plane == 2'd0)) begin
// clear shift registers since some of them may be unused and need to forced to 0
sd_shift_1 <= 16'h0000;
@@ -447,10 +454,31 @@ always @(posedge clk) begin
end
end
// move data from input buffer into line buffer
if((st_h_state == 2'd3) && (vga_hcnt[0] == 1'b0)) begin
sd_buffer[{st_hcnt[9:0], sd_toggle}] <=
{palette_r[sd_index], palette_g[sd_index], palette_b[sd_index]};
// to store border colors we need to know which border we currently draw
if(st_hcnt == t4_h_border_left) sd_border_side <= 1'b0;
if(st_hcnt == t0_h_border_right) sd_border_side <= 1'b1;
// scan doubler makes the st side operate at half the vga pixel clock
if(vga_hcnt[0] == 1'b0) begin
// move data from shift register into line buffer. capture border colors as
// well to have the scan doubler delay in the border colors as well just in
// case a program changes border colors dynamically (e.g. different colors
// for left and right or top and bottom borders)
if(st_h_state == 2'd3) begin
sd_buffer[{LINE_BORDER + st_hcnt[9:0], sd_toggle}] <=
{palette_r[sd_index], palette_g[sd_index], palette_b[sd_index]};
end else if(st_h_state == 2'd2) begin
// move bites from left/right border into appropriate places in the line buffer
if(!sd_border_side)
// left border
sd_buffer[{st_hcnt[9:0] - t4_h_border_left-10'd1, sd_toggle}] <=
{palette_r[0], palette_g[0], palette_b[0]};
else
// right border
sd_buffer[{st_hcnt[9:0] + LINE_BORDER, sd_toggle}] <=
{palette_r[0], palette_g[0], palette_b[0]};
end
end
end
@@ -488,7 +516,8 @@ always @(posedge clk) begin
end
// memory enable signal 16/32/64 bits (16*planes) ahead of display enable (de)
if(me_v) begin
// include bus cycle to stay in sync in scna doubler mode
if(me_v && bus_cycle[0]) begin
if(st_hcnt == me_h_start) me <= 1'b1;
if(st_hcnt == me_h_end) me <= 1'b0;
end
@@ -497,10 +526,8 @@ always @(posedge clk) begin
if(st_hcnt == me_h_start)
plane <= 2'd0;
// starting new image at left/top start of (vga) border, this doesn't matter
// and is easier than coping with the differnt resultions of the st video
// modes
if((vga_hcnt == t4_h_border_left) && (vcnt == t10_v_border_top)) begin
// The video address counter is reloaded slightly before vsync
if((vga_hcnt == t4_h_border_left) && (vcnt == t8_v_sync - 10'd3)) begin
vaddr <= _v_bas_ad;
// copy syncmode
@@ -549,64 +576,72 @@ reg [1:0] v_state; // 0=sync, 1=blank, 2=border, 3=display
wire blank = (v_state == 2'd1) || (vga_h_state == 2'd1) || (v_state == 2'd0) || (vga_h_state == 2'd0);
wire de = (v_state == 2'd3) && (vga_h_state == 2'd3);
wire border =
((v_state == 2'd2) && ((vga_h_state == 2'd3) || (vga_h_state == 2'd2)) || // top/bottom border
(vga_h_state == 2'd2) && ((v_state == 2'd3) || (v_state == 2'd2))); // left/right border
// time in horizontal timing where vertical states change (at the begin of the sync phase)
wire [9:0] v_event = t2_h_sync;
// time in horizontal timing where vertical states change (at the begin of the left blank phase)
wire [9:0] v_event = t3_h_blank_left;
// extend adjust values to 10 bits
wire [9:0] adjust_v = { adjust[7], adjust[7], adjust[7:0] };
wire [9:0] adjust_h = { adjust[15], adjust[15], adjust[15:8] };
reg vga_v_sync, vga_h_sync;
always @(posedge clk) begin
if(reset) begin
// It is important to reset the vga_hcnt counter here and this way (using reset which is the
// plls init signal). This is necessary to keep the video states in sync with the cpus memory
// timing.
vga_hcnt <= 10'd0;
vcnt <= 10'd0;
end else begin
// ------------- horizontal VGA timing generation -------------
if(vga_hcnt == t5_h_end) vga_hcnt <= 10'd0;
else vga_hcnt <= vga_hcnt + 10'd1;
// ------------- horizontal VGA timing generation -------------
// sync horizontal counter with bus cycle counter so cpu and video stay synchronous
// even if horizotal counter is affected by resolution changes
// the scan doubler is a special case as the atari line timing then expands over two vga
// lines and may/must be asynchronous to the vga timing at the end of the first line
if(vga_hcnt == t5_h_end) begin
if((bus_cycle == 4'd15) || (scan_doubler_enable && sd_vcnt[0]))
vga_hcnt <= 10'd0;
end else
vga_hcnt <= vga_hcnt + 10'd1;
// generate user adjustable vga sync signal
if( vga_hcnt == t2_h_sync - adjust_h ) vga_h_sync <= 1'b1;
if( vga_hcnt == t3_h_blank_left - adjust_h ) vga_h_sync <= 1'b0;
// generate horizontal video signal states
if( vga_hcnt == t2_h_sync ) vga_h_state <= 2'd0;
if((vga_hcnt == t0_h_border_right) || (vga_hcnt == t4_h_border_left)) vga_h_state <= 2'd2;
if((vga_hcnt == t1_h_blank_right) || (vga_hcnt == t3_h_blank_left)) vga_h_state <= 2'd1;
if( vga_hcnt == t5_h_end) vga_h_state <= 2'd3;
// ------------- horizontal ST timing generation -------------
// Run st timing at full speed if no scan doubler is being used. Otherwise run
// it at half speed
if((!scan_doubler_enable) || vga_hcnt[0]) begin
if(st_hcnt == t5_h_end) begin
// changing video modes toggles scan_doubler_enable and will bring
// the two hcnt counters out of sync. So we'll resync st_hcnt with vgs_hcnt here
if((vga_hcnt == t5_h_end) && (!scan_doubler_enable || !sd_vcnt[0]))
st_hcnt <= 10'd0;
end else
st_hcnt <= st_hcnt + 10'd1;
// generate horizontal video signal states
if( vga_hcnt == t2_h_sync ) vga_h_state <= 2'd0;
if((vga_hcnt == t0_h_border_right) || (vga_hcnt == t4_h_border_left)) vga_h_state <= 2'd2;
if((vga_hcnt == t1_h_blank_right) || (vga_hcnt == t3_h_blank_left)) vga_h_state <= 2'd1;
if( vga_hcnt == t5_h_end) vga_h_state <= 2'd3;
// ------------- horizontal ST timing generation -------------
// Run st timing at full speed if no scan doubler is being used. Otherwise run
// it at half speed
if((!scan_doubler_enable) || vga_hcnt[0]) begin
if(st_hcnt == t5_h_end) begin
// changing video modes toggles scan_doubler_enable and will bring
// the two hcnt counters out of sync. So we'll resync st_hcnt with vgs_hcnt here
if((vga_hcnt == t5_h_end) && (!scan_doubler_enable || !vcnt[0]))
st_hcnt <= 10'd0;
end else
st_hcnt <= st_hcnt + 10'd1;
if( st_hcnt == t2_h_sync ) st_h_state <= 2'd0;
if((st_hcnt == t0_h_border_right) || (st_hcnt == t4_h_border_left)) st_h_state <= 2'd2;
if((st_hcnt == t1_h_blank_right) || (st_hcnt == t3_h_blank_left)) st_h_state <= 2'd1;
if( st_hcnt == t5_h_end) st_h_state <= 2'd3;
end
// generate horizontal video signal states
if( st_hcnt == t2_h_sync ) st_h_state <= 2'd0;
if((st_hcnt == t0_h_border_right) || (st_hcnt == t4_h_border_left)) st_h_state <= 2'd2;
if((st_hcnt == t1_h_blank_right) || (st_hcnt == t3_h_blank_left)) st_h_state <= 2'd1;
if( st_hcnt == t5_h_end) st_h_state <= 2'd3;
end
// vertical state changes at end of hsync (begin of left blank)
if(vga_hcnt == v_event) begin
// vertical state changes at end of hsync (begin of left blank)
if(vga_hcnt == v_event) begin
// ------------- vertical timing generation -------------
// increase vcnt
if(vcnt == t11_v_end) vcnt <= 10'd0;
else vcnt <= vcnt + 10'd1;
// ------------- vertical timing generation -------------
// increase vcnt
if(vcnt == t11_v_end) vcnt <= 10'd0;
else vcnt <= vcnt + 10'd1;
if( vcnt == t8_v_sync - adjust_v ) vga_v_sync <= 1'b1;
if( vcnt == t9_v_blank_top - adjust_v ) vga_v_sync <= 1'b0;
// generate vertical video signal states
if( vcnt == t8_v_sync ) v_state <= 2'd0;
if((vcnt == t6_v_border_bot) || (vcnt == t10_v_border_top)) v_state <= 2'd2;
if((vcnt == t7_v_blank_bot) || (vcnt == t9_v_blank_top)) v_state <= 2'd1;
if( vcnt == t11_v_end) v_state <= 2'd3;
end
// generate vertical video signal states
if( vcnt == t8_v_sync ) v_state <= 2'd0;
if((vcnt == t6_v_border_bot) || (vcnt == t10_v_border_top)) v_state <= 2'd2;
if((vcnt == t7_v_blank_bot) || (vcnt == t9_v_blank_top)) v_state <= 2'd1;
if( vcnt == t11_v_end) v_state <= 2'd3;
end
end

View File

@@ -23,17 +23,10 @@
// http://martin.hinner.info/vga/timing.html
// http://www.epanorama.net/faq/vga2rgb/calc.html
// original atari video timing
// mono color
// pclk 32MHz 16/8MHz
// hfreq 35.7kHz 15.75kHz
// vfreq 71.2Hz 50/60Hz
//
// avg. values derived from frequencies:
// hdisp 640 640/320
// htot 896 1015/507
// vdisp 400 200
// vtot 501 315/262
// clocks on real sts:
// PAL 32084988 Hz
// NTSC 32042400 Hz
// MIST 31875000 Hz
module video_modes (
inout mono, // select monochrome mode (and not color)
@@ -52,16 +45,16 @@ localparam V_ACT = 10'd400;
// TIMING CONSTRAINTS:
// The total width (act+both blank+2*border+sync) must be a multiple of 16, for
// low rez a multiple of 32
// For modes to be used with the scan doubler the total heigth (act+both blank+
// 2*border+sync) must be a multiple of 4
// scan doubled modes a multiple of 8
// ---------------------------------------------------------------------------
// ----------------------------- pal56 timing -------------------------------
// ---------------------------------------------------------------------------
// PAL modes need ~80 pixels vertical border for border removal
// 34.21 kHz / 55.9 Hz
// 56Hz replacement for Atari 50Hz low and medium resolution video mode scan doubled:
// total: 1024x626, active incl border: 800x560, displayed: 640x400
// horizontal scan rate: 17.27 kHz, vertical scan rate: 56.34 hz
wire [121:0] pal56_config_str;
@@ -76,12 +69,15 @@ conf pal56_conf(
// ----------------------------- pal50 timing -------------------------------
// ---------------------------------------------------------------------------
wire [121:0] pal50_config_str;
// Atari 50Hz low and medium resolution video mode scan doubled:
// total: 1024x626, active incl border: 800x560, displayed: 640x400
// horizontal scan rate: 15.625 kHz, vertical scan rate: 49.92 hz
wire [121:0] pal50_config_str;
conf pal50_conf(
// front porch sync width back porch border width sync polarity
.h_fp ( 10'd80), .h_s ( 10'd40), .h_bp (10'd152), .h_bd (10'd40), .h_sp (1'b1),
.v_fp ( 10'd37), .v_s ( 10'd3), .v_bp ( 10'd36), .v_bd (10'd80), .v_sp (1'b1),
.h_fp ( 10'd80), .h_s ( 10'd64), .h_bp ( 10'd80), .h_bd (10'd80), .h_sp (1'b1),
.v_fp ( 10'd30), .v_s ( 10'd6), .v_bp ( 10'd30), .v_bd (10'd80), .v_sp (1'b1),
.str (pal50_config_str)
);
@@ -89,14 +85,15 @@ conf pal50_conf(
// ------------------------------ ntsc timing -------------------------------
// ---------------------------------------------------------------------------
// 31.01 kHz / 59.63 Hz
// Atari 60Hz low and medium resolution video mode scan doubled:
// total: 1016x526, active incl border: 800x480, displayed: 640x400
// horizontal scan rate: 15.748 kHz, vertical scan rate: 59.88 hz
wire [121:0] ntsc_config_str;
conf ntsc_conf(
// front porch sync width back porch border width sync polarity
.h_fp ( 10'd88), .h_s (10'd120), .h_bp ( 10'd96), .h_bd (10'd40), .h_sp (1'b0),
.v_fp ( 10'd18), .v_s ( 10'd3), .v_bp ( 10'd19), .v_bd (10'd40), .v_sp (1'b0),
.h_fp ( 10'd76), .h_s ( 10'd64), .h_bp ( 10'd76), .h_bd (10'd80), .h_sp (1'b1),
.v_fp ( 10'd20), .v_s ( 10'd6), .v_bp ( 10'd20), .v_bd (10'd40), .v_sp (1'b0),
.str (ntsc_config_str)
);
@@ -104,19 +101,22 @@ conf ntsc_conf(
// ------------------------------ mono timing -------------------------------
// ---------------------------------------------------------------------------
// Atari 71Hz high resolution video mode:
// total: 896x501, displayed: 640x400
// horizontal scan rate: 35.714 kHz, vertical scan rate: 71.286 hz
wire [121:0] mono_config_str;
conf mono_conf(
// front porch sync width back porch border width sync polarity
.h_fp ( 10'd24), .h_s ( 10'd40), .h_bp (10'd128), .h_bd ( 10'd0), .h_sp (1'b0),
.v_fp ( 10'd55), .v_s ( 10'd3), .v_bp ( 10'd74), .v_bd ( 10'd0), .v_sp (1'b0),
.h_fp (10'd108), .h_s ( 10'd40), .h_bp (10'd108), .h_bd ( 10'd0), .h_sp (1'b0),
.v_fp ( 10'd48), .v_s ( 10'd5), .v_bp ( 10'd48), .v_bd ( 10'd0), .v_sp (1'b0),
.str (mono_config_str)
);
// this is the video mode multiplexer ...
assign mode_str =
mono?mono_config_str:(pal?(pal56?pal56_config_str:pal50_config_str):ntsc_config_str);
assign mode_str = mono?mono_config_str:(pal?(pal56?pal56_config_str:pal50_config_str):ntsc_config_str);
endmodule