| 1 |
31 |
robfinch |
// ============================================================================
|
| 2 |
|
|
// __
|
| 3 |
|
|
// \\__/ o\ (C) 2006-2022 Robert Finch, Waterloo
|
| 4 |
|
|
// \ __ / All rights reserved.
|
| 5 |
|
|
// \/_// robfinch@finitron.ca
|
| 6 |
|
|
// ||
|
| 7 |
|
|
//
|
| 8 |
|
|
// rfTextController.sv
|
| 9 |
|
|
// text controller
|
| 10 |
|
|
//
|
| 11 |
|
|
// BSD 3-Clause License
|
| 12 |
|
|
// Redistribution and use in source and binary forms, with or without
|
| 13 |
|
|
// modification, are permitted provided that the following conditions are met:
|
| 14 |
|
|
//
|
| 15 |
|
|
// 1. Redistributions of source code must retain the above copyright notice, this
|
| 16 |
|
|
// list of conditions and the following disclaimer.
|
| 17 |
|
|
//
|
| 18 |
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
| 19 |
|
|
// this list of conditions and the following disclaimer in the documentation
|
| 20 |
|
|
// and/or other materials provided with the distribution.
|
| 21 |
|
|
//
|
| 22 |
|
|
// 3. Neither the name of the copyright holder nor the names of its
|
| 23 |
|
|
// contributors may be used to endorse or promote products derived from
|
| 24 |
|
|
// this software without specific prior written permission.
|
| 25 |
|
|
//
|
| 26 |
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
| 27 |
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| 28 |
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 29 |
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
| 30 |
|
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 31 |
|
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 32 |
|
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
| 33 |
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
| 34 |
|
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 35 |
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 36 |
|
|
//
|
| 37 |
|
|
//
|
| 38 |
|
|
// Text Controller
|
| 39 |
|
|
//
|
| 40 |
|
|
// FEATURES
|
| 41 |
|
|
//
|
| 42 |
|
|
// This core requires an external timing generator to provide horizontal
|
| 43 |
|
|
// and vertical sync signals, but otherwise can be used as a display
|
| 44 |
|
|
// controller on it's own. However, this core may also be embedded within
|
| 45 |
|
|
// another core such as a VGA controller.
|
| 46 |
|
|
//
|
| 47 |
|
|
// Window positions are referenced to the rising edge of the vertical and
|
| 48 |
|
|
// horizontal sync pulses.
|
| 49 |
|
|
//
|
| 50 |
|
|
// The core includes an embedded dual port RAM to hold the screen
|
| 51 |
|
|
// characters.
|
| 52 |
|
|
//
|
| 53 |
|
|
// The controller expects a 64kB memory region to be reserved.
|
| 54 |
|
|
//
|
| 55 |
|
|
// Memory Map:
|
| 56 |
|
|
// 0000-3FFF display ram
|
| 57 |
|
|
// DF00-DFFF controller registers
|
| 58 |
|
|
// E000-FFFF character bitmap ram
|
| 59 |
|
|
//
|
| 60 |
|
|
//--------------------------------------------------------------------
|
| 61 |
|
|
// Registers
|
| 62 |
|
|
//
|
| 63 |
|
|
// 00h
|
| 64 |
|
|
// 7 - 0 cccccccc number of columns (horizontal displayed number of characters)
|
| 65 |
|
|
// 15- 8 rrrrrrrr number of rows (vertical displayed number of characters)
|
| 66 |
|
|
// 19-16 dddd character output delay
|
| 67 |
|
|
// 43-32 nnnn nnnnnnnn window left (horizontal sync position - reference for left edge of displayed)
|
| 68 |
|
|
// 59-48 nnnn nnnnnnnn window top (vertical sync position - reference for the top edge of displayed)
|
| 69 |
|
|
// 01h
|
| 70 |
|
|
// 4- 0 nnnnn maximum scan line (char ROM max value is 7)
|
| 71 |
|
|
// 11- 8 wwww pixel size - width
|
| 72 |
|
|
// 15-12 hhhh pixel size - height
|
| 73 |
|
|
// 24 r reset state bit
|
| 74 |
|
|
// 32 e controller enable
|
| 75 |
|
|
// 40 m multi-color mode
|
| 76 |
|
|
// 48-52 nnnnn yscroll
|
| 77 |
|
|
// 56-60 nnnnn xscroll
|
| 78 |
|
|
// 02h
|
| 79 |
|
|
// 23- 0 cccccccc cccccccc color code for transparent background RGB 8,8,8 (only RGB 7,7,7 used)
|
| 80 |
|
|
// 63-32 cccc...cccc border color ZRGB 8,8,8,8
|
| 81 |
|
|
// 03h
|
| 82 |
|
|
// 23- 0 cccccccc cccccccc tile color code 1
|
| 83 |
|
|
// 55-32 cccccccc cccccccc tile color code 2
|
| 84 |
|
|
// 04h
|
| 85 |
|
|
// 4- 0 eeeee cursor end
|
| 86 |
|
|
// 7- 5 bbb blink control
|
| 87 |
|
|
// BP: 00=no blink
|
| 88 |
|
|
// BP: 01=no display
|
| 89 |
|
|
// BP: 10=1/16 field rate blink
|
| 90 |
|
|
// BP: 11=1/32 field rate blink
|
| 91 |
|
|
// 12- 8 sssss cursor start
|
| 92 |
|
|
// 15-14 tt cursor image type (box, underline, sidebar, asterisk
|
| 93 |
|
|
// 47-32 aaaaaaaa aaaaaaaa cursor position
|
| 94 |
|
|
// 05h
|
| 95 |
|
|
// 15- 0 aaaaaaaa aaaaaaaa start address (index into display memory)
|
| 96 |
|
|
// 07h
|
| 97 |
|
|
// 150 - - aaaaaaaa aaaaaaaa light pen position
|
| 98 |
|
|
//--------------------------------------------------------------------
|
| 99 |
|
|
//
|
| 100 |
|
|
// ============================================================================
|
| 101 |
|
|
|
| 102 |
|
|
//`define USE_CLOCK_GATE
|
| 103 |
|
|
`define INTERNAL_RAMS 1'b1
|
| 104 |
|
|
|
| 105 |
|
|
module rfTextController_x12(
|
| 106 |
|
|
rst_i, clk_i, cs_i,
|
| 107 |
|
|
cti_i, cyc_i, stb_i, ack_o, wr_i, adr_i, dat_i, dat_o,
|
| 108 |
|
|
txt_clk_o, txt_cyc_o, txt_stb_o, txt_ack_i, txt_we_o, txt_sel_o, txt_adr_o, txt_dat_o, txt_dat_i,
|
| 109 |
|
|
cbm_clk_o, cbm_cyc_o, cbm_stb_o, cbm_ack_i, cbm_we_o, cbm_sel_o, cbm_adr_o, cbm_dat_o, cbm_dat_i,
|
| 110 |
|
|
lp_i,
|
| 111 |
|
|
dot_clk_i, hsync_i, vsync_i, blank_i, border_i, zrgb_i, zrgb_o, xonoff_i
|
| 112 |
|
|
);
|
| 113 |
|
|
parameter num = 4'd1;
|
| 114 |
|
|
parameter COLS = 8'd64;
|
| 115 |
|
|
parameter ROWS = 8'd32;
|
| 116 |
|
|
|
| 117 |
|
|
// Syscon
|
| 118 |
|
|
input rst_i; // reset
|
| 119 |
|
|
input clk_i; // clock
|
| 120 |
|
|
|
| 121 |
|
|
// Slave signals
|
| 122 |
|
|
input cs_i; // circuit select
|
| 123 |
|
|
input [2:0] cti_i;
|
| 124 |
|
|
input cyc_i; // valid bus cycle
|
| 125 |
|
|
input stb_i; // data strobe
|
| 126 |
|
|
output ack_o; // data acknowledge
|
| 127 |
|
|
input wr_i; // write
|
| 128 |
|
|
input [15:0] adr_i; // address
|
| 129 |
|
|
input [11:0] dat_i; // data input
|
| 130 |
|
|
output reg [11:0] dat_o; // data output
|
| 131 |
|
|
|
| 132 |
|
|
// Master Signals
|
| 133 |
|
|
output txt_clk_o;
|
| 134 |
|
|
output reg txt_cyc_o;
|
| 135 |
|
|
output reg txt_stb_o;
|
| 136 |
|
|
input txt_ack_i;
|
| 137 |
|
|
output txt_we_o;
|
| 138 |
|
|
output [7:0] txt_sel_o;
|
| 139 |
|
|
output reg [16:0] txt_adr_o;
|
| 140 |
|
|
output [63:0] txt_dat_o;
|
| 141 |
|
|
input [63:0] txt_dat_i;
|
| 142 |
|
|
|
| 143 |
|
|
output cbm_clk_o; // character bitmap data fetch clock
|
| 144 |
|
|
output reg cbm_cyc_o;
|
| 145 |
|
|
output reg cbm_stb_o;
|
| 146 |
|
|
input cbm_ack_i;
|
| 147 |
|
|
output cbm_we_o;
|
| 148 |
|
|
output [7:0] cbm_sel_o;
|
| 149 |
|
|
output reg [15:0] cbm_adr_o;
|
| 150 |
|
|
output [63:0] cbm_dat_o;
|
| 151 |
|
|
input [63:0] cbm_dat_i;
|
| 152 |
|
|
|
| 153 |
|
|
input lp_i; // light pen
|
| 154 |
|
|
|
| 155 |
|
|
// Video signals
|
| 156 |
|
|
input dot_clk_i; // video dot clock
|
| 157 |
|
|
input hsync_i; // end of scan line
|
| 158 |
|
|
input vsync_i; // end of frame
|
| 159 |
|
|
input blank_i; // blanking signal
|
| 160 |
|
|
input border_i; // border area
|
| 161 |
|
|
input [31:0] zrgb_i; // input pixel stream
|
| 162 |
|
|
output reg [31:0] zrgb_o; // output pixel stream
|
| 163 |
|
|
input xonoff_i;
|
| 164 |
|
|
|
| 165 |
|
|
reg controller_enable;
|
| 166 |
|
|
reg [31:0] bkColor32, bkColor32d; // background color
|
| 167 |
|
|
reg [31:0] fgColor32, fgColor32d; // foreground color
|
| 168 |
|
|
|
| 169 |
|
|
wire [1:0] pix; // pixel value from character generator 1=on,0=off
|
| 170 |
|
|
|
| 171 |
|
|
reg por;
|
| 172 |
|
|
wire vclk;
|
| 173 |
|
|
assign txt_clk_o = vclk;
|
| 174 |
|
|
assign txt_we_o = por;
|
| 175 |
|
|
assign txt_sel_o = 8'hFF;
|
| 176 |
|
|
assign cbm_clk_o = vclk;
|
| 177 |
|
|
assign cbm_we_o = 1'b0;
|
| 178 |
|
|
assign cbm_sel_o = 8'hFF;
|
| 179 |
|
|
|
| 180 |
|
|
reg [63:0] rego;
|
| 181 |
|
|
reg [4:0] yscroll;
|
| 182 |
|
|
reg [5:0] xscroll;
|
| 183 |
|
|
reg [11:0] windowTop;
|
| 184 |
|
|
reg [11:0] windowLeft;
|
| 185 |
|
|
reg [ 7:0] numCols;
|
| 186 |
|
|
reg [ 7:0] numRows;
|
| 187 |
|
|
reg [ 7:0] charOutDelay;
|
| 188 |
|
|
reg [ 1:0] mode;
|
| 189 |
|
|
reg [ 4:0] maxRowScan;
|
| 190 |
|
|
reg [ 5:0] maxScanpix;
|
| 191 |
|
|
reg [1:0] tileWidth; // width of tile in bytes (0=1,1=2,2=4,3=8)
|
| 192 |
|
|
reg [ 4:0] cursorStart, cursorEnd;
|
| 193 |
|
|
reg [15:0] cursorPos;
|
| 194 |
|
|
reg [1:0] cursorType;
|
| 195 |
|
|
reg [15:0] startAddress;
|
| 196 |
|
|
reg [ 2:0] rBlink;
|
| 197 |
|
|
reg [3:0] bdrCode;
|
| 198 |
|
|
wire [23:0] bdrColor; // Border color
|
| 199 |
|
|
reg [ 3:0] pixelWidth; // horizontal pixel width in clock cycles
|
| 200 |
|
|
reg [ 3:0] pixelHeight; // vertical pixel height in scan lines
|
| 201 |
|
|
reg mcm; // multi-color mode
|
| 202 |
|
|
|
| 203 |
|
|
wire [11:0] hctr; // horizontal reference counter (counts clocks since hSync)
|
| 204 |
|
|
wire [11:0] scanline; // scan line
|
| 205 |
|
|
reg [ 7:0] row; // vertical reference counter (counts rows since vSync)
|
| 206 |
|
|
reg [ 7:0] col; // horizontal column
|
| 207 |
|
|
reg [ 4:0] rowscan; // scan line within row
|
| 208 |
|
|
reg [ 5:0] colscan; // pixel column number within cell
|
| 209 |
|
|
wire nxt_row; // when to increment the row counter
|
| 210 |
|
|
wire nxt_col; // when to increment the column counter
|
| 211 |
|
|
reg [ 5:0] bcnt; // blink timing counter
|
| 212 |
|
|
wire blink;
|
| 213 |
|
|
reg iblank;
|
| 214 |
|
|
reg [4:0] maxScanlinePlusOne;
|
| 215 |
|
|
|
| 216 |
|
|
wire nhp; // next horizontal pixel
|
| 217 |
|
|
wire ld_shft = nxt_col & nhp;
|
| 218 |
|
|
|
| 219 |
|
|
|
| 220 |
|
|
// display and timing signals
|
| 221 |
|
|
reg [15:0] txtAddr; // index into memory
|
| 222 |
|
|
reg [15:0] penAddr;
|
| 223 |
|
|
wire [23:0] screen_ram_out; // character code
|
| 224 |
|
|
wire [23:0] txtBkColor; // background color code
|
| 225 |
|
|
wire [23:0] txtFgColor; // foreground color code
|
| 226 |
|
|
wire [5:0] txtZorder;
|
| 227 |
|
|
reg [3:0] txtTcCode; // transparent color code
|
| 228 |
|
|
wire [23:0] txtTcColor;
|
| 229 |
|
|
reg [3:0] tileCode1;
|
| 230 |
|
|
reg [3:0] tileCode2;
|
| 231 |
|
|
wire [23:0] tileColor1;
|
| 232 |
|
|
wire [23:0] tileColor2;
|
| 233 |
|
|
reg bgt, bgtd;
|
| 234 |
|
|
|
| 235 |
|
|
wire [11:0] tdat_o;
|
| 236 |
|
|
wire [8:0] chdat_o;
|
| 237 |
|
|
|
| 238 |
|
|
wire [2:0] scanindex = rowscan[2:0];
|
| 239 |
|
|
|
| 240 |
|
|
//--------------------------------------------------------------------
|
| 241 |
|
|
// bus interfacing
|
| 242 |
|
|
// Address Decoding
|
| 243 |
|
|
// I/O range Dx
|
| 244 |
|
|
//--------------------------------------------------------------------
|
| 245 |
|
|
// Register the inputs
|
| 246 |
|
|
reg cs_rom, cs_reg, cs_text, cs_any;
|
| 247 |
|
|
reg [15:0] radr_i;
|
| 248 |
|
|
reg [11:0] rdat_i;
|
| 249 |
|
|
reg rwr_i;
|
| 250 |
|
|
always_ff @(posedge clk_i)
|
| 251 |
|
|
cs_rom <= cs_i && cyc_i && stb_i && (adr_i[15:8] > 8'hDF);
|
| 252 |
|
|
always_ff @(posedge clk_i)
|
| 253 |
|
|
cs_reg <= cs_i && cyc_i && stb_i && (adr_i[15:8] == 8'hDF);
|
| 254 |
|
|
always_ff @(posedge clk_i)
|
| 255 |
|
|
cs_text <= cs_i && cyc_i && stb_i && (adr_i[15:8] < 8'hDF);
|
| 256 |
|
|
always_ff @(posedge clk_i)
|
| 257 |
|
|
cs_any <= cs_i && cyc_i && stb_i;
|
| 258 |
|
|
always_ff @(posedge clk_i)
|
| 259 |
|
|
rwr_i <= wr_i;
|
| 260 |
|
|
always_ff @(posedge clk_i)
|
| 261 |
|
|
radr_i <= adr_i;
|
| 262 |
|
|
always_ff @(posedge clk_i)
|
| 263 |
|
|
rdat_i <= dat_i;
|
| 264 |
|
|
|
| 265 |
|
|
// Register outputs
|
| 266 |
|
|
always @(posedge clk_i)
|
| 267 |
|
|
if (cs_i)
|
| 268 |
|
|
casez({cs_rom,cs_reg,cs_text})
|
| 269 |
|
|
3'b1??: dat_o <= {3'b0,chdat_o};
|
| 270 |
|
|
3'b01?: dat_o <= rego;
|
| 271 |
|
|
3'b001: dat_o <= tdat_o;
|
| 272 |
|
|
default: dat_o <= 12'h0;
|
| 273 |
|
|
endcase
|
| 274 |
|
|
else
|
| 275 |
|
|
dat_o <= 12'h0;
|
| 276 |
|
|
|
| 277 |
|
|
//always @(posedge clk_i)
|
| 278 |
|
|
// if (cs_text) begin
|
| 279 |
|
|
// $display("TC WRite: %h %h", adr_i, dat_i);
|
| 280 |
|
|
// $stop;
|
| 281 |
|
|
// end
|
| 282 |
|
|
|
| 283 |
|
|
// - there is a four cycle latency for reads, an ack is generated
|
| 284 |
|
|
// after the synchronous RAM read
|
| 285 |
|
|
// - writes can be acknowledged right away.
|
| 286 |
|
|
|
| 287 |
|
|
ack_gen #(
|
| 288 |
|
|
.READ_STAGES(5),
|
| 289 |
|
|
.WRITE_STAGES(1),
|
| 290 |
|
|
.REGISTER_OUTPUT(1)
|
| 291 |
|
|
)
|
| 292 |
|
|
uag1 (
|
| 293 |
|
|
.rst_i(rst_i),
|
| 294 |
|
|
.clk_i(clk_i),
|
| 295 |
|
|
.ce_i(1'b1),
|
| 296 |
|
|
.i(cs_any),
|
| 297 |
|
|
.we_i(cs_any & rwr_i),
|
| 298 |
|
|
.o(ack_o),
|
| 299 |
|
|
.rid_i(0),
|
| 300 |
|
|
.wid_i(0),
|
| 301 |
|
|
.rid_o(),
|
| 302 |
|
|
.wid_o()
|
| 303 |
|
|
);
|
| 304 |
|
|
|
| 305 |
|
|
//--------------------------------------------------------------------
|
| 306 |
|
|
//--------------------------------------------------------------------
|
| 307 |
|
|
`ifdef USE_CLOCK_GATE
|
| 308 |
|
|
BUFHCE ucb1 (.I(dot_clk_i), .CE(controller_enable), .O(vclk));
|
| 309 |
|
|
`else
|
| 310 |
|
|
assign vclk = dot_clk_i;
|
| 311 |
|
|
`endif
|
| 312 |
|
|
|
| 313 |
|
|
//--------------------------------------------------------------------
|
| 314 |
|
|
// Video Memory
|
| 315 |
|
|
//--------------------------------------------------------------------
|
| 316 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 317 |
|
|
// Address Calculation:
|
| 318 |
|
|
// - Simple: the row times the number of cols plus the col plus the
|
| 319 |
|
|
// base screen address
|
| 320 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 321 |
|
|
|
| 322 |
|
|
reg [15:0] rowcol;
|
| 323 |
|
|
always_ff @(posedge vclk)
|
| 324 |
|
|
txtAddr <= startAddress + rowcol + col;
|
| 325 |
|
|
|
| 326 |
|
|
// Register read-back memory
|
| 327 |
|
|
// Allows reading back of register values by shadowing them with ram
|
| 328 |
|
|
|
| 329 |
|
|
wire [5:0] rrm_adr = radr_i[5:0];
|
| 330 |
|
|
wire [11:0] rrm_o;
|
| 331 |
|
|
|
| 332 |
|
|
regReadbackMem #(.WID(12)) rrm0L
|
| 333 |
|
|
(
|
| 334 |
|
|
.wclk(clk_i),
|
| 335 |
|
|
.adr(rrm_adr),
|
| 336 |
|
|
.wce(cs_reg),
|
| 337 |
|
|
.we(rwr_i),
|
| 338 |
|
|
.i(rdat_i[11:0]),
|
| 339 |
|
|
.o(rrm_o[11:0])
|
| 340 |
|
|
);
|
| 341 |
|
|
|
| 342 |
|
|
wire [23:0] lfsr_o;
|
| 343 |
|
|
lfsr #(24) ulfsr1(rst_i, dot_clk_i, 1'b1, 1'b0, lfsr_o);
|
| 344 |
|
|
assign m_dat_o = lfsr_o;
|
| 345 |
|
|
|
| 346 |
|
|
/*
|
| 347 |
|
|
wire pe_cs;
|
| 348 |
|
|
edge_det u1(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(cs_text), .pe(pe_cs), .ne(), .ee() );
|
| 349 |
|
|
|
| 350 |
|
|
reg [14:0] ctr;
|
| 351 |
|
|
always @(posedge clk_i)
|
| 352 |
|
|
if (pe_cs) begin
|
| 353 |
|
|
if (cti_i==3'b000)
|
| 354 |
|
|
ctr <= adr_i[16:3];
|
| 355 |
|
|
else
|
| 356 |
|
|
ctr <= adr_i[16:3] + 12'd1;
|
| 357 |
|
|
cnt <= 3'b000;
|
| 358 |
|
|
end
|
| 359 |
|
|
else if (cs_text && cnt[2:0]!=3'b100 && cti_i!=3'b000) begin
|
| 360 |
|
|
ctr <= ctr + 2'd1;
|
| 361 |
|
|
cnt <= cnt + 3'd1;
|
| 362 |
|
|
end
|
| 363 |
|
|
|
| 364 |
|
|
reg [13:0] radr;
|
| 365 |
|
|
always @(posedge clk_i)
|
| 366 |
|
|
radr <= pe_cs ? adr_i[16:3] : ctr;
|
| 367 |
|
|
*/
|
| 368 |
|
|
// text screen RAM
|
| 369 |
|
|
wire [13:0] bram_adr = radr_i[13:0];
|
| 370 |
|
|
|
| 371 |
|
|
`ifdef INTERNAL_RAMS
|
| 372 |
|
|
rfTextControllerRam_x12 screen_ram1
|
| 373 |
|
|
(
|
| 374 |
|
|
.clka(clk_i),
|
| 375 |
|
|
.ena(cs_text),
|
| 376 |
|
|
.wea(rwr_i),
|
| 377 |
|
|
.addra({radr_i[12:0],radr_i[13]}),
|
| 378 |
|
|
.dina(rdat_i),
|
| 379 |
|
|
.douta(tdat_o),
|
| 380 |
|
|
.clkb(vclk),
|
| 381 |
|
|
.enb(ld_shft|por),
|
| 382 |
|
|
.web(por),
|
| 383 |
|
|
.addrb(txtAddr[12:0]),
|
| 384 |
|
|
.dinb({12'hE6,lfsr_o[11:0]}),
|
| 385 |
|
|
.doutb(screen_ram_out)
|
| 386 |
|
|
);
|
| 387 |
|
|
|
| 388 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 389 |
|
|
// Character bitmap ROM
|
| 390 |
|
|
// - room for 512 8x8 characters
|
| 391 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 392 |
|
|
wire [63:0] char_bmp; // character ROM output
|
| 393 |
|
|
char_ram charRam0
|
| 394 |
|
|
(
|
| 395 |
|
|
.clk_i(clk_i),
|
| 396 |
|
|
.cs_i(cs_rom),
|
| 397 |
|
|
.we_i(1'b0),
|
| 398 |
|
|
.adr_i(radr_i[14:0]),
|
| 399 |
|
|
.dat_i(rdat_i),
|
| 400 |
|
|
.dat_o(chdat_o),
|
| 401 |
|
|
.dot_clk_i(vclk),
|
| 402 |
|
|
.ce_i(ld_shft),
|
| 403 |
|
|
.char_code_i(screen_ram_out[8:0]),
|
| 404 |
|
|
.maxscanline_i(maxScanlinePlusOne),
|
| 405 |
|
|
.scanline_i(rowscan[4:0]),
|
| 406 |
|
|
.bmp_o(char_bmp)
|
| 407 |
|
|
);
|
| 408 |
|
|
//assign char_bmp[63:9] = 55'h0;
|
| 409 |
|
|
`else
|
| 410 |
|
|
reg [63:0] char_bmp; // character ROM output
|
| 411 |
|
|
`endif
|
| 412 |
|
|
|
| 413 |
|
|
reg [63:0] txt_dati;
|
| 414 |
|
|
reg [31:0] bmp_ndx;
|
| 415 |
|
|
`ifdef INTERNAL_RAMS
|
| 416 |
|
|
`else
|
| 417 |
|
|
always_ff @(posedge vclk)
|
| 418 |
|
|
bmp_ndx <= (maxScanlinePlusOne * txt_dati[15:0] + rowscan[4:0]) << tileWidth;
|
| 419 |
|
|
always_ff @(posedge vclk)
|
| 420 |
|
|
begin
|
| 421 |
|
|
if (ld_shft) begin
|
| 422 |
|
|
txt_cyc_o <= 1'b1;
|
| 423 |
|
|
txt_stb_o <= 1'b1;
|
| 424 |
|
|
txt_adr_o <= {txtAddr[13:0],3'b0};
|
| 425 |
|
|
cbm_cyc_o <= 1'b1;
|
| 426 |
|
|
cbm_stb_o <= 1'b1;
|
| 427 |
|
|
cbm_adr_o <= {bmp_ndx[31:3],3'b0};
|
| 428 |
|
|
end
|
| 429 |
|
|
if (txt_ack_i) begin
|
| 430 |
|
|
txt_cyc_o <= 1'b0;
|
| 431 |
|
|
txt_stb_o <= 1'b0;
|
| 432 |
|
|
txt_dati <= txt_dat_i;
|
| 433 |
|
|
end
|
| 434 |
|
|
if (cbm_ack_i) begin
|
| 435 |
|
|
cbm_cyc_o <= 1'b0;
|
| 436 |
|
|
cbm_stb_o <= 1'b0;
|
| 437 |
|
|
case(tileWidth)
|
| 438 |
|
|
2'd0: char_bmp <= cbm_dat_i >> {bmp_ndx[2:0],3'b0};
|
| 439 |
|
|
2'd1: char_bmp <= cbm_dat_i >> {bmp_ndx[2:1],4'b0};
|
| 440 |
|
|
2'd2: char_bmp <= cbm_dat_i >> {bmp_ndx[2],5'b0};
|
| 441 |
|
|
2'd3: char_bmp <= cbm_dat_i;
|
| 442 |
|
|
endcase
|
| 443 |
|
|
end
|
| 444 |
|
|
end
|
| 445 |
|
|
`endif
|
| 446 |
|
|
|
| 447 |
|
|
/*
|
| 448 |
|
|
syncRam4kx9 charRam0
|
| 449 |
|
|
(
|
| 450 |
|
|
.clka(clk_i), // input wire clka
|
| 451 |
|
|
.ena(cs_rom), // input wire ena
|
| 452 |
|
|
.wea(1'b0),//rwr_i), // input wire [0 : 0] wea
|
| 453 |
|
|
.addra(bram_adr), // input wire [11 : 0] addra
|
| 454 |
|
|
.dina(rdat_i[8:0]), // input wire [8 : 0] dina
|
| 455 |
|
|
.douta(chdat_o), // output wire [8 : 0] douta
|
| 456 |
|
|
.clkb(vclk), // input wire clkb
|
| 457 |
|
|
.enb(ld_shft), // input wire enb
|
| 458 |
|
|
.web(1'b0), // input wire [0 : 0] web
|
| 459 |
|
|
.addrb({screen_ram_out[8:0],scanline[2:0]}), // input wire [11 : 0] addrb
|
| 460 |
|
|
.dinb(9'h0), // input wire [8 : 0] dinb
|
| 461 |
|
|
.doutb(char_bmp) // output wire [8 : 0] doutb
|
| 462 |
|
|
);
|
| 463 |
|
|
*/
|
| 464 |
|
|
|
| 465 |
|
|
// pipeline delay - sync color with character bitmap output
|
| 466 |
|
|
reg [5:0] txtZorder1;
|
| 467 |
|
|
|
| 468 |
|
|
wire [3:0] txtBkCode1 = screen_ram_out[15:12];
|
| 469 |
|
|
wire [3:0] txtFgCode1 = screen_ram_out[19:16];
|
| 470 |
|
|
rfColorROM ucr1(vclk, ld_shft, {1'b0,txtBkCode1}, txtBkColor);
|
| 471 |
|
|
rfColorROM ucr2(vclk, ld_shft, {1'b0,txtFgCode1}, txtFgColor);
|
| 472 |
|
|
rfColorROM ucr3(vclk, 1'b1, {1'b0,txtTcCode}, txtTcColor);
|
| 473 |
|
|
rfColorROM ucr4(vclk, 1'b1, {1'b0,bdrCode}, bdrColor);
|
| 474 |
|
|
rfColorROM ucr5(vclk, ld_shft, {1'b0,tileCode1}, tileColor1);
|
| 475 |
|
|
rfColorROM ucr6(vclk, ld_shft, {1'b0,tileCode2}, tileColor2);
|
| 476 |
|
|
|
| 477 |
|
|
always @(posedge vclk)
|
| 478 |
|
|
if (ld_shft) txtZorder1 <= 6'h3F;
|
| 479 |
|
|
|
| 480 |
|
|
//--------------------------------------------------------------------
|
| 481 |
|
|
// Light Pen
|
| 482 |
|
|
//--------------------------------------------------------------------
|
| 483 |
|
|
wire lpe;
|
| 484 |
|
|
edge_det u1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(lp_i), .pe(lpe), .ne(), .ee() );
|
| 485 |
|
|
|
| 486 |
|
|
always @(posedge clk_i)
|
| 487 |
|
|
if (rst_i)
|
| 488 |
|
|
penAddr <= 32'h0000_0000;
|
| 489 |
|
|
else begin
|
| 490 |
|
|
if (lpe)
|
| 491 |
|
|
penAddr <= txtAddr;
|
| 492 |
|
|
end
|
| 493 |
|
|
|
| 494 |
|
|
|
| 495 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 496 |
|
|
// Register read port
|
| 497 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 498 |
|
|
always @*
|
| 499 |
|
|
if (cs_reg) begin
|
| 500 |
|
|
case(radr_i[5:0])
|
| 501 |
|
|
6'd56: rego <= {8'h00,penAddr[15:12]};
|
| 502 |
|
|
6'd57: rego <= penAddr[11:0];
|
| 503 |
|
|
default: rego <= rrm_o;
|
| 504 |
|
|
endcase
|
| 505 |
|
|
end
|
| 506 |
|
|
else
|
| 507 |
|
|
rego <= 12'h000;
|
| 508 |
|
|
|
| 509 |
|
|
|
| 510 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 511 |
|
|
// Register write port
|
| 512 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 513 |
|
|
|
| 514 |
|
|
always @(posedge clk_i)
|
| 515 |
|
|
if (rst_i) begin
|
| 516 |
|
|
por <= 1'b1;
|
| 517 |
|
|
mcm <= 1'b0;
|
| 518 |
|
|
controller_enable <= 1'b1;
|
| 519 |
|
|
xscroll <= 6'd0;
|
| 520 |
|
|
yscroll <= 5'd0;
|
| 521 |
|
|
txtTcCode <= 4'hE;
|
| 522 |
|
|
bdrCode <= 4'hE;
|
| 523 |
|
|
startAddress <= 16'h0000;
|
| 524 |
|
|
cursorStart <= 5'd00;
|
| 525 |
|
|
cursorEnd <= 5'd31;
|
| 526 |
|
|
cursorPos <= 16'h0003;
|
| 527 |
|
|
cursorType <= 2'b00;
|
| 528 |
|
|
// 104x63
|
| 529 |
|
|
/*
|
| 530 |
|
|
windowTop <= 12'd26;
|
| 531 |
|
|
windowLeft <= 12'd260;
|
| 532 |
|
|
pixelWidth <= 4'd0;
|
| 533 |
|
|
pixelHeight <= 4'd1; // 525 pixels (408 with border)
|
| 534 |
|
|
*/
|
| 535 |
|
|
// 52x31
|
| 536 |
|
|
/*
|
| 537 |
|
|
// 84x47
|
| 538 |
|
|
windowTop <= 12'd16;
|
| 539 |
|
|
windowLeft <= 12'd90;
|
| 540 |
|
|
pixelWidth <= 4'd1; // 681 pixels
|
| 541 |
|
|
pixelHeight <= 4'd1; // 384 pixels
|
| 542 |
|
|
*/
|
| 543 |
|
|
// 48x29
|
| 544 |
|
|
if (num==4'd1) begin
|
| 545 |
|
|
windowTop <= 12'd4058;//12'd16;
|
| 546 |
|
|
windowLeft <= 12'd3956;//12'd3930;//12'd86;
|
| 547 |
|
|
pixelWidth <= 4'd0; // 800 pixels
|
| 548 |
|
|
pixelHeight <= 4'd0; // 600 pixels
|
| 549 |
|
|
numCols <= COLS;
|
| 550 |
|
|
numRows <= ROWS;
|
| 551 |
|
|
maxRowScan <= 5'd17;
|
| 552 |
|
|
maxScanpix <= 6'd11;
|
| 553 |
|
|
rBlink <= 3'b111; // 01 = non display
|
| 554 |
|
|
charOutDelay <= 8'd5;
|
| 555 |
|
|
end
|
| 556 |
|
|
else if (num==4'd2) begin
|
| 557 |
|
|
windowTop <= 12'd4032;//12'd16;
|
| 558 |
|
|
windowLeft <= 12'd3720;//12'd86;
|
| 559 |
|
|
pixelWidth <= 4'd0; // 800 pixels
|
| 560 |
|
|
pixelHeight <= 4'd0; // 600 pixels
|
| 561 |
|
|
numCols <= 40;
|
| 562 |
|
|
numRows <= 25;
|
| 563 |
|
|
maxRowScan <= 5'd7;
|
| 564 |
|
|
maxScanpix <= 6'd7;
|
| 565 |
|
|
rBlink <= 3'b111; // 01 = non display
|
| 566 |
|
|
charOutDelay <= 8'd6;
|
| 567 |
|
|
end
|
| 568 |
|
|
end
|
| 569 |
|
|
else begin
|
| 570 |
|
|
|
| 571 |
|
|
if (bcnt > 6'd10)
|
| 572 |
|
|
por <= 1'b0;
|
| 573 |
|
|
|
| 574 |
|
|
if (cs_reg & rwr_i) begin // register write ?
|
| 575 |
|
|
$display("TC Write: r%d=%h", rrm_adr, rdat_i);
|
| 576 |
|
|
case(radr_i[5:0])
|
| 577 |
|
|
6'd0: numCols <= rdat_i[7:0];
|
| 578 |
|
|
6'd1: numRows <= rdat_i[7:0];
|
| 579 |
|
|
6'd2: charOutDelay <= rdat_i;
|
| 580 |
|
|
6'd4: ;
|
| 581 |
|
|
6'd5: windowLeft[11:0] <= rdat_i;
|
| 582 |
|
|
6'd6: ;
|
| 583 |
|
|
6'd7: windowTop[11:0] <= rdat_i;
|
| 584 |
|
|
6'd8: maxRowScan <= rdat_i[4:0];
|
| 585 |
|
|
6'd9:
|
| 586 |
|
|
begin
|
| 587 |
|
|
pixelHeight <= rdat_i[7:4];
|
| 588 |
|
|
pixelWidth <= rdat_i[3:0]; // horizontal pixel width
|
| 589 |
|
|
end
|
| 590 |
|
|
6'd11: por <= rdat_i[0];
|
| 591 |
|
|
6'd12: controller_enable <= rdat_i[0];
|
| 592 |
|
|
6'd13: mcm <= rdat_i[0];
|
| 593 |
|
|
6'd14: yscroll <= rdat_i[4:0];
|
| 594 |
|
|
6'd15: xscroll <= rdat_i[5:0];
|
| 595 |
|
|
6'd16: txtTcCode <= rdat_i[7:0];
|
| 596 |
|
|
6'd20: bdrCode <= rdat_i[7:0];
|
| 597 |
|
|
6'd24: tileCode1 <= rdat_i[7:0];
|
| 598 |
|
|
6'd28: tileCode2 <= rdat_i[7:0];
|
| 599 |
|
|
6'd31: maxScanpix <= rdat_i[5:0];
|
| 600 |
|
|
6'd32:
|
| 601 |
|
|
begin
|
| 602 |
|
|
cursorEnd <= rdat_i[4:0]; // scan line sursor starts on
|
| 603 |
|
|
rBlink <= rdat_i[7:5];
|
| 604 |
|
|
end
|
| 605 |
|
|
6'd33:
|
| 606 |
|
|
begin
|
| 607 |
|
|
cursorStart <= rdat_i[4:0]; // scan line cursor ends on
|
| 608 |
|
|
cursorType <= rdat_i[7:6];
|
| 609 |
|
|
end
|
| 610 |
|
|
6'd34: cursorPos[15:12] <= rdat_i[3:0];
|
| 611 |
|
|
6'd35: cursorPos[11: 0] <= rdat_i;
|
| 612 |
|
|
6'd40: startAddress[15:12] <= rdat_i[3:0];
|
| 613 |
|
|
6'd41: startAddress[11: 0] <= rdat_i;
|
| 614 |
|
|
default: ;
|
| 615 |
|
|
endcase
|
| 616 |
|
|
end
|
| 617 |
|
|
end
|
| 618 |
|
|
|
| 619 |
|
|
|
| 620 |
|
|
//--------------------------------------------------------------------
|
| 621 |
|
|
//--------------------------------------------------------------------
|
| 622 |
|
|
|
| 623 |
|
|
// "Box" cursor bitmap
|
| 624 |
|
|
reg [7:0] curout;
|
| 625 |
|
|
always @*
|
| 626 |
|
|
case({cursorType,scanindex})
|
| 627 |
|
|
// Box cursor
|
| 628 |
|
|
5'b00_000: curout = 8'b11111110;
|
| 629 |
|
|
5'b00_001: curout = 8'b10000010;
|
| 630 |
|
|
5'b00_010: curout = 8'b10000010;
|
| 631 |
|
|
5'b00_011: curout = 8'b10000010;
|
| 632 |
|
|
5'b00_100: curout = 8'b10000010;
|
| 633 |
|
|
5'b00_101: curout = 8'b10000010;
|
| 634 |
|
|
5'b00_110: curout = 8'b10010010;
|
| 635 |
|
|
5'b00_111: curout = 8'b11111110;
|
| 636 |
|
|
// vertical bar cursor
|
| 637 |
|
|
5'b01_000: curout = 8'b11000000;
|
| 638 |
|
|
5'b01_001: curout = 8'b10000000;
|
| 639 |
|
|
5'b01_010: curout = 8'b10000000;
|
| 640 |
|
|
5'b01_011: curout = 8'b10000000;
|
| 641 |
|
|
5'b01_100: curout = 8'b10000000;
|
| 642 |
|
|
5'b01_101: curout = 8'b10000000;
|
| 643 |
|
|
5'b01_110: curout = 8'b10000000;
|
| 644 |
|
|
5'b01_111: curout = 8'b11000000;
|
| 645 |
|
|
// underline cursor
|
| 646 |
|
|
5'b10_000: curout = 8'b00000000;
|
| 647 |
|
|
5'b10_001: curout = 8'b00000000;
|
| 648 |
|
|
5'b10_010: curout = 8'b00000000;
|
| 649 |
|
|
5'b10_011: curout = 8'b00000000;
|
| 650 |
|
|
5'b10_100: curout = 8'b00000000;
|
| 651 |
|
|
5'b10_101: curout = 8'b00000000;
|
| 652 |
|
|
5'b10_110: curout = 8'b00000000;
|
| 653 |
|
|
5'b10_111: curout = 8'b11111111;
|
| 654 |
|
|
// Asterisk
|
| 655 |
|
|
5'b11_000: curout = 8'b00000000;
|
| 656 |
|
|
5'b11_001: curout = 8'b00000000;
|
| 657 |
|
|
5'b11_010: curout = 8'b00100100;
|
| 658 |
|
|
5'b11_011: curout = 8'b00011000;
|
| 659 |
|
|
5'b11_100: curout = 8'b01111110;
|
| 660 |
|
|
5'b11_101: curout = 8'b00011000;
|
| 661 |
|
|
5'b11_110: curout = 8'b00100100;
|
| 662 |
|
|
5'b11_111: curout = 8'b00000000;
|
| 663 |
|
|
endcase
|
| 664 |
|
|
|
| 665 |
|
|
|
| 666 |
|
|
//-------------------------------------------------------------
|
| 667 |
|
|
// Video Stuff
|
| 668 |
|
|
//-------------------------------------------------------------
|
| 669 |
|
|
|
| 670 |
|
|
wire pe_hsync;
|
| 671 |
|
|
wire pe_vsync;
|
| 672 |
|
|
edge_det edh1
|
| 673 |
|
|
(
|
| 674 |
|
|
.rst(rst_i),
|
| 675 |
|
|
.clk(vclk),
|
| 676 |
|
|
.ce(1'b1),
|
| 677 |
|
|
.i(hsync_i),
|
| 678 |
|
|
.pe(pe_hsync),
|
| 679 |
|
|
.ne(),
|
| 680 |
|
|
.ee()
|
| 681 |
|
|
);
|
| 682 |
|
|
|
| 683 |
|
|
edge_det edv1
|
| 684 |
|
|
(
|
| 685 |
|
|
.rst(rst_i),
|
| 686 |
|
|
.clk(vclk),
|
| 687 |
|
|
.ce(1'b1),
|
| 688 |
|
|
.i(vsync_i),
|
| 689 |
|
|
.pe(pe_vsync),
|
| 690 |
|
|
.ne(),
|
| 691 |
|
|
.ee()
|
| 692 |
|
|
);
|
| 693 |
|
|
|
| 694 |
|
|
// Horizontal counter:
|
| 695 |
|
|
//
|
| 696 |
|
|
/*
|
| 697 |
|
|
HVCounter uhv1
|
| 698 |
|
|
(
|
| 699 |
|
|
.rst(rst_i),
|
| 700 |
|
|
.vclk(vclk),
|
| 701 |
|
|
.pixcce(1'b1),
|
| 702 |
|
|
.sync(hsync_i),
|
| 703 |
|
|
.cnt_offs(windowLeft),
|
| 704 |
|
|
.pixsz(pixelWidth),
|
| 705 |
|
|
.maxpix(maxScanpix),
|
| 706 |
|
|
.nxt_pix(nhp),
|
| 707 |
|
|
.pos(col),
|
| 708 |
|
|
.nxt_pos(nxt_col),
|
| 709 |
|
|
.ctr(hctr)
|
| 710 |
|
|
);
|
| 711 |
|
|
*/
|
| 712 |
|
|
|
| 713 |
|
|
// Vertical counter:
|
| 714 |
|
|
//
|
| 715 |
|
|
/*
|
| 716 |
|
|
HVCounter uhv2
|
| 717 |
|
|
(
|
| 718 |
|
|
.rst(rst_i),
|
| 719 |
|
|
.vclk(vclk),
|
| 720 |
|
|
.pixcce(pe_hsync),
|
| 721 |
|
|
.sync(vsync_i),
|
| 722 |
|
|
.cnt_offs(windowTop),
|
| 723 |
|
|
.pixsz(pixelHeight),
|
| 724 |
|
|
.maxpix(maxRowScan),
|
| 725 |
|
|
.nxt_pix(),
|
| 726 |
|
|
.pos(row),
|
| 727 |
|
|
.nxt_pos(nxt_row),
|
| 728 |
|
|
.ctr(scanline)
|
| 729 |
|
|
);
|
| 730 |
|
|
*/
|
| 731 |
|
|
|
| 732 |
|
|
// We generally don't care about the exact reset point, unless debugging in
|
| 733 |
|
|
// simulation. The counters will eventually cycle to a proper state. A little
|
| 734 |
|
|
// bit of logic / routing can be avoided by omitting the reset.
|
| 735 |
|
|
`ifdef SIM
|
| 736 |
|
|
wire sym_rst = rst_i;
|
| 737 |
|
|
`else
|
| 738 |
|
|
wire sym_rst = 1'b0;
|
| 739 |
|
|
`endif
|
| 740 |
|
|
|
| 741 |
|
|
// Raw scanline counter
|
| 742 |
|
|
vid_counter #(12) u_vctr (.rst(sym_rst), .clk(vclk), .ce(pe_hsync), .ld(pe_vsync), .d(windowTop), .q(scanline), .tc());
|
| 743 |
|
|
vid_counter #(12) u_hctr (.rst(sym_rst), .clk(vclk), .ce(1'b1), .ld(pe_hsync), .d(windowLeft), .q(hctr), .tc());
|
| 744 |
|
|
|
| 745 |
|
|
// Vertical pixel height counter, synchronized to scanline #0
|
| 746 |
|
|
reg [3:0] vpx;
|
| 747 |
|
|
wire nvp = vpx==pixelHeight;
|
| 748 |
|
|
always @(posedge vclk)
|
| 749 |
|
|
if (sym_rst)
|
| 750 |
|
|
vpx <= 4'b0;
|
| 751 |
|
|
else begin
|
| 752 |
|
|
if (pe_hsync) begin
|
| 753 |
|
|
if (scanline==12'd0)
|
| 754 |
|
|
vpx <= 4'b0;
|
| 755 |
|
|
else if (nvp)
|
| 756 |
|
|
vpx <= 4'd0;
|
| 757 |
|
|
else
|
| 758 |
|
|
vpx <= vpx + 4'd1;
|
| 759 |
|
|
end
|
| 760 |
|
|
end
|
| 761 |
|
|
|
| 762 |
|
|
reg [3:0] hpx;
|
| 763 |
|
|
assign nhp = hpx==pixelWidth;
|
| 764 |
|
|
always @(posedge vclk)
|
| 765 |
|
|
if (sym_rst)
|
| 766 |
|
|
hpx <= 4'b0;
|
| 767 |
|
|
else begin
|
| 768 |
|
|
if (hctr==12'd0)
|
| 769 |
|
|
hpx <= 4'b0;
|
| 770 |
|
|
else if (nhp)
|
| 771 |
|
|
hpx <= 4'd0;
|
| 772 |
|
|
else
|
| 773 |
|
|
hpx <= hpx + 4'd1;
|
| 774 |
|
|
end
|
| 775 |
|
|
|
| 776 |
|
|
// The scanline row within a character bitmap
|
| 777 |
|
|
always @(posedge vclk)
|
| 778 |
|
|
if (sym_rst)
|
| 779 |
|
|
rowscan <= 5'd0;
|
| 780 |
|
|
else begin
|
| 781 |
|
|
if (pe_hsync & nvp) begin
|
| 782 |
|
|
if (scanline==12'd0)
|
| 783 |
|
|
rowscan <= yscroll;
|
| 784 |
|
|
else if (rowscan==maxRowScan)
|
| 785 |
|
|
rowscan <= 5'd0;
|
| 786 |
|
|
else
|
| 787 |
|
|
rowscan <= rowscan + 5'd1;
|
| 788 |
|
|
end
|
| 789 |
|
|
end
|
| 790 |
|
|
|
| 791 |
|
|
assign nxt_col = colscan==maxScanpix;
|
| 792 |
|
|
always @(posedge vclk)
|
| 793 |
|
|
if (sym_rst)
|
| 794 |
|
|
colscan <= 6'd0;
|
| 795 |
|
|
else begin
|
| 796 |
|
|
if (nhp) begin
|
| 797 |
|
|
if (hctr==12'd0)
|
| 798 |
|
|
colscan <= xscroll;
|
| 799 |
|
|
else if (nxt_col)
|
| 800 |
|
|
colscan <= 6'd0;
|
| 801 |
|
|
else
|
| 802 |
|
|
colscan <= colscan + 2'd1;
|
| 803 |
|
|
end
|
| 804 |
|
|
end
|
| 805 |
|
|
|
| 806 |
|
|
// The screen row
|
| 807 |
|
|
always @(posedge vclk)
|
| 808 |
|
|
if (sym_rst)
|
| 809 |
|
|
row <= 8'd0;
|
| 810 |
|
|
else begin
|
| 811 |
|
|
if (pe_hsync & nvp) begin
|
| 812 |
|
|
if (scanline==12'd0)
|
| 813 |
|
|
row <= 8'd0;
|
| 814 |
|
|
else if (rowscan==maxRowScan)
|
| 815 |
|
|
row <= row + 8'd1;
|
| 816 |
|
|
end
|
| 817 |
|
|
end
|
| 818 |
|
|
|
| 819 |
|
|
// The screen column
|
| 820 |
|
|
always @(posedge vclk)
|
| 821 |
|
|
if (sym_rst)
|
| 822 |
|
|
col <= 8'd0;
|
| 823 |
|
|
else begin
|
| 824 |
|
|
if (hctr==12'd0)
|
| 825 |
|
|
col <= 8'd0;
|
| 826 |
|
|
else if (nhp) begin
|
| 827 |
|
|
if (nxt_col)
|
| 828 |
|
|
col <= col + 8'd1;
|
| 829 |
|
|
end
|
| 830 |
|
|
end
|
| 831 |
|
|
|
| 832 |
|
|
// More useful, the offset of the start of the text display on a line.
|
| 833 |
|
|
always @(posedge vclk)
|
| 834 |
|
|
if (sym_rst)
|
| 835 |
|
|
rowcol <= 16'd0;
|
| 836 |
|
|
else begin
|
| 837 |
|
|
if (pe_hsync & nvp) begin
|
| 838 |
|
|
if (scanline==12'd0)
|
| 839 |
|
|
rowcol <= 8'd0;
|
| 840 |
|
|
else if (rowscan==maxRowScan)
|
| 841 |
|
|
rowcol <= rowcol + numCols;
|
| 842 |
|
|
end
|
| 843 |
|
|
end
|
| 844 |
|
|
|
| 845 |
|
|
// Takes 3 clock for scanline to become stable, but should be stable before any
|
| 846 |
|
|
// chars are displayed.
|
| 847 |
|
|
reg [13:0] rxmslp1;
|
| 848 |
|
|
always @(posedge vclk)
|
| 849 |
|
|
maxScanlinePlusOne <= maxRowScan + 4'd1;
|
| 850 |
|
|
//always @(posedge vclk)
|
| 851 |
|
|
// rxmslp1 <= row * maxScanlinePlusOne;
|
| 852 |
|
|
//always @(posedge vclk)
|
| 853 |
|
|
// scanline <= scanline - rxmslp1;
|
| 854 |
|
|
|
| 855 |
|
|
|
| 856 |
|
|
// Blink counter
|
| 857 |
|
|
//
|
| 858 |
|
|
always @(posedge vclk)
|
| 859 |
|
|
if (sym_rst)
|
| 860 |
|
|
bcnt <= 6'd0;
|
| 861 |
|
|
else begin
|
| 862 |
|
|
if (pe_vsync)
|
| 863 |
|
|
bcnt <= bcnt + 6'd1;
|
| 864 |
|
|
end
|
| 865 |
|
|
|
| 866 |
|
|
reg blink_en;
|
| 867 |
|
|
always @(posedge vclk)
|
| 868 |
|
|
blink_en <= (cursorPos+4==txtAddr) && (rowscan[4:0] >= cursorStart) && (rowscan[4:0] <= cursorEnd);
|
| 869 |
|
|
|
| 870 |
|
|
VT151 ub2
|
| 871 |
|
|
(
|
| 872 |
|
|
.e_n(!blink_en),
|
| 873 |
|
|
.s(rBlink),
|
| 874 |
|
|
.i0(1'b1), .i1(1'b0), .i2(bcnt[4]), .i3(bcnt[5]),
|
| 875 |
|
|
.i4(1'b1), .i5(1'b0), .i6(bcnt[4]), .i7(bcnt[5]),
|
| 876 |
|
|
.z(blink),
|
| 877 |
|
|
.z_n()
|
| 878 |
|
|
);
|
| 879 |
|
|
|
| 880 |
|
|
always @(posedge vclk)
|
| 881 |
|
|
if (ld_shft)
|
| 882 |
|
|
bkColor32 <= {txtZorder1,2'b00,txtBkColor};
|
| 883 |
|
|
always @(posedge vclk)
|
| 884 |
|
|
if (nhp)
|
| 885 |
|
|
bkColor32d <= bkColor32;
|
| 886 |
|
|
always @(posedge vclk)
|
| 887 |
|
|
if (ld_shft)
|
| 888 |
|
|
fgColor32 <= {txtZorder1,2'b00,txtFgColor};
|
| 889 |
|
|
always @(posedge vclk)
|
| 890 |
|
|
if (nhp)
|
| 891 |
|
|
fgColor32d <= fgColor32;
|
| 892 |
|
|
|
| 893 |
|
|
always @(posedge vclk)
|
| 894 |
|
|
if (ld_shft)
|
| 895 |
|
|
bgt <= txtBkCode1==txtTcCode;
|
| 896 |
|
|
always @(posedge vclk)
|
| 897 |
|
|
if (nhp)
|
| 898 |
|
|
bgtd <= bgt;
|
| 899 |
|
|
|
| 900 |
|
|
// Convert character bitmap to pixels
|
| 901 |
|
|
reg [63:0] charout1;
|
| 902 |
|
|
always @(posedge vclk)
|
| 903 |
|
|
charout1 <= blink ? (char_bmp ^ curout) : char_bmp;
|
| 904 |
|
|
|
| 905 |
|
|
// Convert parallel to serial
|
| 906 |
|
|
ParallelToSerial ups1
|
| 907 |
|
|
(
|
| 908 |
|
|
.rst(rst_i),
|
| 909 |
|
|
.clk(vclk),
|
| 910 |
|
|
.mcm(mcm),
|
| 911 |
|
|
.ce(nhp),
|
| 912 |
|
|
.ld(ld_shft),
|
| 913 |
|
|
.a(maxScanpix[5:3]),
|
| 914 |
|
|
.qin(2'b0),
|
| 915 |
|
|
.d(charout1),
|
| 916 |
|
|
.qh(pix)
|
| 917 |
|
|
);
|
| 918 |
|
|
/*
|
| 919 |
|
|
always_ff @(posedge vclk)
|
| 920 |
|
|
if (rst_i) begin
|
| 921 |
|
|
pix <= 64'd0;
|
| 922 |
|
|
end
|
| 923 |
|
|
else begin
|
| 924 |
|
|
if (nhp) begin
|
| 925 |
|
|
if (ld_shft)
|
| 926 |
|
|
pix <= charout1;
|
| 927 |
|
|
else begin
|
| 928 |
|
|
if (mcm)
|
| 929 |
|
|
pix <= {2'b00,pix[63:2]};
|
| 930 |
|
|
else
|
| 931 |
|
|
pix <= {1'b0,pix[63:1]};
|
| 932 |
|
|
end
|
| 933 |
|
|
end
|
| 934 |
|
|
end
|
| 935 |
|
|
*/
|
| 936 |
|
|
reg [1:0] pix1;
|
| 937 |
|
|
always_ff @(posedge vclk)
|
| 938 |
|
|
if (nhp)
|
| 939 |
|
|
pix1 <= pix[1:0];
|
| 940 |
|
|
|
| 941 |
|
|
// Pipelining Effect:
|
| 942 |
|
|
// - character output is delayed by 2 or 3 character times relative to the video counters
|
| 943 |
|
|
// depending on the resolution selected
|
| 944 |
|
|
// - this means we must adapt the blanking signal by shifting the blanking window
|
| 945 |
|
|
// two or three character times.
|
| 946 |
|
|
wire bpix = hctr[2] ^ rowscan[4];// ^ blink;
|
| 947 |
|
|
always_ff @(posedge vclk)
|
| 948 |
|
|
if (nhp)
|
| 949 |
|
|
iblank <= (row >= numRows) || (col >= numCols + charOutDelay) || (col < charOutDelay);
|
| 950 |
|
|
|
| 951 |
|
|
|
| 952 |
|
|
// Choose between input RGB and controller generated RGB
|
| 953 |
|
|
// Select between foreground and background colours.
|
| 954 |
|
|
// Note the ungated dot clock must be used here, or output from other
|
| 955 |
|
|
// controllers would not be visible if the clock were gated off.
|
| 956 |
|
|
always_ff @(posedge dot_clk_i)
|
| 957 |
|
|
casez({controller_enable&xonoff_i,blank_i,iblank,border_i,bpix,mcm,pix1})
|
| 958 |
|
|
8'b01??????: zrgb_o <= 32'h00000000;
|
| 959 |
|
|
8'b11??????: zrgb_o <= 32'h00000000;
|
| 960 |
|
|
8'b1001????: zrgb_o <= bdrColor;
|
| 961 |
|
|
//6'b10010?: zrgb_o <= 32'hFFBF2020;
|
| 962 |
|
|
//6'b10011?: zrgb_o <= 32'hFFDFDFDF;
|
| 963 |
|
|
8'b1000?00?: zrgb_o <= (zrgb_i[31:24] > bkColor32d[31:24]) ? zrgb_i : bkColor32d;
|
| 964 |
|
|
// 8'b1000?0?0: zrgb_o <= bkColor32d;
|
| 965 |
|
|
8'b1000?01?: zrgb_o <= fgColor32d; // ToDo: compare z-order
|
| 966 |
|
|
8'b1000?100: zrgb_o <= (zrgb_i[31:24] > bkColor32d[31:24]) ? zrgb_i : bkColor32d;
|
| 967 |
|
|
8'b1000?101: zrgb_o <= fgColor32d;
|
| 968 |
|
|
8'b1000?110: zrgb_o <= {8'hFF,tileColor1};
|
| 969 |
|
|
8'b1000?111: zrgb_o <= {8'hFF,tileColor2};
|
| 970 |
|
|
// 6'b1010?0: zrgb_o <= bgtd ? zrgb_i : bkColor32d;
|
| 971 |
|
|
// 6'b1010?1: zrgb_o <= fgColor32d;
|
| 972 |
|
|
default: zrgb_o <= zrgb_i;
|
| 973 |
|
|
endcase
|
| 974 |
|
|
|
| 975 |
|
|
endmodule
|
| 976 |
|
|
|