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

Subversion Repositories rtftextcontroller

[/] [rtftextcontroller/] [trunk/] [rtl/] [verilog/] [rtfTextController.v] - Blame information for rev 3

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

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

powered by: WebSVN 2.1.0

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