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

Subversion Repositories rtftextcontroller

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

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 30 robfinch
wire [20:0] txtBkCode1;
452
wire [20:0] txtFgCode1;
453
wire [5:0] txtZorder1;
454 29 robfinch
 
455 30 robfinch
delay #(.WID(21),.DEP(3)) udlyb (.clk(vclk), .ce(ld_shft), .i(screen_ram_out[36:16]), .o(txtBkCode1));
456
delay #(.WID(21),.DEP(3)) udlyf (.clk(vclk), .ce(ld_shft), .i(screen_ram_out[57:37]), .o(txtFgCode1));
457
delay #(.WID( 6),.DEP(3)) udlyz (.clk(vclk), .ce(ld_shft), .i(screen_ram_out[63:58]), .o(txtZorder1));
458
 
459
 
460 29 robfinch
//--------------------------------------------------------------------
461
// Light Pen
462
//--------------------------------------------------------------------
463
wire lpe;
464
edge_det u1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(lp_i), .pe(lpe), .ne(), .ee() );
465
 
466
always @(posedge clk_i)
467
        if (rst_i)
468
                penAddr <= 32'h0000_0000;
469
        else begin
470
                if (lpe)
471
                        penAddr <= txtAddr;
472
        end
473
 
474
 
475
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
476
// Register read port
477
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
478
always @*
479
        if (cs_reg) begin
480
                case(rrm_adr)
481
                4'd7:             rego <= penAddr;
482
                default:        rego <= rrm_o;
483
                endcase
484
        end
485
        else
486
                rego <= 64'h0000;
487
 
488
 
489
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
490
// Register write port
491
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
492
 
493
always @(posedge clk_i)
494
        if (rst_i) begin
495
          por <= 1'b1;
496
          controller_enable <= 1'b1;
497
    xscroll              <= 6'd0;
498
    yscroll              <= 6'd0;
499
    txtTcCode    <= 16'h1ff;
500
    bdrColor     <= 32'hFFBF2020;
501
    startAddress <= 16'h0000;
502
    fontAddress  <= 16'h0000;
503
    cursorStart  <= 5'd00;
504
    cursorEnd    <= 5'd31;
505
    cursorPos    <= 16'h0003;
506
    cursorType   <= 2'b00;
507
// 104x63
508
/*
509
                windowTop    <= 12'd26;
510
                windowLeft   <= 12'd260;
511
                pixelWidth   <= 4'd0;
512
                pixelHeight  <= 4'd1;           // 525 pixels (408 with border)
513
*/
514
// 52x31
515
/*
516
                // 84x47
517
                windowTop    <= 12'd16;
518
                windowLeft   <= 12'd90;
519
                pixelWidth   <= 4'd1;           // 681 pixels
520
                pixelHeight  <= 4'd1;           // 384 pixels
521
*/
522
                // 48x29
