diff options
author | H. Peter Anvin <hpa@trantor.hos.anvin.org> | 2010-09-18 15:23:56 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@trantor.hos.anvin.org> | 2010-09-18 15:23:56 -0700 |
commit | 58b28518d10b10b92143f64a6e438c214bb7860d (patch) | |
tree | 1cd1b15b96b5a5b98e0c9bd393e55e17052f1bd0 | |
parent | 7318780bb586bc8ea3f5cc6d55c996cae84a8cc4 (diff) | |
download | abc80-58b28518d10b10b92143f64a6e438c214bb7860d.tar.gz abc80-58b28518d10b10b92143f64a6e438c214bb7860d.tar.xz abc80-58b28518d10b10b92143f64a6e438c214bb7860d.zip |
abc80: use an original-compatible 6x10 character matrix
Use a 6x10 character matrix instead of a "cheating" 8x16. This is
the resolution used by the original system. We use 480-line VGA
mode to display this, so we have to use double-scanning.
-rw-r--r-- | abc80.qsf | 5 | ||||
-rw-r--r-- | abc80.v | 11 | ||||
-rw-r--r-- | data/6x10-abc-l1.bdf | 16 | ||||
-rw-r--r-- | data/Makefile | 12 | ||||
-rwxr-xr-x | data/bdf2bin.pl | 14 | ||||
-rw-r--r-- | display.v | 236 |
6 files changed, 161 insertions, 133 deletions
@@ -34,7 +34,7 @@ set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 2.2
set_global_assignment -name PROJECT_CREATION_TIME_DATE "23:24:24 AUGUST 26, 2004"
-set_global_assignment -name LAST_QUARTUS_VERSION 8.1
+set_global_assignment -name LAST_QUARTUS_VERSION "9.0 SP2"
# Pin & Location Assignments
# ==========================
@@ -543,7 +543,7 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top set_global_assignment -name USE_CONFIGURATION_DEVICE ON
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
-set_global_assignment -name USE_SIGNALTAP_FILE stp3.stp
+set_global_assignment -name USE_SIGNALTAP_FILE stp6.stp
set_global_assignment -name VERILOG_FILE mega/pll2.v
set_global_assignment -name VERILOG_FILE mega/serrxfifo.v
set_global_assignment -name VERILOG_FILE i2c.v
@@ -552,7 +552,6 @@ set_global_assignment -name VERILOG_FILE mega/basic80.v set_global_assignment -name VERILOG_FILE mega/sddrom.v
set_global_assignment -name VERILOG_FILE mega/sddram.v
set_global_assignment -name VERILOG_FILE mega/ddio_out.v
-set_global_assignment -name MIF_FILE data/sdram.mif
set_global_assignment -name VERILOG_FILE sddisk.v
set_global_assignment -name VERILOG_FILE sound.v
set_global_assignment -name VHDL_FILE t80/T80_Pack.vhd
@@ -96,20 +96,17 @@ module abc80 ( // ------------------------------------------------------------------------ wire cpu_clk; // 25 MHz - wire video_clk; // 25 MHz = screen pixel rate - wire xvideo_clk; // 18.75 MHz = compatible screen pixel rate + wire video_clk; // 18.75 MHz = compatible screen pixel rate wire fast_clk; // 100 MHz wire audio_clk; // 16 MHz = I2S master clock wire pll1_locked; wire pll2_locked; - assign video_clk = cpu_clk; - pll1 pll1 ( .inclk0 ( clock_50 ), // 50 MHz input clock .c0 ( fast_clk ), // x2/1 = 100 MHz .c1 ( cpu_clk ), // x1/2 = 25 MHz - .c2 ( xvideo_clk ), // x3/8 = 18.75 MHz + .c2 ( video_clk ), // x3/8 = 18.75 MHz .locked ( pll1_locked ) ); @@ -259,7 +256,7 @@ module abc80 ( wire [10:0] video_a; wire [7:0] video_d; wire [10:0] chargen_a; - wire [7:0] chargen_d; + wire [7:0] chargen_d; // Only the low 6 bits are actually used wire [2:0] rgb; wire [7:0] vram_do; wire [7:0] cgen_do; @@ -299,7 +296,7 @@ module abc80 ( .a ( video_a ), .d ( video_d ), .ga ( chargen_a ), - .gd ( chargen_d ), + .gd ( chargen_d[5:0] ), .rgb ( rgb ), .vsync ( vga_vs ), .hsync ( vga_hs ) diff --git a/data/6x10-abc-l1.bdf b/data/6x10-abc-l1.bdf index 82d3e28..5363f8b 100644 --- a/data/6x10-abc-l1.bdf +++ b/data/6x10-abc-l1.bdf @@ -578,15 +578,15 @@ STARTCHAR parenleft ENCODING 40 SWIDTH 600 0 DWIDTH 6 0 -BBX 6 7 0 1 +BBX 3 7 1 0 BITMAP -fc -fc -fc -e0 -e0 -e0 -e0 +20 +40 +80 +80 +80 +40 +20 ENDCHAR STARTCHAR parenright ENCODING 41 diff --git a/data/Makefile b/data/Makefile index 0ddc8b6..ebb8418 100644 --- a/data/Makefile +++ b/data/Makefile @@ -43,10 +43,12 @@ printer.mif : printer.bin $(BIN2MIF) mmu.mif : mmuinit.pl $(PERL) mmuinit.pl > $@ || ( rm -f $@ ; exit 1 ) -FONT = 8x16-abc-l1.bdf +FONT = 6x10-abc-l1.bdf CHARSET = abcsefi +# These are the sizes in ROM, not the actual font +SIZES = 8 16 chargen.bin : $(FONT) bdf2bin.pl - $(PERL) bdf2bin.pl $(CHARSET) < $< > $@ || ( rm -f $@ ; exit 1 ) + $(PERL) bdf2bin.pl $(CHARSET) $(SIZES) < $< > $@ || ( rm -f $@ ; exit 1 ) chargen.mif : chargen.bin $(BIN2MIF) $(PERL) $(BIN2MIF) 2048 8 < $< > $@ || ( rm -f $@ ; exit 1 ) @@ -58,13 +60,13 @@ videoram.bin: video.txt genvideo.pl $(PERL) bin2poke.pl $< 16384 100 RETURN | cat charpoke.bah - > $@ || ( rm -f $@ ; exit 1 ) abcsefi.bin : $(FONT) bdf2bin.pl - $(PERL) bdf2bin.pl abcsefi < $< > $@ || ( rm -f $@ ; exit 1 ) + $(PERL) bdf2bin.pl abcsefi $(SIZES) < $< > $@ || ( rm -f $@ ; exit 1 ) abcdkno.bin : $(FONT) bdf2bin.pl - $(PERL) bdf2bin.pl abcdkno < $< > $@ || ( rm -f $@ ; exit 1 ) + $(PERL) bdf2bin.pl abcdkno $(SIZES) < $< > $@ || ( rm -f $@ ; exit 1 ) abcintl.bin : $(FONT) bdf2bin.pl - $(PERL) bdf2bin.pl abcintl < $< > $@ || ( rm -f $@ ; exit 1 ) + $(PERL) bdf2bin.pl abcintl $(SIZES) < $< > $@ || ( rm -f $@ ; exit 1 ) clean: rm -f *.obj *.bin *.mif *.bas diff --git a/data/bdf2bin.pl b/data/bdf2bin.pl index fb312cf..36f4d50 100755 --- a/data/bdf2bin.pl +++ b/data/bdf2bin.pl @@ -25,17 +25,19 @@ binmode STDOUT; "`abcdefghijklmnopqrstuvwxyz{|}~\x7f" ); -($set) = @ARGV; +($set, $xsize, $ysize) = @ARGV; $set = 'abcsefi' if ( !defined($charsets{$set}) ); $chars = $charsets{$set}; while ( defined($line = <STDIN>) ) { chomp $line; if ( $line =~ /^FONTBOUNDINGBOX\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/ ) { - $xsize = $1 + 0; - $ysize = $2 + 0; - $xoff = $3 + 0; - $yoff = $4 + 0; + $fxsize = $1 + 0; + $fysize = $2 + 0; + $xsize = $fxsize unless defined($xsize); + $ysize = $fysize unless defined($ysize); + $xoff = $3 + ($fxsize - $xsize); + $yoff = $4 + $fysize; @bitmasks = ("\0" x $ysize) x 256; } elsif ( $line =~ /^ENCODING\s+(\S+)/ ) { $thischar = $1 + 0; @@ -43,7 +45,7 @@ while ( defined($line = <STDIN>) ) { $cxsize = $1 + 0; $cysize = $2 + 0; $xstart = $3 - $xoff; - $ystart = $ysize - $4 - $cysize + $yoff; + $ystart = $yoff - $4 - $cysize; } elsif ( $line =~/^BITMAP\b/ ) { for ( $i = 0 ; $i < $cysize ; $i++ ) { $line = <STDIN>; @@ -1,5 +1,5 @@ module display ( - input clk, + input clk, // 18.75 MHz input width, input reverse, @@ -10,34 +10,36 @@ module display ( output [10:0] a, input [7:0] d, output [10:0] ga, - input [7:0] gd, + input [5:0] gd, output reg [2:0] rgb, output reg vsync, output reg hsync ); -// We use the standard VGA "text" monitor timings mode, -// htime = 31.77 us (31.47 kHz), vtime = 14.27 ms (70 Hz) -// The standard VGA uses a pixel clock of 25.175 MHz, we use 25 MHz, -// and round to multiples of 8. The error is about 0.8%, which -// is far, far less than the margin of error in real systems. +// We use the standard VGA 640x480 monitor timings mode, htime = 31.77 +// us (31.47 kHz), vtime = 16.68 ms (60 Hz) The standard VGA uses a +// pixel clock of 25.175 MHz, we use 18.75 MHz, which is 25*3/4 for +// 480 horizontal pixels; the error is about 0.8%, which is far, far +// less than the margin of error in real systems. // // This gives us the following timings: // -// Horizontal: 96 pixels (12 char) sync -// 40 pixels ( 5 char) back porch/border -// 640 pixels (80 char) graphics -// 24 pixels ( 3 char) front porch +// Horizontal: +// 480 pixels (80 char) graphics +// 12 pixels ( 2 char) back porch/border +// 72 pixels (12 char) sync +// 30 pixels ( 5 char) front porch // ---------- -// 800 pixels +// 594 pixels (31.68 us) // -// Vertical: 2 lines sync -// 41 lines back porch/border -// 384 lines graphics (24 rows @ 16 pixels) -// 22 lines front porch +// Vertical: +// 480 lines graphics (24 rows x 10 pixels x 2 scans/pixel) +// 10 lines back porch/border +// 2 lines sync +// 33 lines front porch // --------- -// 449 lines +// 525 lines // // In this implementation we start timing with the display area in both // cases, *except* that we prefetch by one character, and therefore start @@ -49,29 +51,35 @@ module display ( // // VGA monitors used the sync polarity to determine the mode, // especially the desired aspect ratio. Therefore, we want to use -hsync -// and +vsync, meaning hsync is active low and vsync is active high. +// and -vsync, - meaning active low, + meaning active high. - parameter x_blank = 640+8; - parameter x_sync = x_blank+32; - parameter x_front = x_sync+96; - parameter x_max = 800; + parameter x_blank = 480+6; + parameter x_sync = x_blank+(12-6); + parameter x_front = x_sync+72; + parameter x_max = 594; - parameter y_blank = 384; - parameter y_sync = y_blank+30; + parameter y_blank = 480; + parameter y_sync = y_blank+10; parameter y_front = y_sync+2; - parameter y_max = 449; + parameter y_max = 525; - parameter hsync_polarity = 1'b0; // -hsync - parameter vsync_polarity = 1'b1; // +vsync + parameter hsync_minus = 1'b1; // -hsync + parameter vsync_minus = 1'b1; // -vsync reg [9:0] x; // Horizontal pixel count - reg [8:0] y; // Vertical pixel count + reg [9:0] y; // Vertical pixel count + reg [6:0] xchr; // Character column (0..99) + reg [2:0] xpxl; // Pixel column in character (0..5) + reg [4:0] ychr; // Character row (0..26) + reg [3:0] ypxl; // Pixel row in character (0..9) + reg [4:0] ylu; // Previous character line + wire xvideo; // Non-blanked in the x direction wire yvideo; // Non-blanked in the y direction - wire [10:0] a80; // Character row assuming 80 columns - wire [10:0] a80u; // Character row assuming 80 columns (up 1 line) - reg [5:0] scan_counter; // Counter of total scans (for flashing et al) - reg [7:0] pixrow; // One character worth of pixels + wire [10:0] a80; // Memory address assuming 80 columns + wire [10:0] a80u; // Memory address assuming 80 columns (-1 line) + reg [4:0] scan_counter; // Counter of total scans (for flashing et al) + reg [5:0] pixrow; // One character worth of pixels reg prefetch; // True for the prefetch character position // For the current text line @@ -104,38 +112,42 @@ module display ( wire gsep = wasdble ? wasgsep : isgsep; wire do_flsh = wasdble ? wasflsh : isflsh; wire do_hide = wasdble ? washide : ishide; + + // Should we advance the character pixel? + wire advance = width | x[0]; // Address mapping for 80 characters; for 40 characters // we shift this left by 1 - assign a80[3:0] = x[6:3]; - wire [3:0] xmiddle = { 1'b0, x[9:7] }; - wire [3:0] ymiddle = { y[8:7] , y[8:7] }; + assign a80[3:0] = xchr[3:0]; + wire [3:0] xmiddle = { 1'b0, xchr[6:4] }; + wire [3:0] ymiddle = { ychr[4:3] , ychr[4:3] }; assign a80[7:4] = xmiddle+ymiddle; - assign a80[10:8] = y[6:4]; + assign a80[10:8] = ychr[2:0]; // Address mapping for 80 characters minus one line - wire [4:0] ylu = y[8:4] - 1; - assign a80u[3:0] = x[6:3]; + assign a80u[3:0] = xchr[3:0]; wire [3:0] yumiddle = { ylu[4:3] , ylu[4:3] }; assign a80u[7:4] = xmiddle+yumiddle; assign a80u[10:8] = ylu[2:0]; // Final address mapping // Note: We read the current char between pixels 0 and 1, - // and the char above between pixels 2 and 3; hence the use of x[1]. - wire [10:0] amap = x[1] ? a80u : a80; + // and the char above between pixels 2 and 3; hence the use of xchr[1]. + wire [10:0] amap = xchr[1] ? a80u : a80; assign a = width ? amap[10:0] : { 1'b1, amap[10:1] }; // Character generator address mapping assign ga[10:4] = somechar[6:0]; - assign ga[3:0] = wasdble ? { 1'b1, y[3:1] } : isdble ? { 1'b0, y[3:1] } : y[3:0]; + assign ga[3:0] = wasdble ? { 1'b1, ypxl[3:1] } : + isdble ? { 1'b0, ypxl[3:1] } : + ypxl[3:0]; // Video enable signal assign xvideo = ( x < x_blank ); assign yvideo = ( y < y_blank ); // Flashing - wire flash_on = scan_counter[5]; + wire flash_on = scan_counter[4]; // Inverse video. The normal is a flashing inverse cursor, but // if "noblink" is asserted the cursor is steady inverted. If @@ -146,13 +158,11 @@ module display ( always @(posedge clk) begin - // The x[9:4] means ignore the first character prefetch. We really - // should realign the counters, here. if ( xvideo & yvideo & ~prefetch ) if ( testpattern ) // Pixel test pattern for LCD monitor calibration rgb <= {3{x[0] ^ y[0]}}; - else if ( pixrow[7] & ~(do_flsh & ~flash_on) & ~(do_hide & ~reveal) ) + else if ( pixrow[5] & ~(do_flsh & ~flash_on) & ~(do_hide & ~reveal) ) rgb <= fg ^ {3{invert}}; else rgb <= bg ^ {3{invert}}; @@ -160,19 +170,19 @@ module display ( rgb <= 3'b0; // Blank // Sync pulses - vsync <= ( y >= y_sync && y < y_front ) ^ ~vsync_polarity; - hsync <= ( x >= x_sync && x < x_front ) ^ ~hsync_polarity; - + vsync <= ( y >= y_sync && y < y_front ) ^ vsync_minus; + hsync <= ( x >= x_sync && x < x_front ) ^ hsync_minus; + // Rotating shift register; may be overridden by the below // The rotation is so that if we're in GHOL mode we already - // have the reserved value - if ( width | x[0] ) - pixrow <= { pixrow[6:0], pixrow[7] }; + // have the previous value + if ( advance ) + pixrow <= { pixrow[4:0], pixrow[5] }; - // This code is run 8 times per character; regardless of width - if ( width | ~x[3] ) + // This code is run 6 times per character; regardless of width + if ( advance ) begin - case ( x[2:0] ) + case ( xpxl ) 3'b001: begin // Load and process character @@ -182,10 +192,10 @@ module display ( 3'b011: begin // Load and process previous-line character - thatchar <= (y[8:4] == 0) ? 8'h00 : d; + thatchar <= (ychr == 0) ? 8'h00 : d; end - 3'b111: + 3'b101: begin // Load a new pixel row? if ( xvideo ) @@ -268,72 +278,62 @@ module display ( begin // Generate graphical character case ( ga[3:0] ) - 4'h0, 4'h1, 4'h2, 4'h3: + 4'h0, 4'h1: begin - pixrow[7] <= somechar[0]; - pixrow[6] <= somechar[0]; pixrow[5] <= somechar[0]; - pixrow[4] <= somechar[0] & ~gsep; - pixrow[3] <= somechar[1]; + pixrow[4] <= somechar[0]; + pixrow[3] <= somechar[0] & ~gsep; pixrow[2] <= somechar[1]; pixrow[1] <= somechar[1]; pixrow[0] <= somechar[1] & ~gsep; end - 4'h4: + 4'h2: begin - pixrow[7] <= somechar[0] & ~gsep; - pixrow[6] <= somechar[0] & ~gsep; pixrow[5] <= somechar[0] & ~gsep; pixrow[4] <= somechar[0] & ~gsep; - pixrow[3] <= somechar[1] & ~gsep; + pixrow[3] <= somechar[0] & ~gsep; pixrow[2] <= somechar[1] & ~gsep; pixrow[1] <= somechar[1] & ~gsep; pixrow[0] <= somechar[1] & ~gsep; end - 4'h5, 4'h6, 4'h7, 4'h8, 4'h9: + 4'h3, 4'h4, 4'h5: begin - pixrow[7] <= somechar[2]; - pixrow[6] <= somechar[2]; pixrow[5] <= somechar[2]; - pixrow[4] <= somechar[2] & ~gsep; - pixrow[3] <= somechar[3]; + pixrow[4] <= somechar[2]; + pixrow[3] <= somechar[2] & ~gsep; pixrow[2] <= somechar[3]; pixrow[1] <= somechar[3]; pixrow[0] <= somechar[3] & ~gsep; end - 4'hA: + 4'h6: begin - pixrow[7] <= somechar[2] & ~gsep; - pixrow[6] <= somechar[2] & ~gsep; pixrow[5] <= somechar[2] & ~gsep; pixrow[4] <= somechar[2] & ~gsep; - pixrow[3] <= somechar[3] & ~gsep; + pixrow[3] <= somechar[2] & ~gsep; pixrow[2] <= somechar[3] & ~gsep; pixrow[1] <= somechar[3] & ~gsep; pixrow[0] <= somechar[3] & ~gsep; end - 4'hB, 4'hC, 4'hD, 4'hE: + 4'h7, 4'h8: begin - pixrow[7] <= somechar[4]; - pixrow[6] <= somechar[4]; pixrow[5] <= somechar[4]; - pixrow[4] <= somechar[4] & ~gsep; - pixrow[3] <= somechar[6]; + pixrow[4] <= somechar[4]; + pixrow[3] <= somechar[4] & ~gsep; pixrow[2] <= somechar[6]; pixrow[1] <= somechar[6]; pixrow[0] <= somechar[6] & ~gsep; end - 4'hF: + 4'h9: begin - pixrow[7] <= somechar[4] & ~gsep; - pixrow[6] <= somechar[4] & ~gsep; pixrow[5] <= somechar[4] & ~gsep; pixrow[4] <= somechar[4] & ~gsep; - pixrow[3] <= somechar[6] & ~gsep; + pixrow[3] <= somechar[4] & ~gsep; pixrow[2] <= somechar[6] & ~gsep; pixrow[1] <= somechar[6] & ~gsep; pixrow[0] <= somechar[6] & ~gsep; end + default: + pixrow <= 5'bxxxxxx; endcase // case( ga[3:0] ) end // if ( wasdble ? (wasgraph & thatchar[5]) : (isgraph & thischar[5]) ) else if ( (somechar[6:5] != 2'b00) | (wasdble ? wasgrel : isgrel) ) @@ -343,43 +343,71 @@ module display ( prefetch <= 1'b0; end // if ( xvideo ) inverse <= somechar[7]; - end // case: 3'b111 - endcase // case( x[2:0] ) - end // if ( width | ~x[3] ) + end // case: 3'b101 + endcase // case( xpxl ) + end // if ( advance ) // Counters if ( x == x_max-1 ) begin - x <= 0; + x <= 10'd0; + xchr <= 7'd0; + xpxl <= 3'd0; pixrow <= 8'b0; // Read-ahead spot is blank prefetch <= 1'b1; // Prefetch character - inverse <= 0; // Not inverse video + inverse <= 1'b0; // Not inverse video curfg <= 3'b111; // Default fg is white curbg <= 3'b000; // Default bg is black - isgraph <= 0; // Not graphic mode - isflsh <= 0; // Not flashing - isgsep <= 0; // Not separated - isdble <= 0; // Not double - isgrel <= 1; // Release graphics - ishide <= 0; // Not hidden + isgraph <= 1'b0; // Not graphic mode + isflsh <= 1'b0; // Not flashing + isgsep <= 1'b0; // Not separated + isdble <= 1'b0; // Not double + isgrel <= 1'b1; // Release graphics + ishide <= 1'b0; // Not hidden oldfg <= 3'b111; // Default fg is white oldbg <= 3'b000; // Default bg is black - wasgraph <= 0; // Not graphic mode - wasflsh <= 0; // Not flashing - wasgsep <= 0; // Not separated - wasdble <= 0; // Not double - wasgrel <= 1; // Release graphics - washide <= 0; // Not hidden + wasgraph <= 1'b0; // Not graphic mode + wasflsh <= 1'b0; // Not flashing + wasgsep <= 1'b0; // Not separated + wasdble <= 1'b0; // Not double + wasgrel <= 1'b1; // Release graphics + washide <= 1'b0; // Not hidden + ylu <= ychr; // Previous character row if ( y == y_max-1 ) begin - y <= 0; + y <= 10'd0; + ychr <= 6'd0; + ypxl <= 5'd0; scan_counter <= scan_counter + 1; end else - y <= y + 1; + begin + if ( y[0] ) // Double scanning + begin + if ( ypxl == 4'd9 ) + begin + ypxl <= 4'd0; + ychr <= ychr + 1; + end + else + ypxl <= ypxl + 1; + end + y <= y + 1; + end // else: !if( y == y_max-1 ) end // if ( x == x_max-1 ) else - x <= x + 1; + begin + if ( width | x[0] ) + begin + if ( xpxl == 3'd5 ) + begin + xpxl <= 0; + xchr <= xchr + 1; + end + else + xpxl <= xpxl + 1; + end + x <= x + 1; + end // else: !if( x == x_max-1 ) end // always @ (posedge clk) endmodule // display -
\ No newline at end of file |