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

Subversion Repositories rtftextcontroller

[/] [rtftextcontroller/] [trunk/] [rtl/] [verilog/] [GFX_TextController.sv] - Blame information for rev 29

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

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

powered by: WebSVN 2.1.0

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