523
                if (num==4'd1) begin
524
      windowTop    <= 12'd4058;//12'd16;
525 30 robfinch
      windowLeft   <= 12'd3964;//12'd3930;//12'd86;
526 29 robfinch
      pixelWidth   <= 4'd0;             // 1280 pixels
527
      pixelHeight  <= 4'd0;             // 720 pixels
528
      numCols      <= COLS;
529
      numRows      <= ROWS;
530
      maxRowScan  <= 6'd17;
531
      maxScanpix   <= 6'd11;
532
      rBlink       <= 3'b111;           // 01 = non display
533
      charOutDelay <= 8'd7;
534
                end
535
                else if (num==4'd2) begin
536
      windowTop    <= 12'd4032;//12'd16;
537
      windowLeft   <= 12'd3720;//12'd86;
538
      pixelWidth   <= 4'd0;        // 800 pixels
539
      pixelHeight  <= 4'd0;        // 600 pixels
540
      numCols      <= 40;
541
      numRows      <= 25;
542
      maxRowScan  <= 6'd7;
543
      maxScanpix   <= 6'd7;
544
      rBlink       <= 3'b111;        // 01 = non display
545
      charOutDelay <= 8'd6;
546
                end
547
        end
548
        else begin
549
 
550
                if (bcnt > 6'd10)
551
                        por <= 1'b0;
552
 
553
                if (cs_reg & rwr_i) begin       // register write ?
554
                        $display("TC Write: r%d=%h", rrm_adr, rdat_i);
555
                        case(rrm_adr)
556
                        4'd0:   begin
557
                                        if (rsel_i[0]) numCols    <= rdat_i[7:0];
558
                                        if (rsel_i[1]) numRows    <= rdat_i[15:8];
559
                                        if (rsel_i[2]) charOutDelay <= rdat_i[23:16];
560
                                        if (rsel_i[4]) windowLeft[7:0] <= rdat_i[39:32];
561
                                        if (rsel_i[5]) windowLeft[11:8] <= rdat_i[43:40];
562
                                        if (rsel_i[6]) windowTop[7:0]  <= rdat_i[55:48];
563
                                        if (rsel_i[7]) windowTop[11:8]  <= rdat_i[59:56];
564
                                        end
565
                        4'd1:
566
                                begin
567
                                        if (rsel_i[0]) maxRowScan <= rdat_i[5:0];
568
                                        if (rsel_i[1]) begin
569
                                                pixelHeight <= rdat_i[15:12];
570
                                                pixelWidth  <= rdat_i[11:8];    // horizontal pixel width
571
                                        end
572
                                        if (rsel_i[2]) maxScanpix <= rdat_i[21:16];
573
                                        if (rsel_i[3]) por <= rdat_i[24];
574
                                        if (rsel_i[4]) controller_enable <= rdat_i[32];
575
                                        if (rsel_i[6]) yscroll <= rdat_i[53:48];
576
                                        if (rsel_i[7]) xscroll <= rdat_i[61:56];
577
                                end
578
                        4'd2:   // Color Control
579
                                begin
580
                                        if (rsel_i[0]) txtTcCode[7:0] <= rdat_i[7:0];
581
                                        if (rsel_i[1]) txtTcCode[15:8] <= rdat_i[15:8];
582
                                        if (rsel_i[2]) txtTcCode[20:16] <= rdat_i[20:16];
583
                                        if (rsel_i[4]) bdrColor[7:0] <= dat_i[39:32];
584
                                        if (rsel_i[5]) bdrColor[15:8] <= dat_i[47:40];
585
                                        if (rsel_i[6]) bdrColor[23:16] <= dat_i[55:48];
586
                                        if (rsel_i[7]) bdrColor[31:24] <= dat_i[63:56];
587
                                end
588
                        4'd3:   // Cursor Control
589
                                begin
590
                                        if (rsel_i[0]) begin
591
                                                cursorEnd <= rdat_i[4:0];       // scan line sursor starts on
592
                                                rBlink      <= rdat_i[7:5];
593
                                        end
594
                                        if (rsel_i[1]) begin
595
                                                cursorStart <= rdat_i[12:8];    // scan line cursor ends on
596
                                                cursorType  <= rdat_i[15:14];
597
                                        end
598
                                        if (rsel_i[4]) cursorPos[7:0] <= rdat_i[39:32];
599
                                        if (rsel_i[5]) cursorPos[15:8] <= rdat_i[47:40];
600
                                end
601
                        4'd4:   // Page flipping / scrolling
602
                                begin
603
                                        if (rsel_i[0]) startAddress[7:0] <= rdat_i[7:0];
604
                                        if (rsel_i[1]) startAddress[15:8] <= rdat_i[15:8];
605
                                end
606
                  4'd5:
607
                    begin
608
                      if (rsel_i[0]) fontAddress[7:0] <= rdat_i[7:0];
609
                      if (rsel_i[1]) fontAddress[15:8] <= rdat_i[15:8];
610
                    end
611
                        default: ;
612
                        endcase
613
                end
614
        end
615
 
616
 
617
//--------------------------------------------------------------------
618
//--------------------------------------------------------------------
619
 
620
// "Box" cursor bitmap
621
(* ram_style="block" *)
622
reg [31:0] curram [0:511];
623
reg [31:0] curout, curout1;
624
initial begin
625
        // Box cursor
626
  curram[0] = 8'b11111110;
627
  curram[1] = 8'b10000010;
628
  curram[2] = 8'b10000010;
629
  curram[3] = 8'b10000010;
630
  curram[4] = 8'b10000010;
631
  curram[5] = 8'b10000010;
632
  curram[6] = 8'b10010010;
633
  curram[7] = 8'b11111110;
634
        // vertical bar cursor
635
  curram[32] = 8'b11000000;
636
  curram[33] = 8'b10000000;
637
  curram[34] = 8'b10000000;
638
  curram[35] = 8'b10000000;
639
  curram[36] = 8'b10000000;
640
  curram[37] = 8'b10000000;
641
  curram[38] = 8'b10000000;
642
  curram[39] = 8'b11000000;
643
        // underline cursor
644
  curram[64] = 8'b00000000;
645
  curram[65] = 8'b00000000;
646
  curram[66] = 8'b00000000;
647
  curram[67] = 8'b00000000;
648
  curram[68] = 8'b00000000;
649
  curram[69] = 8'b00000000;
650
  curram[70] = 8'b00000000;
651
  curram[71] = 8'b11111111;
652
        // Asterisk
653
  curram[96] = 8'b00000000;
654
  curram[97] = 8'b00000000;
655
  curram[98] = 8'b00100100;
656
  curram[99] = 8'b00011000;
657
  curram[100] = 8'b01111110;
658
  curram[101] = 8'b00011000;
659
  curram[102] = 8'b00100100;
660
  curram[103] = 8'b00000000;
661
end
662
always @(posedge vclk)
663
  if (ld_shft)
664
          curout1 <= curram[{cursorType,rowscan}];
665
always @(posedge vclk)
666
  curout <= curout1;
667
 
668
//-------------------------------------------------------------
669
// Video Stuff
670
//-------------------------------------------------------------
671
 
672
wire pe_hsync;
673
wire pe_vsync;
674
edge_det edh1
675
(
676
        .rst(rst_i),
677
        .clk(vclk),
678
        .ce(1'b1),
679
        .i(hsync_i),
680
        .pe(pe_hsync),
681
        .ne(),
682
        .ee()
683
);
684
 
685
edge_det edv1
686
(
687
        .rst(rst_i),
688
        .clk(vclk),
689
        .ce(1'b1),
690
        .i(vsync_i),
691
        .pe(pe_vsync),
692
        .ne(),
693
        .ee()
694
);
695
 
696
// Horizontal counter:
697
//
698
/*
699
HVCounter uhv1
700
(
701
        .rst(rst_i),
702
        .vclk(vclk),
703
        .pixcce(1'b1),
704
        .sync(hsync_i),
705
        .cnt_offs(windowLeft),
706
        .pixsz(pixelWidth),
707
        .maxpix(maxScanpix),
708
        .nxt_pix(nhp),
709
        .pos(col),
710
        .nxt_pos(nxt_col),
711
        .ctr(hctr)
712
);
713
*/
714
 
715
// Vertical counter:
716
//
717
/*
718
HVCounter uhv2
719
(
720
        .rst(rst_i),
721
        .vclk(vclk),
722
        .pixcce(pe_hsync),
723
        .sync(vsync_i),
724
        .cnt_offs(windowTop),
725
        .pixsz(pixelHeight),
726
        .maxpix(maxRowScan),
727
        .nxt_pix(),
728
        .pos(row),
729
        .nxt_pos(nxt_row),
730
        .ctr(scanline)
731
);
732
*/
733
 
734
// We generally don't care about the exact reset point, unless debugging in
735
// simulation. The counters will eventually cycle to a proper state. A little
736
// bit of logic / routing can be avoided by omitting the reset.
737
`ifdef SIM
738
wire sym_rst = rst_i;
739
`else
740
wire sym_rst = 1'b0;
741
`endif
742
 
743
// Raw scanline counter
744
vid_counter #(12) u_vctr (.rst(sym_rst), .clk(vclk), .ce(pe_hsync), .ld(pe_vsync), .d(windowTop), .q(scanline), .tc());
745
vid_counter #(12) u_hctr (.rst(sym_rst), .clk(vclk), .ce(1'b1), .ld(pe_hsync), .d(windowLeft), .q(hctr), .tc());
746
 
747
// Vertical pixel height counter, synchronized to scanline #0
748
reg [3:0] vpx;
749
wire nvp = vpx==pixelHeight;
750
always @(posedge vclk)
751
if (sym_rst)
752
        vpx <= 4'b0;
753
else begin
754
        if (pe_hsync) begin
755
                if (scanline==12'd0)
756
                        vpx <= 4'b0;
757
                else if (nvp)
758
                        vpx <= 4'd0;
759
                else
760
                        vpx <= vpx + 4'd1;
761
        end
762
end
763
 
764
reg [3:0] hpx;
765
assign nhp = hpx==pixelWidth;
766
always @(posedge vclk)
767
if (sym_rst)
768
        hpx <= 4'b0;
769
else begin
770
        if (hctr==12'd0)
771
                hpx <= 4'b0;
772
        else if (nhp)
773
                hpx <= 4'd0;
774
        else
775
                hpx <= hpx + 4'd1;
776
end
777
 
778
// The scanline row within a character bitmap
779
always @(posedge vclk)
780
if (sym_rst)
781
        rowscan <= 6'd0;
782
else begin
783
        if (pe_hsync & nvp) begin
784
                if (scanline==12'd0)
785
                        rowscan <= yscroll;
786
                else if (rowscan==maxRowScan)
787
                        rowscan <= 6'd0;
788
                else
789
                        rowscan <= rowscan + 1'd1;
790
        end
791
end
792
 
793
assign nxt_col = colscan==maxScanpix;
794
always @(posedge vclk)
795
if (sym_rst)
796
        colscan <= 6'd0;
797
else begin
798
        if (nhp) begin
799
                if (hctr==12'd0)
800
                        colscan <= xscroll;
801
                else if (nxt_col)
802
                        colscan <= 6'd0;
803
                else
804
                        colscan <= colscan + 1'd1;
805
        end
806
end
807
 
808
// The screen row
809
always @(posedge vclk)
810
if (sym_rst)
811
        row <= 8'd0;
812
else begin
813
        if (pe_hsync & nvp) begin
814
                if (scanline==12'd0)
815
                        row <= 8'd0;
816
                else if (rowscan==maxRowScan)
817
                        row <= row + 8'd1;
818
        end
819
end
820
 
821
// The screen column
822
always @(posedge vclk)
823
if (sym_rst)
824
        col <= 8'd0;
825
else begin
826
        if (hctr==12'd0)
827
                col <= 8'd0;
828
        else if (nhp) begin
829
                if (nxt_col)
830
                        col <= col + 8'd1;
831
        end
832
end
833
 
834
// More useful, the offset of the start of the text display on a line.
835
always @(posedge vclk)
836
if (sym_rst)
837
        rowcol <= 16'd0;
838
else begin
839
        if (pe_hsync & nvp) begin
840
                if (scanline==12'd0)
841
                        rowcol <= 8'd0;
842
                else if (rowscan==maxRowScan)
843
                        rowcol <= rowcol + numCols;
844
        end
845
end
846
 
847
// Takes 3 clock for scanline to become stable, but should be stable before any
848
// chars are displayed.
849
reg [13:0] rxmslp1;
850
always @(posedge vclk)
851
        maxScanlinePlusOne <= maxRowScan + 1'd1;
852
//always @(posedge vclk)
853
//      rxmslp1 <= row * maxScanlinePlusOne;
854
//always @(posedge vclk)
855
//      scanline <= scanline - rxmslp1;
856
 
857
 
858
// Blink counter
859
//
860
always @(posedge vclk)
861
if (sym_rst)
862
        bcnt <= 6'd0;
863
else begin
864
        if (pe_vsync)
865
                bcnt <= bcnt + 6'd1;
866
end
867
 
868
reg blink_en;
869
always @(posedge vclk)
870
        blink_en <= (cursorPos+3==txtAddr) && (rowscan >= cursorStart) && (rowscan <= cursorEnd);
871
 
872
VT151 ub2
873
(
874
        .e_n(!blink_en),
875
        .s(rBlink),
876
        .i0(1'b1), .i1(1'b0), .i2(bcnt[4]), .i3(bcnt[5]),
877
        .i4(1'b1), .i5(1'b0), .i6(bcnt[4]), .i7(bcnt[5]),
878
        .z(blink),
879
        .z_n()
880
);
881
 
882
always @(posedge vclk)
883 30 robfinch
  if (ld_shft)
884
    bkColor32 <= {txtZorder1,2'b00,txtBkCode1[20:14],1'b0,txtBkCode1[13:7],1'b0,txtBkCode1[6:0],1'b0};
885 29 robfinch
always @(posedge vclk)
886
        if (nhp)
887
                bkColor32d <= bkColor32;
888 30 robfinch
 
889 29 robfinch
always @(posedge vclk)
890 30 robfinch
  if (ld_shft)
891
    fgColor32 <= {txtZorder1,2'b00,txtFgCode1[20:14],1'b0,txtFgCode1[13:7],1'b0,txtFgCode1[6:0],1'b0};
892 29 robfinch
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.