diff options
author | H. Peter Anvin <hpa@trantor.hos.anvin.org> | 2010-09-18 23:01:51 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@trantor.hos.anvin.org> | 2010-09-18 23:01:51 -0700 |
commit | cfae781bf19c4a5e2faa88d25f1bd56cba82f2ab (patch) | |
tree | 255d52e84e39e0678e7f56b27aa1eb312f0bd1dd | |
parent | a378cfc8700a22c4be05a44b4e110241760318e9 (diff) | |
download | abc80-cfae781bf19c4a5e2faa88d25f1bd56cba82f2ab.tar.gz abc80-cfae781bf19c4a5e2faa88d25f1bd56cba82f2ab.tar.xz abc80-cfae781bf19c4a5e2faa88d25f1bd56cba82f2ab.zip |
Make the "high-resolution" graphics unit work (sort of...)
Make the high-resolution graphics unit actually work... at least with
80-character text display. It still doesn't seem to work for a
40-character test display.
-rw-r--r-- | abc80.v | 85 | ||||
-rwxr-xr-x | data/fgcol.pl | 9 | ||||
-rwxr-xr-x | data/mmuinit.pl | 4 | ||||
-rw-r--r-- | display.v | 67 | ||||
-rw-r--r-- | mega/fgcolrom.v | 18 |
5 files changed, 149 insertions, 34 deletions
@@ -250,6 +250,52 @@ module abc80 ( ); // ------------------------------------------------------------------------ + // FG graphics controller - data counters + // + // These counters are here so they run in the cpu_clk clock domain + // -- necessary to multiplex with the SRAM. + // ------------------------------------------------------------------------ + + reg [5:0] fgxaddr; // Byte address horizontally + reg [8:0] fgyaddr; // Byte address vertically (bit 0 ignored) + reg [7:0] fgdata; + wire fgxrst; + reg [1:0] fgxrst_q; + wire fgyrst; + reg [1:0] fgyrst_q; + wire fgack; + reg [1:0] fgack_q; + reg [7:0] fgctl; + reg [4:0] fgpage; // Which 16K page in SRAM + + always @(posedge cpu_clk) + fgack_q <= { fgack_q[0], fgack }; + + always @(posedge cpu_clk) + fgxrst_q <= { fgxrst_q[0], fgxrst }; + + always @(posedge cpu_clk) + fgyrst_q <= { fgyrst_q[0], fgyrst }; + + always @(posedge cpu_clk) + begin + if (fgxrst_q[0] & ~fgxrst_q[1]) + fgxaddr <= ~6'h00; // The first ACK will advance this to 0 + else if (fgack_q[0] & ~fgack_q[1]) + fgxaddr <= fgxaddr + 1; + + if (fgyrst_q[0] & ~fgyrst_q[1]) + fgyaddr <= 8'h00; + else if (fgxrst_q[0] & ~fgxrst_q[1]) + fgyaddr <= fgyaddr + 1; + end // always @(posedge cpu_clk) + + // fgyaddr[0] ignored due to double-scanning + wire [18:0] sram_fgaddr = { fgpage, fgyaddr[8:1], fgxaddr }; + + wire sram_fgreq = fgack_q[0] & ~fgack_q[1]; + + // ------------------------------------------------------------------------ // Video controller // ------------------------------------------------------------------------ @@ -299,7 +345,13 @@ module abc80 ( .gd ( chargen_d[5:0] ), .rgb ( rgb ), .vsync ( vga_vs ), - .hsync ( vga_hs ) + .hsync ( vga_hs ), + + .fg_ctl ( fgctl ), + .fg_data ( fgdata ), + .fg_ack ( fgack ), + .fg_xrst ( fgxrst ), + .fg_yrst ( fgyrst ) ); assign vga_r = {4{rgb[2]}}; @@ -321,12 +373,12 @@ module abc80 ( wire sram_we_w; reg sram_we_q1; reg sram_we_q2; + reg sram_fgrd; // Are we actually accessed by the CPU? wire sram_cpu = msel[0] & cpu_clk_en; - assign sram_ce_n = ~sram_cpu; - assign sram_oe_w = sram_cpu & ~cpu_rd_n; + assign sram_oe_w = (sram_cpu & ~cpu_rd_n) | sram_fgrd; assign sram_we_w = sram_cpu & ~cpu_wr_n; always @(negedge rst_n or posedge fast_clk) @@ -345,13 +397,14 @@ module abc80 ( // The address to drive onto the bus. This is a placeholder for // multiplexing with the Fine Graphics unit. - wire [18:0] sram_addr = sram_cpu ? mmu_a[18:0] : 19'h7ffff; + wire [18:0] sram_addr = sram_cpu ? mmu_a[18:0] : sram_fgaddr; // Driving output pins. assign sram_a = sram_addr[18:1]; assign sram_be_n = sram_addr[0] ? ~2'b10 : ~2'b01; + assign sram_ce_n = ~(sram_cpu | sram_fgrd); assign sram_oe_n = ~sram_oe_w; assign sram_we_n = ~(sram_we_w & ~sram_we_q2); @@ -360,6 +413,15 @@ module abc80 ( // SRAM Input side MUX assign sram_do = sram_addr[0] ? sram_dq[15:8] : sram_dq[7:0]; + always @(posedge cpu_clk) + if (sram_fgreq) + sram_fgrd <= 1'b1; + else if (sram_fgrd & ~sram_cpu) + begin + sram_fgrd <= 1'b0; + fgdata <= sram_do; + end + // ------------------------------------------------------------------------ // External flash ROM // Note: the flash ROM is a 70 ns part. With MMU delays, we have about @@ -806,7 +868,10 @@ module abc80 ( prog_s7_0 <= 0; prog_s7_1 <= 0; - intio_do <= ~8'b0; + intio_do <= ~8'b0; + + fgctl <= 8'h00; + fgpage <= 5'h04; end else begin @@ -834,6 +899,10 @@ module abc80 ( prog_s7_0 <= cpu_do[7:0]; 5'b10111: prog_s7_1 <= cpu_do[7:0]; + 5'b11110: + fgctl <= cpu_do[7:0]; + 5'b11111: + fgpage <= cpu_do[4:0]; endcase // casex cpu_a[5:0] ) end // if ( intio_sel & ~cpu_wr_n ) else if ( ~abc_out_n[7] ) @@ -864,6 +933,12 @@ module abc80 ( intio_do <= prog_s7_0; 5'b10111: intio_do <= prog_s7_1; + 5'b11110: + intio_do <= fgctl; + 5'b11111: + intio_do <= { 3'b0, fgpage }; + default: + intio_do <= 8'hFF; endcase // casex ( cpu_a[5:0] ) end // if ( intio_sel & ~cpu_rd_n ) end diff --git a/data/fgcol.pl b/data/fgcol.pl index 4d8df63..2b96114 100755 --- a/data/fgcol.pl +++ b/data/fgcol.pl @@ -20,11 +20,12 @@ 'YCYC', 'YYCC', 'YWYW', 'YYWW', 'BMBM', 'BBMM', 'BCBC', 'BBCC', 'BWBW', 'BBWW', 'MCMC', 'MMCC', 'MWMW', 'MMWW', 'CWCW', 'CCWW' ); -%colenc = ('K' => 0, 'B' => 1, 'G' => 2, 'C' => 3, - 'R' => 4, 'M' => 5, 'Y' => 6, 'W' => 7); +# Note: bit 3 means opaque +%colenc = ('K' => 0, 'B' => 9, 'G' => 10, 'C' => 11, + 'R' => 12, 'M' => 13, 'Y' => 14, 'W' => 15); print "DEPTH = 512;\n"; -print "WIDTH = 3;\n"; +print "WIDTH = 4;\n"; print "ADDRESS_RADIX = HEX;\n"; print "DATA_RADIX = HEX;\n"; print "CONTENT\n"; @@ -35,7 +36,7 @@ for ($i = 0; $i < 128; $i++) { for ($x = 0; $x < 4; $x++) { $c = substr($coltbl[$i], $x, 1); $c = $colenc{$c}; - printf "%02X : %01X\n", $a++, $c; + printf "%02X : %01X;\n", $a++, $c; } } print "END;\n"; diff --git a/data/mmuinit.pl b/data/mmuinit.pl index 2b3eaa9..389c89f 100755 --- a/data/mmuinit.pl +++ b/data/mmuinit.pl @@ -34,7 +34,7 @@ sub do_ram() { if ( $testram ) { # Tiny amount of RAM (4K) for ( ; $i < 0xF0 ; $i++ ) { - printf("%03X : %04X;\n", $a++, 0xFFFF); + printf("%03X : %04X;\n", $a++, 0x70FF); } for ( $i = 0xF0 ; $i < 0x100 ; $i++ ) { printf("%03X : %04X;\n", $a++, 0x0000|$i); @@ -61,7 +61,7 @@ for ( $i = 0x00 ; $i < 0x40 ; $i++ ) { # BASIC printf("%03X : %04X;\n", $a++, 0x9000|$i); } for ( $i = 0x40 ; $i < 0x60 ; $i++ ) { # Free for expansion - printf("%03X : %04X;\n", $a++, 0x7FFF); + printf("%03X : %04X;\n", $a++, 0x70FF); } for ( $i = 0x60 ; $i < 0x74 ; $i++ ) { # DOS, IEC options printf("%03X : %04X;\n", $a++, 0x1000|$i); @@ -13,8 +13,14 @@ module display ( input [5:0] gd, output reg [2:0] rgb, - output reg vsync, - output reg hsync + output vsync, + output hsync, + + input [7:0] fg_ctl, + input [7:0] fg_data, + output fg_ack, + output fg_xrst, + output fg_yrst ); // We use the standard VGA 640x480 monitor timings mode, htime = 31.77 @@ -65,7 +71,10 @@ module display ( parameter hsync_minus = 1'b1; // -hsync parameter vsync_minus = 1'b1; // -vsync - + + reg hsync_q; // Horizontal sync active + reg vsync_q; // Vertical sync active + reg [9:0] x; // Horizontal pixel count reg [9:0] y; // Vertical pixel count reg [6:0] xchr; // Character column (0..99) @@ -84,6 +93,9 @@ module display ( reg [5:0] pixrow; // One character worth of pixels reg prefetch; // True for the prefetch character position + // Fine Graphics control + reg [7:0] fgpixels; // One byte of fg pixels + // For the current text line reg [2:0] curfg; // Foreground RGB reg [2:0] curbg; // Background RGB @@ -165,6 +177,9 @@ module display ( assign xvideo = ( x < x_blank ); assign yvideo = ( y < y_blank ); + assign hsync = hsync_q ^ hsync_minus; + assign vsync = vsync_q ^ vsync_minus; + // Flashing wire flash_on = scan_counter[4]; @@ -173,24 +188,48 @@ module display ( // "reverse" is asserted with invert everything *on top of that*... wire invert = (inverse & (flash_on|noblink))^reverse; + // + // Fine graphics + // + assign fg_ack = xvideo & yvideo & (x[2:0] == 3'b000); + assign fg_xrst = yvideo & hsync_q; + assign fg_yrst = vsync_q; + + wire [3:0] fg_argb; + + always @(posedge clk) + if (x[2:0] == 3'b100) + fgpixels <= fg_data; + else if (~x[0]) + fgpixels <= { fgpixels[5:0], 2'bxx }; + + fgcolrom fgcolrom ( + .address ( { fg_ctl[6:0], fgpixels[7:6] } ), + .clock ( clk ), + .q ( fg_argb ) + ); + // Synchronous logic always @(posedge clk) begin - if ( xvideo & yvideo & ~prefetch ) - if ( testpattern ) - // Pixel test pattern for LCD monitor calibration - rgb <= {3{x[0] ^ y[0]}}; - else if ( pixrow[5] & ~(do_flsh & ~flash_on) & ~(do_hide & ~reveal) ) - rgb <= fg ^ {3{invert}}; - else - rgb <= bg ^ {3{invert}}; + if ( ~xvideo | ~yvideo | prefetch ) + rgb <= 3'b000; // Blank + else if ( testpattern ) + // Pixel test pattern for LCD monitor calibration + rgb <= {3{x[0] ^ y[0]}}; + else if ( ~fg_ctl[7] & pixrow[5] + & ~(do_flsh & ~flash_on) + & ~(do_hide & ~reveal) ) + rgb <= fg ^ {3{invert}}; + else if (fg_ctl[7] | fg_argb[3]) + rgb <= fg_argb[2:0]; else - rgb <= 3'b0; // Blank + rgb <= bg ^ {3{invert}}; // Sync pulses - vsync <= ( y >= y_sync && y < y_front ) ^ vsync_minus; - hsync <= ( x >= x_sync && x < x_front ) ^ hsync_minus; + vsync_q <= ( y >= y_sync && y < y_front ); + hsync_q <= ( x >= x_sync && x < x_front ); // Rotating shift register; may be overridden by the below // The rotation is so that if we're in GHOL mode we already diff --git a/mega/fgcolrom.v b/mega/fgcolrom.v index d89270b..6e05d07 100644 --- a/mega/fgcolrom.v +++ b/mega/fgcolrom.v @@ -43,7 +43,7 @@ module fgcolrom ( input [8:0] address;
input clock;
- output [2:0] q;
+ output [3:0] q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
@@ -52,8 +52,8 @@ module fgcolrom ( // synopsys translate_on
`endif
- wire [2:0] sub_wire0;
- wire [2:0] q = sub_wire0[2:0];
+ wire [3:0] sub_wire0;
+ wire [3:0] q = sub_wire0[3:0];
altsyncram altsyncram_component (
.clock0 (clock),
@@ -71,7 +71,7 @@ module fgcolrom ( .clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
- .data_a ({3{1'b1}}),
+ .data_a ({4{1'b1}}),
.data_b (1'b1),
.eccstatus (),
.q_b (),
@@ -91,7 +91,7 @@ module fgcolrom ( altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.widthad_a = 9,
- altsyncram_component.width_a = 3,
+ altsyncram_component.width_a = 4,
altsyncram_component.width_byteena_a = 1;
@@ -126,7 +126,7 @@ endmodule // Retrieval info: PRIVATE: SingleClock NUMERIC "1"
// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
// Retrieval info: PRIVATE: WidthAddr NUMERIC "9"
-// Retrieval info: PRIVATE: WidthData NUMERIC "3"
+// Retrieval info: PRIVATE: WidthData NUMERIC "4"
// Retrieval info: PRIVATE: rden NUMERIC "0"
// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
@@ -139,13 +139,13 @@ endmodule // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "9"
-// Retrieval info: CONSTANT: WIDTH_A NUMERIC "3"
+// Retrieval info: CONSTANT: WIDTH_A NUMERIC "4"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: address 0 0 9 0 INPUT NODEFVAL address[8..0]
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC clock
-// Retrieval info: USED_PORT: q 0 0 3 0 OUTPUT NODEFVAL q[2..0]
+// Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL q[3..0]
// Retrieval info: CONNECT: @address_a 0 0 9 0 address 0 0 9 0
-// Retrieval info: CONNECT: q 0 0 3 0 @q_a 0 0 3 0
+// Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: GEN_FILE: TYPE_NORMAL fgcolrom.v TRUE
|