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

Subversion Repositories rf6809

[/] [rf6809/] [trunk/] [rtl/] [noc/] [video/] [rfTextController_x12.sv] - Blame information for rev 19

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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