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 128kB memory region to be reserved.
|
54 |
|
|
//
|
55 |
|
|
// Memory Map:
|
56 |
|
|
// 00000-0FFFF display ram
|
57 |
|
|
// 10000-1FEFF character bitmap ram
|
58 |
|
|
// 1FF00-1FFFF controller registers
|
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 |
|
|
// 08h
|
70 |
|
|
// 5- 0 nnnnnn char height in pixels, maximum scan line
|
71 |
|
|
// 11- 8 wwww pixel size - width
|
72 |
|
|
// 15-12 hhhh pixel size - height
|
73 |
|
|
// 21-16 nnnnnn char width in pixels
|
74 |
|
|
// 24 r reset state bit
|
75 |
|
|
// 32 e controller enable
|
76 |
|
|
// 40 m multi-color mode
|
77 |
|
|
// 48-52 nnnnn yscroll
|
78 |
|
|
// 56-60 nnnnn xscroll
|
79 |
|
|
// 10h
|
80 |
|
|
// 30- 0 cccccccc cccccccc color code for transparent background RGB 4,9,9,9 (only RGB 7,7,7 used)
|
81 |
|
|
// 63-32 cccc...cccc border color ZRGB 4,9,9,9
|
82 |
|
|
// 18h
|
83 |
|
|
// 30- 0 cccccccc cccccccc tile color code 1
|
84 |
|
|
// 62-32 cccccccc cccccccc tile color code 2
|
85 |
|
|
// 20h
|
86 |
|
|
// 4- 0 eeeee cursor end
|
87 |
|
|
// 7- 5 bbb blink control
|
88 |
|
|
// BP: 00=no blink
|
89 |
|
|
// BP: 01=no display
|
90 |
|
|
// BP: 10=1/16 field rate blink
|
91 |
|
|
// BP: 11=1/32 field rate blink
|
92 |
|
|
// 12- 8 sssss cursor start
|
93 |
|
|
// 15-13 ttt cursor image type (none, box, underline, sidebar, checker, solid
|
94 |
|
|
// 47-32 aaaaaaaa aaaaaaaa cursor position
|
95 |
|
|
// 28h
|
96 |
|
|
// 15- 0 aaaaaaaa aaaaaaaa start address (index into display memory)
|
97 |
|
|
// 30h
|
98 |
|
|
// 15- 0 aaaaaaaa aaaaaaaa font address in char bitmap memory
|
99 |
|
|
// 31-24 dddddd font ascent
|
100 |
|
|
// 63-32 nnnnnnnn nnnnnnnn font ram lock "LOCK" or "UNLK"
|
101 |
|
|
//--------------------------------------------------------------------
|
102 |
|
|
//
|
103 |
|
|
// ============================================================================
|
104 |
|
|
|
105 |
|
|
//`define USE_CLOCK_GATE
|
106 |
|
|
|
107 |
|
|
module rfTextController(
|
108 |
|
|
rst_i, clk_i, cs_i,
|
109 |
|
|
cti_i, cyc_i, stb_i, ack_o, wr_i, sel_i, adr_i, dat_i, dat_o,
|
110 |
|
|
dot_clk_i, hsync_i, vsync_i, blank_i, border_i, zrgb_i, zrgb_o, xonoff_i
|
111 |
|
|
);
|
112 |
|
|
parameter num = 4'd1;
|
113 |
|
|
parameter COLS = 8'd64;
|
114 |
|
|
parameter ROWS = 8'd32;
|
115 |
|
|
parameter BUSWID = 64;
|
116 |
|
|
|
117 |
|
|
|
118 |
|
|
// Syscon
|
119 |
|
|
input rst_i; // reset
|
120 |
|
|
input clk_i; // clock
|
121 |
|
|
|
122 |
|
|
// Slave signals
|
123 |
|
|
input cs_i; // circuit select
|
124 |
|
|
input [2:0] cti_i;
|
125 |
|
|
input cyc_i; // valid bus cycle
|
126 |
|
|
input stb_i; // data strobe
|
127 |
|
|
output ack_o; // data acknowledge
|
128 |
|
|
input wr_i; // write
|
129 |
|
|
input [BUSWID/8-1:0] sel_i; // byte lane select
|
130 |
|
|
input [16:0] adr_i; // address
|
131 |
|
|
input [BUSWID-1:0] dat_i; // data input
|
132 |
|
|
output reg [BUSWID-1:0] dat_o; // data output
|
133 |
|
|
|
134 |
|
|
// Video signals
|
135 |
|
|
input dot_clk_i; // video dot clock
|
136 |
|
|
input hsync_i; // end of scan line
|
137 |
|
|
input vsync_i; // end of frame
|
138 |
|
|
input blank_i; // blanking signal
|
139 |
|
|
input border_i; // border area
|
140 |
|
|
input [39:0] zrgb_i; // input pixel stream
|
141 |
|
|
output reg [39:0] zrgb_o; // output pixel stream
|
142 |
|
|
input xonoff_i;
|
143 |
|
|
|
144 |
|
|
reg controller_enable;
|
145 |
|
|
reg [39:0] bkColor40, bkColor40d, bkColor40d2; // background color
|
146 |
|
|
reg [39:0] fgColor40, fgColor40d, fgColor40d2; // foreground color
|
147 |
|
|
|
148 |
|
|
wire [1:0] pix; // pixel value from character generator 1=on,0=off
|
149 |
|
|
|
150 |
|
|
reg por;
|
151 |
|
|
wire vclk;
|
152 |
|
|
assign txt_clk_o = vclk;
|
153 |
|
|
assign txt_we_o = por;
|
154 |
|
|
assign txt_sel_o = 8'hFF;
|
155 |
|
|
assign cbm_clk_o = vclk;
|
156 |
|
|
assign cbm_we_o = 1'b0;
|
157 |
|
|
assign cbm_sel_o = 8'hFF;
|
158 |
|
|
|
159 |
|
|
reg [63:0] rego;
|
160 |
|
|
reg [5:0] yscroll;
|
161 |
|
|
reg [5:0] xscroll;
|
162 |
|
|
reg [11:0] windowTop;
|
163 |
|
|
reg [11:0] windowLeft;
|
164 |
|
|
reg [ 7:0] numCols;
|
165 |
|
|
reg [ 7:0] numRows;
|
166 |
|
|
reg [ 7:0] charOutDelay;
|
167 |
|
|
reg [ 1:0] mode;
|
168 |
|
|
reg [ 5:0] maxRowScan;
|
169 |
|
|
reg [ 5:0] maxScanpix;
|
170 |
|
|
reg [1:0] tileWidth; // width of tile in bytes (0=1,1=2,2=4,3=8)
|
171 |
|
|
reg [ 5:0] cursorStart, cursorEnd;
|
172 |
|
|
reg [15:0] cursorPos;
|
173 |
|
|
reg [2:0] cursorType;
|
174 |
|
|
reg [15:0] startAddress;
|
175 |
|
|
reg [15:0] fontAddress;
|
176 |
|
|
reg font_locked;
|
177 |
|
|
reg [5:0] fontAscent;
|
178 |
|
|
reg [ 2:0] rBlink;
|
179 |
|
|
reg [31:0] bdrColor; // Border color
|
180 |
|
|
reg [ 3:0] pixelWidth; // horizontal pixel width in clock cycles
|
181 |
|
|
reg [ 3:0] pixelHeight; // vertical pixel height in scan lines
|
182 |
|
|
reg mcm; // multi-color mode
|
183 |
|
|
|
184 |
|
|
wire [11:0] hctr; // horizontal reference counter (counts clocks since hSync)
|
185 |
|
|
wire [11:0] scanline; // scan line
|
186 |
|
|
reg [ 7:0] row; // vertical reference counter (counts rows since vSync)
|
187 |
|
|
reg [ 7:0] col; // horizontal column
|
188 |
|
|
reg [ 5:0] rowscan; // scan line within row
|
189 |
|
|
reg [ 5:0] colscan; // pixel column number within cell
|
190 |
|
|
wire nxt_row; // when to increment the row counter
|
191 |
|
|
wire nxt_col; // when to increment the column counter
|
192 |
|
|
reg [ 5:0] bcnt; // blink timing counter
|
193 |
|
|
wire blink;
|
194 |
|
|
reg iblank;
|
195 |
|
|
reg [5:0] maxScanlinePlusOne;
|
196 |
|
|
|
197 |
|
|
wire nhp; // next horizontal pixel
|
198 |
|
|
wire ld_shft = nxt_col & nhp;
|
199 |
|
|
|
200 |
|
|
|
201 |
|
|
// display and timing signals
|
202 |
|
|
reg [15:0] txtAddr; // index into memory
|
203 |
|
|
reg [15:0] penAddr;
|
204 |
|
|
wire [63:0] screen_ram_out; // character code
|
205 |
|
|
wire [20:0] txtBkColor; // background color code
|
206 |
|
|
wire [20:0] txtFgColor; // foreground color code
|
207 |
|
|
wire [5:0] txtZorder;
|
208 |
|
|
reg [30:0] txtTcCode; // transparent color code
|
209 |
|
|
reg [30:0] tileColor1;
|
210 |
|
|
reg [30:0] tileColor2;
|
211 |
|
|
reg bgt, bgtd, bgtd2;
|
212 |
|
|
|
213 |
|
|
wire [63:0] tdat_o;
|
214 |
|
|
wire [63:0] chdat_o;
|
215 |
|
|
|
216 |
|
|
//--------------------------------------------------------------------
|
217 |
|
|
// bus interfacing
|
218 |
|
|
// Address Decoding
|
219 |
|
|
// I/O range Dx
|
220 |
|
|
//--------------------------------------------------------------------
|
221 |
|
|
// Register the inputs
|
222 |
|
|
reg cs_rom, cs_reg, cs_text, cs_any;
|
223 |
|
|
reg [16:0] radr_i;
|
224 |
|
|
reg [63:0] rdat_i;
|
225 |
|
|
reg rwr_i;
|
226 |
|
|
reg [7:0] rsel_i;
|
227 |
|
|
reg [7:0] wrs_i;
|
228 |
|
|
always_ff @(posedge clk_i)
|
229 |
|
|
cs_rom <= cs_i && cyc_i && stb_i && (adr_i[16:8] >= 9'h100 && adr_i[16:8] < 9'h1FF);
|
230 |
|
|
always_ff @(posedge clk_i)
|
231 |
|
|
cs_reg <= cs_i && cyc_i && stb_i && (adr_i[16:8] == 9'h1FF);
|
232 |
|
|
always_ff @(posedge clk_i)
|
233 |
|
|
cs_text <= cs_i && cyc_i && stb_i && (adr_i[16:8] < 9'h100);
|
234 |
|
|
always_ff @(posedge clk_i)
|
235 |
|
|
cs_any <= cs_i && cyc_i && stb_i;
|
236 |
|
|
always_ff @(posedge clk_i)
|
237 |
|
|
wrs_i <= BUSWID==64 ? {8{wr_i}} & sel_i :
|
238 |
|
|
adr_i[2] ? {{4{wr_i}} & sel_i,4'h0} : {4'h0,{4{wr_i}} & sel_i};
|
239 |
|
|
always_ff @(posedge clk_i)
|
240 |
|
|
rwr_i <= wr_i;
|
241 |
|
|
always_ff @(posedge clk_i)
|
242 |
|
|
rsel_i <= BUSWID==64 ? sel_i : adr_i[2] ? {sel_i,4'h0} : {4'h0,sel_i};
|
243 |
|
|
always_ff @(posedge clk_i)
|
244 |
|
|
radr_i <= adr_i;
|
245 |
|
|
always_ff @(posedge clk_i)
|
246 |
|
|
rdat_i <= BUSWID==64 ? dat_i : {2{dat_i}};
|
247 |
|
|
|
248 |
|
|
// Register outputs
|
249 |
|
|
always @(posedge clk_i)
|
250 |
|
|
if (BUSWID==64)
|
251 |
|
|
casez({cs_rom,cs_reg,cs_text})
|
252 |
|
|
3'b1??: dat_o <= chdat_o;
|
253 |
|
|
3'b01?: dat_o <= rego;
|
254 |
|
|
3'b001: dat_o <= tdat_o;
|
255 |
|
|
default: dat_o <= 'h0;
|
256 |
|
|
endcase
|
257 |
|
|
else if (BUSWID==32)
|
258 |
|
|
casez({cs_rom,cs_reg,cs_text})
|
259 |
|
|
3'b1??: dat_o <= radr_i[2] ? chdat_o[63:32] : chdat_o[31:0];
|
260 |
|
|
3'b01?: dat_o <= radr_i[2] ? rego[63:32] : rego[31:0];
|
261 |
|
|
3'b001: dat_o <= radr_i[2] ? tdat_o[63:32] : tdat_o[31:0];
|
262 |
|
|
default: dat_o <= 'd0;
|
263 |
|
|
endcase
|
264 |
|
|
else
|
265 |
|
|
dat_o <= 'd0;
|
266 |
|
|
|
267 |
|
|
//always @(posedge clk_i)
|
268 |
|
|
// if (cs_text) begin
|
269 |
|
|
// $display("TC WRite: %h %h", adr_i, dat_i);
|
270 |
|
|
// $stop;
|
271 |
|
|
// end
|
272 |
|
|
|
273 |
|
|
// - there is a four cycle latency for reads, an ack is generated
|
274 |
|
|
// after the synchronous RAM read
|
275 |
|
|
// - writes can be acknowledged right away.
|
276 |
|
|
|
277 |
|
|
ack_gen #(
|
278 |
|
|
.READ_STAGES(5),
|
279 |
|
|
.WRITE_STAGES(1),
|
280 |
|
|
.REGISTER_OUTPUT(1)
|
281 |
|
|
)
|
282 |
|
|
uag1 (
|
283 |
|
|
.clk_i(clk_i),
|
284 |
|
|
.ce_i(1'b1),
|
285 |
|
|
.i(cs_any),
|
286 |
|
|
.we_i(cs_any & rwr_i),
|
287 |
|
|
.o(ack_o),
|
288 |
|
|
.rid_i(0),
|
289 |
|
|
.wid_i(0),
|
290 |
|
|
.rid_o(),
|
291 |
|
|
.wid_o()
|
292 |
|
|
);
|
293 |
|
|
|
294 |
|
|
//--------------------------------------------------------------------
|
295 |
|
|
//--------------------------------------------------------------------
|
296 |
|
|
`ifdef USE_CLOCK_GATE
|
297 |
|
|
BUFHCE ucb1 (.I(dot_clk_i), .CE(controller_enable), .O(vclk));
|
298 |
|
|
`else
|
299 |
|
|
assign vclk = dot_clk_i;
|
300 |
|
|
`endif
|
301 |
|
|
|
302 |
|
|
//--------------------------------------------------------------------
|
303 |
|
|
// Video Memory
|
304 |
|
|
//--------------------------------------------------------------------
|
305 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
306 |
|
|
// Address Calculation:
|
307 |
|
|
// - Simple: the row times the number of cols plus the col plus the
|
308 |
|
|
// base screen address
|
309 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
310 |
|
|
|
311 |
|
|
reg [15:0] rowcol;
|
312 |
|
|
always_ff @(posedge vclk)
|
313 |
|
|
txtAddr <= startAddress + rowcol + col;
|
314 |
|
|
|
315 |
|
|
// Register read-back memory
|
316 |
|
|
// This core to be found under Memory-Cores folder
|
317 |
|
|
// Allows reading back of register values by shadowing them with ram
|
318 |
|
|
|
319 |
|
|
wire [3:0] rrm_adr = radr_i[6:3];
|
320 |
|
|
wire [63:0] rrm_o;
|
321 |
|
|
|
322 |
|
|
regReadbackMem #(.WID(8)) rrm0L
|
323 |
|
|
(
|
324 |
|
|
.wclk(clk_i),
|
325 |
|
|
.adr(rrm_adr),
|
326 |
|
|
.wce(cs_reg),
|
327 |
|
|
.we(rwr_i & rsel_i[0]),
|
328 |
|
|
.i(rdat_i[7:0]),
|
329 |
|
|
.o(rrm_o[7:0])
|
330 |
|
|
);
|
331 |
|
|
|
332 |
|
|
regReadbackMem #(.WID(8)) rrm0H
|
333 |
|
|
(
|
334 |
|
|
.wclk(clk_i),
|
335 |
|
|
.adr(rrm_adr),
|
336 |
|
|
.wce(cs_reg),
|
337 |
|
|
.we(rwr_i & rsel_i[1]),
|
338 |
|
|
.i(rdat_i[15:8]),
|
339 |
|
|
.o(rrm_o[15:8])
|
340 |
|
|
);
|
341 |
|
|
|
342 |
|
|
regReadbackMem #(.WID(8)) rrm1L
|
343 |
|
|
(
|
344 |
|
|
.wclk(clk_i),
|
345 |
|
|
.adr(rrm_adr),
|
346 |
|
|
.wce(cs_reg),
|
347 |
|
|
.we(rwr_i & rsel_i[2]),
|
348 |
|
|
.i(rdat_i[23:16]),
|
349 |
|
|
.o(rrm_o[23:16])
|
350 |
|
|
);
|
351 |
|
|
|
352 |
|
|
regReadbackMem #(.WID(8)) rrm1H
|
353 |
|
|
(
|
354 |
|
|
.wclk(clk_i),
|
355 |
|
|
.adr(rrm_adr),
|
356 |
|
|
.wce(cs_reg),
|
357 |
|
|
.we(rwr_i & rsel_i[3]),
|
358 |
|
|
.i(rdat_i[31:24]),
|
359 |
|
|
.o(rrm_o[31:24])
|
360 |
|
|
);
|
361 |
|
|
|
362 |
|
|
regReadbackMem #(.WID(8)) rrm2L
|
363 |
|
|
(
|
364 |
|
|
.wclk(clk_i),
|
365 |
|
|
.adr(rrm_adr),
|
366 |
|
|
.wce(cs_reg),
|
367 |
|
|
.we(rwr_i & rsel_i[4]),
|
368 |
|
|
.i(rdat_i[39:32]),
|
369 |
|
|
.o(rrm_o[39:32])
|
370 |
|
|
);
|
371 |
|
|
|
372 |
|
|
regReadbackMem #(.WID(8)) rrm2H
|
373 |
|
|
(
|
374 |
|
|
.wclk(clk_i),
|
375 |
|
|
.adr(rrm_adr),
|
376 |
|
|
.wce(cs_reg),
|
377 |
|
|
.we(rwr_i & rsel_i[5]),
|
378 |
|
|
.i(rdat_i[47:40]),
|
379 |
|
|
.o(rrm_o[47:40])
|
380 |
|
|
);
|
381 |
|
|
|
382 |
|
|
regReadbackMem #(.WID(8)) rrm3L
|
383 |
|
|
(
|
384 |
|
|
.wclk(clk_i),
|
385 |
|
|
.adr(rrm_adr),
|
386 |
|
|
.wce(cs_reg),
|
387 |
|
|
.we(rwr_i & rsel_i[6]),
|
388 |
|
|
.i(rdat_i[55:48]),
|
389 |
|
|
.o(rrm_o[55:48])
|
390 |
|
|
);
|
391 |
|
|
|
392 |
|
|
regReadbackMem #(.WID(8)) rrm3H
|
393 |
|
|
(
|
394 |
|
|
.wclk(clk_i),
|
395 |
|
|
.adr(rrm_adr),
|
396 |
|
|
.wce(cs_reg),
|
397 |
|
|
.we(rwr_i & rsel_i[7]),
|
398 |
|
|
.i(rdat_i[63:56]),
|
399 |
|
|
.o(rrm_o[63:56])
|
400 |
|
|
);
|
401 |
|
|
|
402 |
|
|
wire [31:0] lfsr1_o;
|
403 |
|
|
lfsr #(32) ulfsr1(rst_i, dot_clk_i, 1'b1, 1'b0, lfsr1_o);
|
404 |
|
|
wire [63:0] lfsr_o = {6'h20,
|
405 |
|
|
lfsr1_o[26:24],4'b0,lfsr1_o[23:21],4'b0,lfsr1_o[20:18],4'b0,
|
406 |
|
|
lfsr1_o[17:15],4'b0,lfsr1_o[14:12],4'b0,lfsr1_o[11:9],4'b0,
|
407 |
|
|
8'h00,lfsr1_o[8:0]
|
408 |
|
|
};
|
409 |
|
|
|
410 |
|
|
/* This snippit of code for performing burst accesses, under construction.
|
411 |
|
|
wire pe_cs;
|
412 |
|
|
edge_det u1(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(cs_text), .pe(pe_cs), .ne(), .ee() );
|
413 |
|
|
|
414 |
|
|
reg [14:0] ctr;
|
415 |
|
|
always @(posedge clk_i)
|
416 |
|
|
if (pe_cs) begin
|
417 |
|
|
if (cti_i==3'b000)
|
418 |
|
|
ctr <= adr_i[16:3];
|
419 |
|
|
else
|
420 |
|
|
ctr <= adr_i[16:3] + 12'd1;
|
421 |
|
|
cnt <= 3'b000;
|
422 |
|
|
end
|
423 |
|
|
else if (cs_text && cnt[2:0]!=3'b100 && cti_i!=3'b000) begin
|
424 |
|
|
ctr <= ctr + 2'd1;
|
425 |
|
|
cnt <= cnt + 3'd1;
|
426 |
|
|
end
|
427 |
|
|
|
428 |
|
|
reg [13:0] radr;
|
429 |
|
|
always @(posedge clk_i)
|
430 |
|
|
radr <= pe_cs ? adr_i[16:3] : ctr;
|
431 |
|
|
*/
|
432 |
|
|
|
433 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
434 |
|
|
// text screen RAM
|
435 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
436 |
|
|
rfTextScreenRam screen_ram1
|
437 |
|
|
(
|
438 |
|
|
.clka_i(clk_i),
|
439 |
|
|
.csa_i(cs_text),
|
440 |
|
|
.wea_i(rwr_i),
|
441 |
|
|
.sela_i(rsel_i),
|
442 |
|
|
.adra_i(radr_i[15:3]),
|
443 |
|
|
.data_i(rdat_i),
|
444 |
|
|
.data_o(tdat_o),
|
445 |
|
|
.clkb_i(vclk),
|
446 |
|
|
.csb_i(ld_shft|por),
|
447 |
|
|
.web_i(por),
|
448 |
|
|
.selb_i(8'hFF),
|
449 |
|
|
.adrb_i(txtAddr[12:0]),
|
450 |
|
|
.datb_i(lfsr_o),
|
451 |
|
|
.datb_o(screen_ram_out)
|
452 |
|
|
);
|
453 |
|
|
|
454 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
455 |
|
|
// Character bitmap RAM
|
456 |
|
|
// - room for 8160 8x8 characters
|
457 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
458 |
|
|
wire [63:0] char_bmp; // character ROM output
|
459 |
|
|
rfTextCharRam charRam0
|
460 |
|
|
(
|
461 |
|
|
.clk_i(clk_i),
|
462 |
|
|
.cs_i(cs_rom),
|
463 |
|
|
.we_i(rwr_i & ~font_locked),
|
464 |
|
|
.sel_i(rsel_i),
|
465 |
|
|
.adr_i(radr_i[15:3]),
|
466 |
|
|
.dat_i(rdat_i[63:0]),
|
467 |
|
|
.dat_o(chdat_o),
|
468 |
|
|
.dot_clk_i(vclk),
|
469 |
|
|
.ce_i(ld_shft),
|
470 |
|
|
.fontAddress_i(fontAddress),
|
471 |
|
|
.char_code_i(screen_ram_out[12:0]),
|
472 |
|
|
.maxScanpix_i(maxScanpix),
|
473 |
|
|
.maxscanline_i(maxScanlinePlusOne),
|
474 |
|
|
.scanline_i(rowscan[5:0]),
|
475 |
|
|
.bmp_o(char_bmp)
|
476 |
|
|
);
|
477 |
|
|
|
478 |
|
|
// pipeline delay - sync color with character bitmap output
|
479 |
|
|
reg [20:0] txtBkCode1;
|
480 |
|
|
reg [20:0] txtFgCode1;
|
481 |
|
|
reg [5:0] txtZorder1;
|
482 |
|
|
always @(posedge vclk)
|
483 |
|
|
if (ld_shft) txtBkCode1 <= screen_ram_out[36:16];
|
484 |
|
|
always @(posedge vclk)
|
485 |
|
|
if (ld_shft) txtFgCode1 <= screen_ram_out[57:37];
|
486 |
|
|
always @(posedge vclk)
|
487 |
|
|
if (ld_shft) txtZorder1 <= screen_ram_out[63:58];
|
488 |
|
|
|
489 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
490 |
|
|
// Register read port
|
491 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
492 |
|
|
always_comb
|
493 |
|
|
if (cs_reg)
|
494 |
|
|
rego <= rrm_o;
|
495 |
|
|
else
|
496 |
|
|
rego <= 64'h0000;
|
497 |
|
|
|
498 |
|
|
|
499 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
500 |
|
|
// Register write port
|
501 |
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
502 |
|
|
|
503 |
|
|
always_ff @(posedge clk_i)
|
504 |
|
|
if (rst_i) begin
|
505 |
|
|
por <= 1'b1;
|
506 |
|
|
mcm <= 1'b0;
|
507 |
|
|
controller_enable <= 1'b1;
|
508 |
|
|
xscroll <= 5'd0;
|
509 |
|
|
yscroll <= 5'd0;
|
510 |
|
|
txtTcCode <= 24'h1ff;
|
511 |
|
|
bdrColor <= 32'hFFBF2020;
|
512 |
|
|
startAddress <= 16'h0000;
|
513 |
|
|
fontAddress <= 16'h0000;
|
514 |
|
|
font_locked <= 1'b1;
|
515 |
|
|
fontAscent <= 6'd12;
|
516 |
|
|
cursorStart <= 5'd00;
|
517 |
|
|
cursorEnd <= 5'd31;
|
518 |
|
|
cursorPos <= 16'h0003;
|
519 |
|
|
cursorType <= 3'd4; // checker
|
520 |
|
|
// 104x63
|
521 |
|
|
/*
|
522 |
|
|
windowTop <= 12'd26;
|
523 |
|
|
windowLeft <= 12'd260;
|
524 |
|
|
pixelWidth <= 4'd0;
|
525 |
|
|
pixelHeight <= 4'd1; // 525 pixels (408 with border)
|
526 |
|
|
*/
|
527 |
|
|
// 52x31
|
528 |
|
|
/*
|
529 |
|
|
// 84x47
|
530 |
|
|
windowTop <= 12'd16;
|
531 |
|
|
windowLeft <= 12'd90;
|
532 |
|
|
pixelWidth <= 4'd1; // 681 pixels
|
533 |
|
|
pixelHeight <= 4'd1; // 384 pixels
|
534 |
|
|
*/
|
535 |
|
|
// 64x32
|
536 |
|
|
if (num==4'd1) begin
|
537 |
|
|
windowTop <= 12'd4058;//12'd16;
|
538 |
|
|
windowLeft <= 12'd3956;//12'd86;
|
539 |
|
|
pixelWidth <= 4'd0; // 800 pixels
|
540 |
|
|
pixelHeight <= 4'd0; // 600 pixels
|
541 |
|
|
numCols <= COLS;
|
542 |
|
|
numRows <= ROWS;
|
543 |
|
|
maxRowScan <= 6'd17;
|
544 |
|
|
maxScanpix <= 6'd11;
|
545 |
|
|
rBlink <= 3'b111; // 01 = non display
|
546 |
|
|
charOutDelay <= 8'd7;
|
547 |
|
|
end
|
548 |
|
|
else if (num==4'd2) begin
|
549 |
|
|
windowTop <= 12'd4032;//12'd16;
|
550 |
|
|
windowLeft <= 12'd3720;//12'd86;
|
551 |
|
|
pixelWidth <= 4'd0; // 800 pixels
|
552 |
|
|
pixelHeight <= 4'd0; // 600 pixels
|
553 |
|
|
numCols <= 40;
|
554 |
|
|
numRows <= 25;
|
555 |
|
|
maxRowScan <= 5'd7;
|
556 |
|
|
maxScanpix <= 6'd7;
|
557 |
|
|
rBlink <= 3'b111; // 01 = non display
|
558 |
|
|
charOutDelay <= 8'd6;
|
559 |
|
|
end
|
560 |
|
|
end
|
561 |
|
|
else begin
|
562 |
|
|
|
563 |
|
|
if (bcnt > 6'd10)
|
564 |
|
|
por <= 1'b0;
|
565 |
|
|
|
566 |
|
|
if (cs_reg & rwr_i) begin // register write ?
|
567 |
|
|
$display("TC Write: r%d=%h", rrm_adr, rdat_i);
|
568 |
|
|
case(rrm_adr)
|
569 |
|
|
4'd0: begin
|
570 |
|
|
if (rsel_i[0]) numCols <= rdat_i[7:0];
|
571 |
|
|
if (rsel_i[1]) numRows <= rdat_i[15:8];
|
572 |
|
|
if (rsel_i[2]) charOutDelay <= rdat_i[23:16];
|
573 |
|
|
if (rsel_i[4]) windowLeft[7:0] <= rdat_i[39:32];
|
574 |
|
|
if (rsel_i[5]) windowLeft[11:8] <= rdat_i[43:40];
|
575 |
|
|
if (rsel_i[6]) windowTop[7:0] <= rdat_i[55:48];
|
576 |
|
|
if (rsel_i[7]) windowTop[11:8] <= rdat_i[59:56];
|
577 |
|
|
end
|
578 |
|
|
4'd1:
|
579 |
|
|
begin
|
580 |
|
|
if (rsel_i[0]) maxRowScan <= rdat_i[4:0];
|
581 |
|
|
if (rsel_i[1]) begin
|
582 |
|
|
pixelHeight <= rdat_i[15:12];
|
583 |
|
|
pixelWidth <= rdat_i[11:8]; // horizontal pixel width
|
584 |
|
|
end
|
585 |
|
|
if (rsel_i[2]) maxScanpix <= rdat_i[20:16];
|
586 |
|
|
if (rsel_i[3]) por <= rdat_i[24];
|
587 |
|
|
if (rsel_i[4]) controller_enable <= rdat_i[32];
|
588 |
|
|
if (rsel_i[5]) mcm <= rdat_i[40];
|
589 |
|
|
if (rsel_i[6]) yscroll <= rdat_i[52:48];
|
590 |
|
|
if (rsel_i[7]) xscroll <= rdat_i[60:56];
|
591 |
|
|
end
|
592 |
|
|
4'd2: // Color Control
|
593 |
|
|
begin
|
594 |
|
|
if (rsel_i[0]) txtTcCode[7:0] <= rdat_i[7:0];
|
595 |
|
|
if (rsel_i[1]) txtTcCode[15:8] <= rdat_i[15:8];
|
596 |
|
|
if (rsel_i[2]) txtTcCode[23:16] <= rdat_i[23:16];
|
597 |
|
|
if (rsel_i[3]) txtTcCode[30:24] <= rdat_i[30:24];
|
598 |
|
|
if (rsel_i[4]) bdrColor[7:0] <= dat_i[39:32];
|
599 |
|
|
if (rsel_i[5]) bdrColor[15:8] <= dat_i[47:40];
|
600 |
|
|
if (rsel_i[6]) bdrColor[23:16] <= dat_i[55:48];
|
601 |
|
|
if (rsel_i[7]) bdrColor[31:24] <= dat_i[63:56];
|
602 |
|
|
end
|
603 |
|
|
4'd3: // Color Control 2
|
604 |
|
|
begin
|
605 |
|
|
if (rsel_i[0]) tileColor1[7:0] <= rdat_i[7:0];
|
606 |
|
|
if (rsel_i[1]) tileColor1[15:8] <= rdat_i[15:8];
|
607 |
|
|
if (rsel_i[2]) tileColor1[23:16] <= rdat_i[23:16];
|
608 |
|
|
if (rsel_i[3]) tileColor1[30:24] <= rdat_i[30:24];
|
609 |
|
|
if (rsel_i[4]) tileColor2[7:0] <= rdat_i[39:32];
|
610 |
|
|
if (rsel_i[5]) tileColor2[15:8] <= rdat_i[47:40];
|
611 |
|
|
if (rsel_i[6]) tileColor2[23:16] <= rdat_i[55:48];
|
612 |
|
|
if (rsel_i[7]) tileColor2[30:24] <= rdat_i[62:56];
|
613 |
|
|
end
|
614 |
|
|
4'd4: // Cursor Control
|
615 |
|
|
begin
|
616 |
|
|
if (rsel_i[0]) begin
|
617 |
|
|
cursorEnd <= rdat_i[4:0]; // scan line sursor starts on
|
618 |
|
|
rBlink <= rdat_i[7:5];
|
619 |
|
|
end
|
620 |
|
|
if (rsel_i[1]) begin
|
621 |
|
|
cursorStart <= rdat_i[12:8]; // scan line cursor ends on
|
622 |
|
|
cursorType <= rdat_i[15:13];
|
623 |
|
|
end
|
624 |
|
|
if (rsel_i[4]) cursorPos[7:0] <= rdat_i[39:32];
|
625 |
|
|
if (rsel_i[5]) cursorPos[15:8] <= rdat_i[47:40];
|
626 |
|
|
end
|
627 |
|
|
4'd5: // Page flipping / scrolling
|
628 |
|
|
begin
|
629 |
|
|
if (rsel_i[0]) startAddress[7:0] <= rdat_i[7:0];
|
630 |
|
|
if (rsel_i[1]) startAddress[15:8] <= rdat_i[15:8];
|
631 |
|
|
end
|
632 |
|
|
4'd6: //
|
633 |
|
|
begin
|
634 |
|
|
if (rsel_i[0]) fontAddress[7:0] <= rdat_i[7:0];
|
635 |
|
|
if (rsel_i[1]) fontAddress[15:8] <= rdat_i[15:8];
|
636 |
|
|
if (rsel_i[3]) fontAscent[5:0] <= rdat_i[5:0];
|
637 |
|
|
if (&rsel_i[7:4]) begin
|
638 |
|
|
if (rdat_i[63:32]=="LOCK")
|
639 |
|
|
font_locked <= 1'b1;
|
640 |
|
|
else if (rdat_i[63:32]=="UNLK")
|
641 |
|
|
font_locked <= 1'b0;
|
642 |
|
|
end
|
643 |
|
|
end
|
644 |
|
|
default: ;
|
645 |
|
|
endcase
|
646 |
|
|
end
|
647 |
|
|
end
|
648 |
|
|
|
649 |
|
|
|
650 |
|
|
//--------------------------------------------------------------------
|
651 |
|
|
// Cursor image is computed based on the font size, so the available
|
652 |
|
|
// hardware cursors are really simple. More sophisticated hardware
|
653 |
|
|
// cursors can be had via the sprite controller.
|
654 |
|
|
//--------------------------------------------------------------------
|
655 |
|
|
|
656 |
|
|
reg [31:0] curout;
|
657 |
|
|
integer n2;
|
658 |
|
|
always_ff @(posedge vclk)
|
659 |
|
|
if (ld_shft) begin
|
660 |
|
|
curout = 'd0;
|
661 |
|
|
case(cursorType)
|
662 |
|
|
// No cursor
|
663 |
|
|
3'd0: ;
|
664 |
|
|
// "Box" cursor
|
665 |
|
|
3'd1:
|
666 |
|
|
begin
|
667 |
|
|
case(rowscan)
|
668 |
|
|
maxRowScan,5'd0: curout = 32'hFFFFFFFF;
|
669 |
|
|
/*
|
670 |
|
|
maxRowScan-1:
|
671 |
|
|
if (rowscan==maxRowScan-1) begin
|
672 |
|
|
curout[maxScanpix[5:1]] = 1'b1;
|
673 |
|
|
curout[maxScanpix[5:1]+1] = 1'b1;
|
674 |
|
|
end
|
675 |
|
|
*/
|
676 |
|
|
default:
|
677 |
|
|
begin
|
678 |
|
|
curout[maxScanpix] = 1'b1;
|
679 |
|
|
curout[0] = 1'b1;
|
680 |
|
|
end
|
681 |
|
|
endcase
|
682 |
|
|
end
|
683 |
|
|
// Vertical Line cursor
|
684 |
|
|
3'd2: curout[maxScanpix] = 1'b1;
|
685 |
|
|
// Underline cursor
|
686 |
|
|
3'd3:
|
687 |
|
|
if (rowscan==fontAscent)
|
688 |
|
|
curout = 32'hFFFFFFFF;
|
689 |
|
|
// Checker cursor
|
690 |
|
|
3'd4: curout = rowscan[1] ? 32'h33333333 : 32'hCCCCCCCC;
|
691 |
|
|
// Solid cursor
|
692 |
|
|
3'd7: curout = 32'hFFFFFFFF;
|
693 |
|
|
default: curout = 32'hFFFFFFFF;
|
694 |
|
|
endcase
|
695 |
|
|
end
|
696 |
|
|
|
697 |
|
|
//-------------------------------------------------------------
|
698 |
|
|
// Video Stuff
|
699 |
|
|
//-------------------------------------------------------------
|
700 |
|
|
|
701 |
|
|
wire pe_hsync;
|
702 |
|
|
wire pe_vsync;
|
703 |
|
|
edge_det edh1
|
704 |
|
|
(
|
705 |
|
|
.rst(rst_i),
|
706 |
|
|
.clk(vclk),
|
707 |
|
|
.ce(1'b1),
|
708 |
|
|
.i(hsync_i),
|
709 |
|
|
.pe(pe_hsync),
|
710 |
|
|
.ne(),
|
711 |
|
|
.ee()
|
712 |
|
|
);
|
713 |
|
|
|
714 |
|
|
edge_det edv1
|
715 |
|
|
(
|
716 |
|
|
.rst(rst_i),
|
717 |
|
|
.clk(vclk),
|
718 |
|
|
.ce(1'b1),
|
719 |
|
|
.i(vsync_i),
|
720 |
|
|
.pe(pe_vsync),
|
721 |
|
|
.ne(),
|
722 |
|
|
.ee()
|
723 |
|
|
);
|
724 |
|
|
|
725 |
|
|
// We generally don't care about the exact reset point, unless debugging in
|
726 |
|
|
// simulation. The counters will eventually cycle to a proper state. A little
|
727 |
|
|
// bit of logic / routing can be avoided by omitting the reset.
|
728 |
|
|
`ifdef SIM
|
729 |
|
|
wire sym_rst = rst_i;
|
730 |
|
|
`else
|
731 |
|
|
wire sym_rst = 1'b0;
|
732 |
|
|
`endif
|
733 |
|
|
|
734 |
|
|
// Raw scanline counter
|
735 |
|
|
vid_counter #(12) u_vctr (.rst(sym_rst), .clk(vclk), .ce(pe_hsync), .ld(pe_vsync), .d(windowTop), .q(scanline), .tc());
|
736 |
|
|
vid_counter #(12) u_hctr (.rst(sym_rst), .clk(vclk), .ce(1'b1), .ld(pe_hsync), .d(windowLeft), .q(hctr), .tc());
|
737 |
|
|
|
738 |
|
|
// Vertical pixel height counter, synchronized to scanline #0
|
739 |
|
|
reg [3:0] vpx;
|
740 |
|
|
wire nvp = vpx==pixelHeight;
|
741 |
|
|
always @(posedge vclk)
|
742 |
|
|
if (sym_rst)
|
743 |
|
|
vpx <= 4'b0;
|
744 |
|
|
else begin
|
745 |
|
|
if (pe_hsync) begin
|
746 |
|
|
if (scanline==12'd0)
|
747 |
|
|
vpx <= 4'b0;
|
748 |
|
|
else if (nvp)
|
749 |
|
|
vpx <= 4'd0;
|
750 |
|
|
else
|
751 |
|
|
vpx <= vpx + 4'd1;
|
752 |
|
|
end
|
753 |
|
|
end
|
754 |
|
|
|
755 |
|
|
reg [3:0] hpx;
|
756 |
|
|
assign nhp = hpx==pixelWidth;
|
757 |
|
|
always @(posedge vclk)
|
758 |
|
|
if (sym_rst)
|
759 |
|
|
hpx <= 4'b0;
|
760 |
|
|
else begin
|
761 |
|
|
if (hctr==12'd0)
|
762 |
|
|
hpx <= 4'b0;
|
763 |
|
|
else if (nhp)
|
764 |
|
|
hpx <= 4'd0;
|
765 |
|
|
else
|
766 |
|
|
hpx <= hpx + 4'd1;
|
767 |
|
|
end
|
768 |
|
|
|
769 |
|
|
// The scanline row within a character bitmap
|
770 |
|
|
always @(posedge vclk)
|
771 |
|
|
if (sym_rst)
|
772 |
|
|
rowscan <= 5'd0;
|
773 |
|
|
else begin
|
774 |
|
|
if (pe_hsync & nvp) begin
|
775 |
|
|
if (scanline==12'd0)
|
776 |
|
|
rowscan <= yscroll;
|
777 |
|
|
else if (rowscan==maxRowScan)
|
778 |
|
|
rowscan <= 5'd0;
|
779 |
|
|
else
|
780 |
|
|
rowscan <= rowscan + 5'd1;
|
781 |
|
|
end
|
782 |
|
|
end
|
783 |
|
|
|
784 |
|
|
assign nxt_col = colscan==maxScanpix;
|
785 |
|
|
always @(posedge vclk)
|
786 |
|
|
if (sym_rst)
|
787 |
|
|
colscan <= 5'd0;
|
788 |
|
|
else begin
|
789 |
|
|
if (nhp) begin
|
790 |
|
|
if (hctr==12'd0)
|
791 |
|
|
colscan <= xscroll;
|
792 |
|
|
else if (nxt_col)
|
793 |
|
|
colscan <= 5'd0;
|
794 |
|
|
else
|
795 |
|
|
colscan <= colscan + 5'd1;
|
796 |
|
|
end
|
797 |
|
|
end
|
798 |
|
|
|
799 |
|
|
// The screen row
|
800 |
|
|
always @(posedge vclk)
|
801 |
|
|
if (sym_rst)
|
802 |
|
|
row <= 8'd0;
|
803 |
|
|
else begin
|
804 |
|
|
if (pe_hsync & nvp) begin
|
805 |
|
|
if (scanline==12'd0)
|
806 |
|
|
row <= 8'd0;
|
807 |
|
|
else if (rowscan==maxRowScan)
|
808 |
|
|
row <= row + 8'd1;
|
809 |
|
|
end
|
810 |
|
|
end
|
811 |
|
|
|
812 |
|
|
// The screen column
|
813 |
|
|
always @(posedge vclk)
|
814 |
|
|
if (sym_rst)
|
815 |
|
|
col <= 8'd0;
|
816 |
|
|
else begin
|
817 |
|
|
if (hctr==12'd0)
|
818 |
|
|
col <= 8'd0;
|
819 |
|
|
else if (nhp) begin
|
820 |
|
|
if (nxt_col)
|
821 |
|
|
col <= col + 8'd1;
|
822 |
|
|
end
|
823 |
|
|
end
|
824 |
|
|
|
825 |
|
|
// More useful, the offset of the start of the text display on a line.
|
826 |
|
|
always @(posedge vclk)
|
827 |
|
|
if (sym_rst)
|
828 |
|
|
rowcol <= 16'd0;
|
829 |
|
|
else begin
|
830 |
|
|
if (pe_hsync & nvp) begin
|
831 |
|
|
if (scanline==12'd0)
|
832 |
|
|
rowcol <= 8'd0;
|
833 |
|
|
else if (rowscan==maxRowScan)
|
834 |
|
|
rowcol <= rowcol + numCols;
|
835 |
|
|
end
|
836 |
|
|
end
|
837 |
|
|
|
838 |
|
|
// Takes 3 clock for scanline to become stable, but should be stable before any
|
839 |
|
|
// chars are displayed.
|
840 |
|
|
reg [13:0] rxmslp1;
|
841 |
|
|
always_ff @(posedge vclk)
|
842 |
|
|
maxScanlinePlusOne <= maxRowScan + 4'd1;
|
843 |
|
|
|
844 |
|
|
|
845 |
|
|
// Blink counter
|
846 |
|
|
//
|
847 |
|
|
always_ff @(posedge vclk)
|
848 |
|
|
if (sym_rst)
|
849 |
|
|
bcnt <= 6'd0;
|
850 |
|
|
else begin
|
851 |
|
|
if (pe_vsync)
|
852 |
|
|
bcnt <= bcnt + 6'd1;
|
853 |
|
|
end
|
854 |
|
|
|
855 |
|
|
reg blink_en;
|
856 |
|
|
always_ff @(posedge vclk)
|
857 |
|
|
blink_en <= (cursorPos+3==txtAddr);// && (rowscan[4:0] >= cursorStart) && (rowscan[4:0] <= cursorEnd);
|
858 |
|
|
|
859 |
|
|
VT151 ub2
|
860 |
|
|
(
|
861 |
|
|
.e_n(!blink_en),
|
862 |
|
|
.s(rBlink),
|
863 |
|
|
.i0(1'b1), .i1(1'b0), .i2(bcnt[4]), .i3(bcnt[5]),
|
864 |
|
|
.i4(1'b1), .i5(1'b0), .i6(bcnt[4]), .i7(bcnt[5]),
|
865 |
|
|
.z(blink),
|
866 |
|
|
.z_n()
|
867 |
|
|
);
|
868 |
|
|
|
869 |
|
|
always_ff @(posedge vclk)
|
870 |
|
|
if (ld_shft)
|
871 |
|
|
bkColor40 <= {txtZorder1[5:2],txtBkCode1[20:14],5'b0,txtBkCode1[13:7],5'b0,txtBkCode1[6:0],5'b0};
|
872 |
|
|
always_ff @(posedge vclk)
|
873 |
|
|
if (ld_shft)
|
874 |
|
|
bkColor40d <= bkColor40;
|
875 |
|
|
always_ff @(posedge vclk)
|
876 |
|
|
if (nhp)
|
877 |
|
|
bkColor40d2 <= bkColor40d;
|
878 |
|
|
always_ff @(posedge vclk)
|
879 |
|
|
if (ld_shft)
|
880 |
|
|
fgColor40 <= {txtZorder1[5:2],txtFgCode1[20:14],5'b0,txtFgCode1[13:7],5'b0,txtFgCode1[6:0],5'b0};
|
881 |
|
|
always_ff @(posedge vclk)
|
882 |
|
|
if (ld_shft)
|
883 |
|
|
fgColor40d <= fgColor40;
|
884 |
|
|
always_ff @(posedge vclk)
|
885 |
|
|
if (nhp)
|
886 |
|
|
fgColor40d2 <= fgColor40d;
|
887 |
|
|
|
888 |
|
|
always_ff @(posedge vclk)
|
889 |
|
|
if (ld_shft)
|
890 |
|
|
bgt <= txtBkCode1=={txtTcCode[26:20],txtTcCode[17:11],txtTcCode[8:2]};
|
891 |
|
|
always_ff @(posedge vclk)
|
892 |
|
|
if (ld_shft)
|
893 |
|
|
bgtd <= bgt;
|
894 |
|
|
always_ff @(posedge vclk)
|
895 |
|
|
if (nhp)
|
896 |
|
|
bgtd2 <= bgtd;
|
897 |
|
|
|
898 |
|
|
// Convert character bitmap to pixels
|
899 |
|
|
reg [63:0] charout1;
|
900 |
|
|
always_ff @(posedge vclk)
|
901 |
|
|
charout1 <= blink ? (char_bmp ^ curout) : char_bmp;
|
902 |
|
|
|
903 |
|
|
// Convert parallel to serial
|
904 |
|
|
rfTextShiftRegister ups1
|
905 |
|
|
(
|
906 |
|
|
.rst(rst_i),
|
907 |
|
|
.clk(vclk),
|
908 |
|
|
.mcm(mcm),
|
909 |
|
|
.ce(nhp),
|
910 |
|
|
.ld(ld_shft),
|
911 |
|
|
.a(maxScanpix[5:0]),
|
912 |
|
|
.qin(2'b0),
|
913 |
|
|
.d(charout1),
|
914 |
|
|
.qh(pix)
|
915 |
|
|
);
|
916 |
|
|
|
917 |
|
|
// Pipelining Effect:
|
918 |
|
|
// - character output is delayed by 2 or 3 character times relative to the video counters
|
919 |
|
|
// depending on the resolution selected
|
920 |
|
|
// - this means we must adapt the blanking signal by shifting the blanking window
|
921 |
|
|
// two or three character times.
|
922 |
|
|
wire bpix = hctr[2] ^ rowscan[4];// ^ blink;
|
923 |
|
|
always_ff @(posedge vclk)
|
924 |
|
|
if (nhp)
|
925 |
|
|
iblank <= (row >= numRows) || (col >= numCols + charOutDelay) || (col < charOutDelay);
|
926 |
|
|
|
927 |
|
|
|
928 |
|
|
// Choose between input RGB and controller generated RGB
|
929 |
|
|
// Select between foreground and background colours.
|
930 |
|
|
// Note the ungated dot clock must be used here, or output from other
|
931 |
|
|
// controllers would not be visible if the clock were gated off.
|
932 |
|
|
always_ff @(posedge dot_clk_i)
|
933 |
|
|
casez({controller_enable&xonoff_i,blank_i,iblank,border_i,bpix,mcm,pix})
|
934 |
|
|
8'b01??????: zrgb_o <= 40'h00000000;
|
935 |
|
|
8'b11??????: zrgb_o <= 40'h00000000;
|
936 |
|
|
8'b1001????: zrgb_o <= {bdrColor[30:27],bdrColor[26:18],3'b0,bdrColor[17:9],3'b0,bdrColor[8:0],3'b0};
|
937 |
|
|
8'b1000?00?: zrgb_o <= (zrgb_i[39:36] > bkColor40d2[39:36]) ? zrgb_i : bkColor40d2;
|
938 |
|
|
8'b1000?01?: zrgb_o <= fgColor40d2; // ToDo: compare z-order
|
939 |
|
|
8'b1000?100: zrgb_o <= (zrgb_i[39:36] > bkColor40d2[39:36]) ? zrgb_i : bkColor40d2;
|
940 |
|
|
8'b1000?101: zrgb_o <= fgColor40d2;
|
941 |
|
|
8'b1000?110: zrgb_o <= {tileColor1[30:27],tileColor1[26:18],3'b0,tileColor1[17:9],3'b0,tileColor1[8:0],3'b0};
|
942 |
|
|
8'b1000?111: zrgb_o <= {tileColor2[30:27],tileColor2[26:18],3'b0,tileColor2[17:9],3'b0,tileColor2[8:0],3'b0};
|
943 |
|
|
// 6'b1010?0: zrgb_o <= bgtd ? zrgb_i : bkColor32d;
|
944 |
|
|
default: zrgb_o <= zrgb_i;
|
945 |
|
|
endcase
|
946 |
|
|
|
947 |
|
|
endmodule
|
948 |
|
|
|