OpenCores
URL https://opencores.org/ocsvn/rtftextcontroller/rtftextcontroller/trunk

Subversion Repositories rtftextcontroller

[/] [rtftextcontroller/] [trunk/] [rtl/] [verilog/] [rfTextController.sv] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.