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

Subversion Repositories rtf68ksys

[/] [rtf68ksys/] [trunk/] [rtl/] [verilog/] [rtfTextController.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
// ============================================================================
2
//      (C) 2006-2011  Robert Finch
3
//      robfinch@<remove>opencores.org
4
//
5
//      rtfTextController.v
6
//              text controller
7
//
8
// This source file is free software: you can redistribute it and/or modify 
9
// it under the terms of the GNU Lesser General Public License as published 
10
// by the Free Software Foundation, either version 3 of the License, or     
11
// (at your option) any later version.                                      
12
//                                                                          
13
// This source file is distributed in the hope that it will be useful,      
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
16
// GNU General Public License for more details.                             
17
//                                                                          
18
// You should have received a copy of the GNU General Public License        
19
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
20
//                                                                          
21
//
22
//      Text Controller
23
//
24
//      FEATURES
25
//
26
//      This core requires an external timing generator to provide horizontal
27
//      and vertical sync signals, but otherwise can be used as a display
28
//  controller on it's own. However, this core may also be embedded within
29
//  another core such as a VGA controller.
30
//
31
//      Window positions are referenced to the rising edge of the vertical and
32
//      horizontal sync pulses.
33
//
34
//      The core includes an embedded dual port RAM to hold the screen
35
//      characters.
36
//
37
//
38
//--------------------------------------------------------------------
39
// Registers
40
//
41
//      00 -         nnnnnnnn  number of columns (horizontal displayed number of characters)
42
//      01 -         nnnnnnnn  number of rows    (vertical displayed number of characters)
43
//      02 -       n nnnnnnnn  window left       (horizontal sync position - reference for left edge of displayed)
44
//      03 -       n nnnnnnnn  window top        (vertical sync position - reference for the top edge of displayed)
45
//      04 -         ---nnnnn  maximum scan line (char ROM max value is 7)
46
//              05 -         hhhhwwww  pixel size, hhhh=height,wwww=width
47
//      07 -         ---nnnnn  color code for transparent background
48
//      08 -         -BPnnnnn  cursor start / blink control
49
//                             BP: 00=no blink
50
//                             BP: 01=no display
51
//                             BP: 10=1/16 field rate blink
52
//                             BP: 11=1/32 field rate blink
53
//      09 -        ----nnnnn  cursor end
54
//      10 - aaaaaaaa aaaaaaaaa  start address (index into display memory)
55
//      11 - aaaaaaaa aaaaaaaaa  cursor position
56
//      12 - aaaaaaaa aaaaaaaaa  light pen position
57
//--------------------------------------------------------------------
58
//
59
// ============================================================================
60
 
61
module rtfTextController(
62
        rst_i, clk_i,
63
        cyc_i, stb_i, ack_o, we_i, sel_i, adr_i, dat_i, dat_o,
64
        lp, curpos,
65
        vclk, eol, eof, blank, border, rgbIn, rgbOut
66
);
67
parameter COLS = 12'd52;
68
parameter ROWS = 12'd31;
69
 
70
// Syscon
71
input  rst_i;                   // reset
72
input  clk_i;                   // clock
73
 
74
// Slave signals
75
input  cyc_i;                   // cycle valid
76
input  stb_i;                   // data strobe
77
output ack_o;                   // transfer acknowledge
78
input  we_i;                    // write
79
input  [ 1:0] sel_i;     // byte select
80
input  [31:0] adr_i;     // address
81
input  [15:0] dat_i;     // data input
82
output [15:0] dat_o;     // data output
83
reg    [15:0] dat_o;
84
 
85
//
86
input lp;                               // light pen
87
input [15:0] curpos;     // cursor position
88
 
89
// Video signals
90
input vclk;                             // video dot clock
91
input eol;                              // end of scan line
92
input eof;                              // end of frame
93
input blank;                    // blanking signal
94
input border;                   // border area
95
input [24:0] rgbIn;              // input pixel stream
96
output reg [24:0] rgbOut;        // output pixel stream
97
 
98
 
99
wire [23:0] bkColor24;   // background color
100
wire [23:0] fgColor24;   // foreground color
101
wire [23:0] tcColor24;   // transparent color
102
 
103
wire pix;                               // pixel value from character generator 1=on,0=off
104
 
105
reg [15:0] rego;
106
reg [11:0] windowTop;
107
reg [11:0] windowLeft;
108
reg [11:0] numCols;
109
reg [11:0] numRows;
110
reg [ 1:0] mode;
111
reg [ 4:0] maxScanline;
112
reg [ 4:0] maxScanpix;
113
reg [ 4:0] cursorStart, cursorEnd;
114
reg [15:0] cursorPos;
115
reg [15:0] startAddress;
116
reg [ 2:0] rBlink;
117
reg [ 3:0] bdrColorReg;
118
reg [ 3:0] pixelWidth;   // horizontal pixel width in clock cycles
119
reg [ 3:0] pixelHeight;  // vertical pixel height in scan lines
120
 
121
wire [11:0] hctr;                // horizontal reference counter (counts clocks since hSync)
122
wire [11:0] scanline;    // scan line
123
wire [11:0] row;         // vertical reference counter (counts rows since vSync)
124
wire [11:0] col;         // horizontal column
125
reg  [ 4:0] rowscan;     // scan line within row
126
wire nxt_row;                   // when to increment the row counter
127
wire nxt_col;                   // when to increment the column counter
128
wire [ 5:0] bcnt;                // blink timing counter
129
wire blink;
130
reg  iblank;
131
 
132
wire nhp;                               // next horizontal pixel
133
wire ld_shft = nxt_col & nhp;
134
 
135
 
136
// display and timing signals
137
reg [15:0] txtAddr;              // index into memory
138
reg [15:0] penAddr;
139
wire [8:0] txtOut;               // character code
140
wire [7:0] charOut;              // character ROM output
141
wire [3:0] txtBkCode;    // background color code
142
wire [4:0] txtFgCode;    // foreground color code
143
reg  [4:0] txtTcCode;    // transparent color code
144
reg  bgt;
145
 
146
wire [8:0] tdat_o;
147
wire [8:0] cdat_o;
148
wire [7:0] chdat_o;
149
 
150
wire [2:0] scanindex = scanline[2:0];
151
 
152
 
153
//--------------------------------------------------------------------
154
// Address Decoding
155
// I/O range FFDx
156
//--------------------------------------------------------------------
157
wire cs_text = cyc_i && stb_i && (adr_i[31:16]==16'hFFD0);
158
wire cs_color= cyc_i && stb_i && (adr_i[31:16]==16'hFFD1);
159
wire cs_rom  = cyc_i && stb_i && (adr_i[31:16]==16'hFFD2);
160
wire cs_reg  = cyc_i && stb_i && (adr_i[31: 8]==24'hFFDA_00);
161
 
162
 
163
always @(cs_text or cs_color or cs_rom or cs_reg or tdat_o or cdat_o or chdat_o or rego)
164
        if (cs_text) dat_o <= tdat_o;
165
        else if (cs_color) dat_o <= cdat_o;
166
        else if (cs_rom) dat_o <= chdat_o;
167
        else if (cs_reg) dat_o <= rego;
168
        else dat_o <= 16'h0000;
169
 
170
 
171
//--------------------------------------------------------------------
172
// Video Memory
173
//--------------------------------------------------------------------
174
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175
// Address Calculation:
176
//  - Simple: the row times the number of  cols plus the col plue the
177
//    base screen address
178
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
179
 
180
wire [17:0] rowcol = row * numCols;
181
always @(posedge vclk)
182
        txtAddr <= startAddress + rowcol + col;
183
 
184
// text screen RAM
185
syncRam4kx9_1rw1r textRam0
186
(
187
        .wclk(clk_i),
188
        .wadr(adr_i[13:1]),
189
        .i(dat_i),
190
        .wo(tdat_o),
191
        .wce(cs_text),
192
        .we(we_i),
193
        .wrst(1'b0),
194
 
195
        .rclk(vclk),
196
        .radr(txtAddr[12:0]),
197
        .o(txtOut),
198
        .rce(ld_shft),
199
        .rrst(1'b0)
200
);
201
 
202
// screen attribute RAM
203
syncRam4kx9_1rw1r colorRam0
204
(
205
        .wclk(clk_i),
206
        .wadr(adr_i[13:1]),
207
        .i(dat_i),
208
        .wo(cdat_o),
209
        .wce(cs_color),
210
        .we(we_i),
211
        .wrst(1'b0),
212
 
213
        .rclk(vclk),
214
        .radr(txtAddr[12:0]),
215
        .o({txtBkCode,txtFgCode}),
216
        .rce(ld_shft),
217
        .rrst(1'b0)
218
);
219
 
220
 
221
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
222
// Character bitmap ROM
223
// - room for 512 characters
224
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
225
syncRam4kx9_1rw1r charRam0
226
(
227
        .wclk(clk_i),
228
        .wadr(adr_i[11:0]),
229
        .i(dat_i),
230
        .wo(chdat_o),
231
        .wce(cs_rom),
232
        .we(we_i),
233
        .wrst(1'b0),
234
 
235
        .rclk(vclk),
236
        .radr({txtOut,rowscan[2:0]}),
237
        .o(charOut),
238
        .rce(ld_shft),
239
        .rrst(1'b0)
240
);
241
 
242
 
243
// pipeline delay - sync color with character bitmap output
244
reg [3:0] txtBkCode1;
245
reg [4:0] txtFgCode1;
246
always @(posedge vclk)
247
        if (nhp & ld_shft) txtBkCode1 <= txtBkCode;
248
always @(posedge vclk)
249
        if (nhp & ld_shft) txtFgCode1 <= txtFgCode;
250
 
251
//--------------------------------------------------------------------
252
// bus interfacing
253
// - there is a one cycle latency for reads, an ack is generated
254
//   after the synchronous RAM read
255
// - writes can be acknowledged right away.
256
//--------------------------------------------------------------------
257
reg ramRdy;
258
always @(posedge clk_i)
259
        ramRdy = cs_text|cs_rom|cs_color|cs_reg;
260
 
261
assign ack_o = (cyc_i & stb_i) ? (we_i ? (cs_text|cs_color|cs_rom|cs_reg) : ramRdy) : 1'b0;
262
 
263
 
264
//--------------------------------------------------------------------
265
// Registers
266
//
267
//      00 -         nnnnnnnn  number of columns (horizontal displayed number of characters)
268
//      01 -         nnnnnnnn  number of rows    (vertical displayed number of characters)
269
//      02 -       n nnnnnnnn  window left       (horizontal sync position - reference for left edge of displayed)
270
//      03 -       n nnnnnnnn  window top        (vertical sync position - reference for the top edge of displayed)
271
//      04 -         ---nnnnn  maximum scan line (char ROM max value is 7)
272
//              05 -         hhhhwwww  pixel size, hhhh=height,wwww=width
273
//      08 -         -BPnnnnn  cursor start / blink control
274
//                             BP: 00=no blink
275
//                             BP: 01=no display
276
//                             BP: 10=1/16 field rate blink
277
//                             BP: 11=1/32 field rate blink
278
//      09 -        ----nnnnn  cursor end
279
//      10 - aaaaaaaa aaaaaaaaa  start address (index into display memory)
280
//      11 - aaaaaaaa aaaaaaaaa  cursor position
281
//      12 - aaaaaaaa aaaaaaaaa  light pen position
282
//--------------------------------------------------------------------
283
 
284
//--------------------------------------------------------------------
285
// Light Pen
286
//--------------------------------------------------------------------
287
wire lpe;
288
edge_det u1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(lp), .pe(lpe), .ne(), .ee() );
289
 
290
always @(posedge clk_i)
291
        if (rst_i)
292
                penAddr <= 32'h0000_0000;
293
        else begin
294
                if (lpe)
295
                        penAddr <= txtAddr;
296
        end
297
 
298
 
299
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
300
// Register read port
301
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302
always @(cs_reg or cursorPos or penAddr or adr_i)
303
        if (cs_reg) begin
304
                case(adr_i[4:1])
305
                4'd0:           rego <= numCols;
306
                4'd1:           rego <= numRows;
307
                4'd11:          rego <= cursorPos;
308
                4'd12:          rego <= penAddr;
309
                default:        rego <= 16'h0000;
310
                endcase
311
        end
312
        else
313
                rego <= 16'h0000;
314
 
315
 
316
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
317
// Register write port
318
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
319
 
320
reg interlace;
321
always @(posedge clk_i)
322
        if (rst_i) begin
323
// 104x63
324
/*
325
                windowTop    <= 12'd26;
326
                windowLeft   <= 12'd260;
327
                pixelWidth   <= 4'd0;
328
                pixelHeight  <= 4'd1;           // 525 pixels (408 with border)
329
*/
330
// 52x31
331
                windowTop    <= 12'd14;
332
                windowLeft   <= 12'd117;
333
                pixelWidth   <= 4'd1;
334
                pixelHeight  <= 4'd3;           // 262 pixels (248 with border)
335
 
336
                numCols      <= COLS;
337
                numRows      <= ROWS;
338
                maxScanline  <= 5'd7;
339
                maxScanpix   <= 5'd7;
340
                rBlink       <= 3'b111;         // 01 = non display
341
                startAddress <= 16'h0000;
342
                cursorStart  <= 5'd00;
343
                cursorEnd    <= 5'd31;
344
                cursorPos    <= 16'h0003;
345
                txtTcCode    <= 5'd31;
346
        end
347
        else begin
348
 
349
                if (cs_reg & we_i) begin        // register write ?
350
 
351
                        case(adr_i[4:1])
352
                        4'd00:  numCols    <= dat_i;            // horizontal displayed
353
                        4'd01:  numRows    <= dat_i;
354
                        4'd02:  windowLeft <= dat_i[11:0];
355
                        4'd03:  windowTop  <= dat_i[11:0];               // vertical sync position
356
                        4'd04:  maxScanline <= dat_i[4:0];
357
                        4'd05:  begin
358
                                        pixelHeight <= dat_i[7:4];
359
                                        pixelWidth  <= dat_i[3:0];       // horizontal pixel width
360
                                        end
361
                        4'd07:  txtTcCode   <= dat_i[4:0];
362
                        4'd08:  begin
363
                                        cursorStart <= dat_i[4:0];       // scan line sursor starts on
364
                                        rBlink      <= dat_i[7:5];
365
                                        end
366
                        4'd09:  cursorEnd   <= dat_i[4:0];       // scan line cursor ends on
367
                        4'd10:  startAddress <= dat_i;
368
                        4'd11:  cursorPos <= dat_i;
369
                        endcase
370
                end
371
        end
372
 
373
 
374
//--------------------------------------------------------------------
375
//--------------------------------------------------------------------
376
 
377
// "Box" cursor bitmap
378
reg [7:0] curout;
379
always @(scanindex)
380
        case(scanindex)
381
        3'd0:   curout = 8'b11111111;
382
        3'd1:   curout = 8'b10000001;
383
        3'd2:   curout = 8'b10000001;
384
        3'd3:   curout = 8'b10000001;
385
        3'd4:   curout = 8'b10000001;
386
        3'd5:   curout = 8'b10000001;
387
        3'd6:   curout = 8'b10011001;
388
        3'd7:   curout = 8'b11111111;
389
        endcase
390
 
391
 
392
//-------------------------------------------------------------
393
// Video Stuff
394
//-------------------------------------------------------------
395
 
396
// Horizontal counter:
397
//
398
 
399
HVCounter uhv1
400
(
401
        .rst(rst_i),
402
        .vclk(vclk),
403
        .pixcce(1'b1),
404
        .sync(eol),
405
        .cnt_offs(windowLeft),
406
        .pixsz(pixelWidth),
407
        .maxpix(maxScanpix),
408
        .nxt_pix(nhp),
409
        .pos(col),
410
        .nxt_pos(nxt_col),
411
        .ctr(hctr)
412
);
413
 
414
 
415
// Vertical counter:
416
//
417
HVCounter uhv2
418
(
419
        .rst(rst_i),
420
        .vclk(vclk),
421
        .pixcce(eol),
422
        .sync(eof),
423
        .cnt_offs(windowTop),
424
        .pixsz(pixelHeight),
425
        .maxpix(maxScanline),
426
        .nxt_pix(nvp),
427
        .pos(row),
428
        .nxt_pos(nxt_row),
429
        .ctr(scanline)
430
);
431
 
432
always @(posedge vclk)
433
        rowscan <= scanline - row * (maxScanline+1);
434
 
435
 
436
// Blink counter
437
//
438
VT163 #(6) ub1
439
(
440
        .clk(vclk),
441
        .clr_n(!rst_i),
442
        .ent(eol & eof),
443
        .enp(1'b1),
444
        .ld_n(1'b1),
445
        .d(6'd0),
446
        .q(bcnt)
447
);
448
 
449
wire blink_en = (cursorPos+2==txtAddr) && (scanline[4:0] >= cursorStart) && (scanline[4:0] <= cursorEnd);
450
 
451
VT151 ub2
452
(
453
        .e_n(!blink_en),
454
        .s(rBlink),
455
        .i0(1'b1), .i1(1'b0), .i2(bcnt[4]), .i3(bcnt[5]),
456
        .i4(1'b1), .i5(1'b0), .i6(bcnt[4]), .i7(bcnt[5]),
457
        .z(blink),
458
        .z_n()
459
);
460
 
461
// These tables map a five bit color code to an eight bit color value.
462
rtfColorROM ucm1 (.clk(vclk), .ce(nhp & ld_shft), .code(txtBkCode1),  .color(bkColor24) );
463
rtfColorROM ucm2 (.clk(vclk), .ce(nhp & ld_shft), .code(txtFgCode1),  .color(fgColor24) );
464
always @(posedge vclk)
465
        if (nhp & ld_shft)
466
                bgt <= {1'b0,txtBkCode1}==txtTcCode;
467
 
468
 
469
// Convert character bitmap to pixels
470
// For convenience, the character bitmap data in the ROM is in the
471
// opposite bit order to what's needed for the display. The following
472
// just alters the order without adding any hardware.
473
//
474
wire [7:0] charRev = {
475
        charOut[0],
476
        charOut[1],
477
        charOut[2],
478
        charOut[3],
479
        charOut[4],
480
        charOut[5],
481
        charOut[6],
482
        charOut[7]
483
};
484
 
485
wire [7:0] charout1 = blink ? (charRev ^ curout) : charRev;
486
 
487
// Convert parallel to serial
488
ParallelToSerial ups1
489
(
490
        .rst(rst_i),
491
        .clk(vclk),
492
        .ce(nhp),
493
        .ld(ld_shft),
494
        .qin(1'b0),
495
        .d(charout1),
496
        .qh(pix)
497
);
498
 
499
 
500
// Pipelining Effect:
501
// - character output is delayed by 3 character times relative to the video counters.
502
// - this means we must adapt the blanking signal by shifting the blanking window
503
//   three character times.
504
wire bpix = hctr[1] ^ scanline[4];// ^ blink;
505
always @(posedge vclk)
506
        if (nhp)
507
                iblank <= (row >= numRows) || (col >= numCols + 3) || (col < 3);
508
 
509
 
510
// Choose between input RGB and controller generated RGB
511
// Select between foreground and background colours.
512
always @(posedge vclk)
513
        if (nhp) begin
514
                casex({blank,iblank,border,bpix,pix})
515
                5'b1xxxx:       rgbOut <= 25'h0000000;
516
                5'b01xxx:       rgbOut <= rgbIn;
517
                5'b0010x:       rgbOut <= 24'hBF2020;
518
                5'b0011x:       rgbOut <= 24'hDFDFDF;
519
                5'b000x0:       rgbOut <= bgt ? rgbIn : bkColor24;
520
                5'b000x1:       rgbOut <= fgColor24;
521
                default:        rgbOut <= rgbIn;
522
                endcase
523
        end
524
 
525
endmodule
526
 

powered by: WebSVN 2.1.0

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