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

Subversion Repositories rtftextcontroller

[/] [rtftextcontroller/] [trunk/] [rtl/] [verilog/] [rfTextController.sv] - Blame information for rev 32

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 robfinch
// ============================================================================
2
//        __
3 32 robfinch
//   \\__/ o\    (C) 2006-2023  Robert Finch, Waterloo
4 31 robfinch
//    \  __ /    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 32 robfinch
//  The controller expects a 256kB memory region to be reserved.
54 31 robfinch
//
55
//  Memory Map:
56 32 robfinch
//  00000-3FFFF   display ram
57
//  40000-7FFFF   character bitmap ram
58
//  80000-800FF   controller registers
59 31 robfinch
//
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
// 08h
70
//       5- 0              nnnnnn  char height in pixels, maximum scan line
71
//  11- 8                                                          wwww  pixel size - width
72
//  15-12                                                          hhhh  pixel size - height
73
//  21-16              nnnnnn  char width in pixels
74
//  24                      r  reset state bit
75
//  32                      e  controller enable
76
//  40                      m  multi-color mode
77 32 robfinch
//  41                      a  anti-alias mode
78 31 robfinch
//  48-52               nnnnn  yscroll
79
//  56-60               nnnnn  xscroll
80
// 10h
81
//      30- 0   cccccccc cccccccc  color code for transparent background RGB 4,9,9,9 (only RGB 7,7,7 used)
82
//  63-32   cccc...cccc        border color ZRGB 4,9,9,9
83
// 18h
84
//      30- 0   cccccccc cccccccc  tile color code 1
85
//  62-32   cccccccc cccccccc  tile color code 2
86
// 20h
87
//   4- 0               eeeee    cursor end
88
//   7- 5                 bbb  blink control
89
//                             BP: 00=no blink
90
//                             BP: 01=no display
91
//                             BP: 10=1/16 field rate blink
92
//                             BP: 11=1/32 field rate blink
93
//  12- 8               sssss  cursor start
94
//  15-13                                                                       ttt      cursor image type (none, box, underline, sidebar, checker, solid
95
//  47-32   aaaaaaaa aaaaaaaa    cursor position
96
// 28h
97
//  15- 0   aaaaaaaa aaaaaaaa  start address (index into display memory)
98
// 30h
99
//  15- 0   aaaaaaaa aaaaaaaa  font address in char bitmap memory
100
//  31-24              dddddd  font ascent
101
//  63-32   nnnnnnnn nnnnnnnn  font ram lock "LOCK" or "UNLK"
102
//--------------------------------------------------------------------
103
//
104 32 robfinch
// 1209 LUTs / 1003 FFs / 48 BRAMs / 1 DSP
105 31 robfinch
// ============================================================================
106
 
107
//`define USE_CLOCK_GATE
108 32 robfinch
//`define SUPPORT_AAM   1
109
`define TC_RAM_ADDR     32'hEC000001
110
`define TC_CBM_ADDR     32'hEC040001
111
`define TC_REG_ADDR     32'hEC080001
112 31 robfinch
 
113
module rfTextController(
114 32 robfinch
        rst_i, clk_i, cs_config_i, cs_io_i,
115 31 robfinch
        cti_i, cyc_i, stb_i, ack_o, wr_i, sel_i, adr_i, dat_i, dat_o,
116
        dot_clk_i, hsync_i, vsync_i, blank_i, border_i, zrgb_i, zrgb_o, xonoff_i
117
);
118
parameter num = 4'd1;
119
parameter COLS = 8'd64;
120
parameter ROWS = 8'd32;
121 32 robfinch
parameter BUSWID = 32;
122
parameter TEXT_CELL_COUNT = 8192;
123
parameter CFG_BUS = 8'd0;
124
parameter CFG_DEVICE = 5'd1;
125
parameter CFG_FUNC = 3'd0;
126
parameter CFG_VENDOR_ID =       16'h0;
127
parameter CFG_DEVICE_ID =       16'h0;
128
parameter CFG_SUBSYSTEM_VENDOR_ID       = 16'h0;
129
parameter CFG_SUBSYSTEM_ID = 16'h0;
130
parameter CFG_ROM_ADDR = 32'hFFFFFFF0;
131 31 robfinch
 
132
// Syscon
133
input  rst_i;                   // reset
134
input  clk_i;                   // clock
135
 
136 32 robfinch
input cs_config_i;
137
input cs_io_i;
138
 
139 31 robfinch
// Slave signals
140
input  [2:0] cti_i;
141
input  cyc_i;                           // valid bus cycle
142
input  stb_i;       // data strobe
143
output ack_o;                           // data acknowledge
144
input  wr_i;                            // write
145
input  [BUSWID/8-1:0] sel_i;    // byte lane select
146 32 robfinch
input  [31:0] adr_i;    // address
147 31 robfinch
input  [BUSWID-1:0] dat_i;                      // data input
148
output reg [BUSWID-1:0] dat_o;  // data output
149
 
150
// Video signals
151
input dot_clk_i;                // video dot clock
152
input hsync_i;                  // end of scan line
153
input vsync_i;                  // end of frame
154
input blank_i;                  // blanking signal
155
input border_i;                 // border area
156
input [39:0] zrgb_i;            // input pixel stream
157
output reg [39:0] zrgb_o;       // output pixel stream
158
input xonoff_i;
159
 
160 32 robfinch
integer n2,n3;
161 31 robfinch
reg controller_enable;
162 32 robfinch
reg [39:0] bkColor40, bkColor40d, bkColor40d2, bkColor40d3;     // background color
163
reg [39:0] fgColor40, fgColor40d, fgColor40d2, fgColor40d3;     // foreground color
164 31 robfinch
 
165
wire [1:0] pix;                         // pixel value from character generator 1=on,0=off
166
 
167
reg por;
168
wire vclk;
169
 
170
reg [63:0] rego;
171
reg [5:0] yscroll;
172
reg [5:0] xscroll;
173
reg [11:0] windowTop;
174
reg [11:0] windowLeft;
175
reg [ 7:0] numCols;
176
reg [ 7:0] numRows;
177
reg [ 7:0] charOutDelay;
178
reg [ 1:0] mode;
179
reg [ 5:0] maxRowScan;
180
reg [ 5:0] maxScanpix;
181
reg [1:0] tileWidth;            // width of tile in bytes (0=1,1=2,2=4,3=8)
182
reg [ 5:0] cursorStart, cursorEnd;
183
reg [15:0] cursorPos;
184
reg [2:0] cursorType;
185
reg [15:0] startAddress;
186
reg [15:0] fontAddress;
187
reg font_locked;
188
reg [5:0] fontAscent;
189
reg [ 2:0] rBlink;
190
reg [31:0] bdrColor;            // Border color
191
reg [ 3:0] pixelWidth;  // horizontal pixel width in clock cycles
192
reg [ 3:0] pixelHeight; // vertical pixel height in scan lines
193
reg mcm;                                                                // multi-color mode
194 32 robfinch
reg aam;                                                                // anti-alias mode
195 31 robfinch
 
196
wire [11:0] hctr;               // horizontal reference counter (counts clocks since hSync)
197
wire [11:0] scanline;   // scan line
198
reg [ 7:0] row;         // vertical reference counter (counts rows since vSync)
199
reg [ 7:0] col;         // horizontal column
200
reg [ 5:0] rowscan;     // scan line within row
201
reg [ 5:0] colscan;     // pixel column number within cell
202
wire nxt_row;                   // when to increment the row counter
203
wire nxt_col;                   // when to increment the column counter
204
reg [ 5:0] bcnt;                // blink timing counter
205
wire blink;
206
reg  iblank;
207
reg [5:0] maxScanlinePlusOne;
208
 
209
wire nhp;                               // next horizontal pixel
210
wire ld_shft = nxt_col & nhp;
211
 
212
 
213
// display and timing signals
214
reg [15:0] txtAddr;             // index into memory
215
reg [15:0] penAddr;
216
wire [63:0] screen_ram_out;             // character code
217
wire [20:0] txtBkColor; // background color code
218
wire [20:0] txtFgColor; // foreground color code
219
wire [5:0] txtZorder;
220
reg  [30:0] txtTcCode;  // transparent color code
221
reg [30:0] tileColor1;
222
reg [30:0] tileColor2;
223
reg  bgt, bgtd, bgtd2;
224
 
225
wire [63:0] tdat_o;
226
wire [63:0] chdat_o;
227 32 robfinch
reg [63:0] cfg_dat [0:31];
228
reg [63:0] cfg_out;
229 31 robfinch
 
230 32 robfinch
function [63:0] fnRbo;
231
input n;
232
input [63:0] i;
233
        fnRbo = n ? {i[7:0],i[15:8],i[23:16],i[31:24],i[39:32],i[47:40],i[55:48],i[63:56]} : i;
234
endfunction
235
 
236 31 robfinch
//--------------------------------------------------------------------
237
// bus interfacing
238
// Address Decoding
239
// I/O range Dx
240
//--------------------------------------------------------------------
241
// Register the inputs
242 32 robfinch
reg cs_config;
243 31 robfinch
reg cs_rom, cs_reg, cs_text, cs_any;
244 32 robfinch
reg cs_rom1, cs_reg1, cs_text1;
245
reg cs_tc;
246
reg [17:0] radr_i;
247 31 robfinch
reg [63:0] rdat_i;
248
reg rwr_i;
249
reg [7:0] rsel_i;
250
reg [7:0] wrs_i;
251 32 robfinch
reg [31:0] tc_ram_addr;
252
reg [31:0] tc_cbm_addr;
253
reg [31:0] tc_reg_addr;
254
 
255 31 robfinch
always_ff @(posedge clk_i)
256 32 robfinch
        cs_any <= cyc_i & stb_i & cs_io_i;
257 31 robfinch
always_ff @(posedge clk_i)
258 32 robfinch
        cs_config <= cyc_i & stb_i & cs_config_i && adr_i[27:20]==CFG_BUS && adr_i[19:15]==CFG_DEVICE && adr_i[14:12]==CFG_FUNC;
259 31 robfinch
always_ff @(posedge clk_i)
260 32 robfinch
        cs_rom1 <= adr_i[31:18] == tc_cbm_addr[31:18];
261 31 robfinch
always_ff @(posedge clk_i)
262 32 robfinch
        cs_reg1 <= adr_i[31: 8] == tc_reg_addr[31: 8];
263 31 robfinch
always_ff @(posedge clk_i)
264 32 robfinch
        cs_text1 <= adr_i[31:18] == tc_ram_addr[31:18];
265
always_comb
266
        cs_rom <= cs_rom1 && cs_any;
267
always_comb
268
        cs_reg <= cs_reg1 && cs_any;
269
always_comb
270
        cs_text <= cs_text1 && cs_any;
271
always_ff @(posedge clk_i)
272
        wrs_i <= (BUSWID==64) ? {8{wr_i}} & sel_i :
273 31 robfinch
                adr_i[2] ? {{4{wr_i}} & sel_i,4'h0} : {4'h0,{4{wr_i}} & sel_i};
274
always_ff @(posedge clk_i)
275
        rwr_i <= wr_i;
276
always_ff @(posedge clk_i)
277 32 robfinch
        rsel_i <= (BUSWID==64) ? sel_i : adr_i[2] ? {sel_i,4'h0} : {4'h0,sel_i};
278 31 robfinch
always_ff @(posedge clk_i)
279
        radr_i <= adr_i;
280
always_ff @(posedge clk_i)
281 32 robfinch
        rdat_i <= (BUSWID==64) ? dat_i : (BUSWID==32) ? {2{dat_i}} : {4{dat_i}};
282 31 robfinch
 
283
// Register outputs
284 32 robfinch
always_ff @(posedge clk_i)
285 31 robfinch
if (BUSWID==64)
286 32 robfinch
        casez({cs_config,cs_rom,cs_reg,cs_text})
287
        4'b1???:        dat_o <= cfg_out;
288
        4'b01??:        dat_o <= chdat_o;
289
        4'b001?:        dat_o <= rego;
290
        4'b0001:        dat_o <= tdat_o;
291 31 robfinch
        default:        dat_o <= 'h0;
292
        endcase
293
else if (BUSWID==32)
294 32 robfinch
        casez({cs_config,cs_rom,cs_reg,cs_text})
295
        4'b1???:        dat_o <= radr_i[2] ? cfg_out[63:32] : cfg_out[31:0];
296
        4'b01??:        dat_o <= radr_i[2] ? chdat_o[63:32] : chdat_o[31:0];
297
        4'b001?:        dat_o <= radr_i[2] ? rego[63:32] : rego[31:0];
298
        4'b0001:        dat_o <= radr_i[2] ? tdat_o[63:32] : tdat_o[31:0];
299 31 robfinch
        default:        dat_o <= 'd0;
300
        endcase
301
else
302
        dat_o <= 'd0;
303
 
304
//always @(posedge clk_i)
305
//      if (cs_text) begin
306
//              $display("TC WRite: %h %h", adr_i, dat_i);
307
//              $stop;
308
//      end
309
 
310
// - there is a four cycle latency for reads, an ack is generated
311
//   after the synchronous RAM read
312
// - writes can be acknowledged right away.
313
 
314
ack_gen #(
315
        .READ_STAGES(5),
316
        .WRITE_STAGES(1),
317
        .REGISTER_OUTPUT(1)
318
)
319
uag1 (
320 32 robfinch
        .rst_i(rst_i),
321 31 robfinch
        .clk_i(clk_i),
322
        .ce_i(1'b1),
323 32 robfinch
        .i((cs_any|cs_config) & ~rwr_i),
324
        .we_i((cs_any|cs_config) & rwr_i),
325 31 robfinch
        .o(ack_o),
326
        .rid_i(0),
327
        .wid_i(0),
328
        .rid_o(),
329
        .wid_o()
330
);
331
 
332
//--------------------------------------------------------------------
333 32 robfinch
// config
334 31 robfinch
//--------------------------------------------------------------------
335 32 robfinch
 
336
initial begin
337
        for (n3 = 0; n3 < 32; n3 = n3 + 1)
338
                cfg_dat[n3] = 'd0;
339
end
340
 
341
always_ff @(posedge clk_i)
342
if (rst_i) begin
343
        tc_ram_addr <= `TC_RAM_ADDR;
344
        tc_cbm_addr <= `TC_CBM_ADDR;
345
        tc_reg_addr     <= `TC_REG_ADDR;
346
end
347
else begin
348
        if (cs_config) begin
349
                if (rwr_i)
350
                        case(radr_i[7:3])
351
                        5'h02:
352
                                begin
353
                                        if (&rsel_i[3:0] && rdat_i[31:0]==32'hFFFFFFFF)
354
                                                tc_ram_addr <= 32'hFFFFFFFF;    // no memory is needed
355
                                        else begin
356
                                                if (rsel_i[0])  tc_ram_addr[7:0] <= rdat_i[7:0];
357
                                                if (rsel_i[1])  tc_ram_addr[15:8] <= rdat_i[15:8];
358
                                                if (rsel_i[2])  tc_ram_addr[23:16] <= rdat_i[23:16];
359
                                                if (rsel_i[3])  tc_ram_addr[31:24] <= rdat_i[31:24];
360
                                        end
361
                                        if (&rsel_i[7:4] && rdat_i[31:0]==32'hFFFFFFFF)
362
                                                tc_cbm_addr <= 32'hFFFFFFFF;    // no memory is needed
363
                                        else begin
364
                                                if (rsel_i[4])  tc_cbm_addr[7:0] <= rdat_i[7:0];
365
                                                if (rsel_i[5])  tc_cbm_addr[15:8] <= rdat_i[15:8];
366
                                                if (rsel_i[6])  tc_cbm_addr[23:16] <= rdat_i[23:16];
367
                                                if (rsel_i[7])  tc_cbm_addr[31:24] <= rdat_i[31:24];
368
                                        end
369
                                end
370
                        5'h03:
371
                                begin
372
                                        if (&rsel_i[3:0] && rdat_i[31:0]==32'hFFFFFFFF)
373
                                                tc_reg_addr <= 32'hFFFFFFFF;    // no memory is needed
374
                                        else begin
375
                                                if (rsel_i[0])  tc_reg_addr[7:0] <= rdat_i[7:0];
376
                                                if (rsel_i[1])  tc_reg_addr[15:8] <= rdat_i[15:8];
377
                                                if (rsel_i[2])  tc_reg_addr[23:16] <= rdat_i[23:16];
378
                                                if (rsel_i[3])  tc_reg_addr[31:24] <= rdat_i[31:24];
379
                                        end
380
                                end
381
                        default:
382
                                cfg_dat[radr_i[7:3]] <= rdat_i;
383
                        endcase
384
                else
385
                        case(radr_i[7:3])
386
                        5'h00:  cfg_out <= {32'h0,CFG_DEVICE_ID,CFG_VENDOR_ID};
387
                        5'h01:  cfg_out <= {8'h00,8'h00,8'h00,8'd32,24'h0,8'h0};
388
                        5'h02:  cfg_out <= {tc_cbm_addr,tc_ram_addr};
389
                        5'h03:  cfg_out <= {32'hFFFFFFFF,tc_reg_addr};
390
                        5'h04:  cfg_out <= 64'hFFFFFFFFFFFFFFFF;
391
                        5'h05:  cfg_out <= {CFG_SUBSYSTEM_ID,CFG_SUBSYSTEM_VENDOR_ID,32'h0};
392
                        5'h06:  cfg_out <= {24'h00,8'h00,CFG_ROM_ADDR};
393
                        5'h07:  cfg_out <= {8'd8,8'd0,8'd0,8'd0,32'h0};
394
                        default:        cfg_out <= cfg_dat[radr_i[7:3]];
395
                        endcase
396
        end
397
end
398
 
399
 
400
//--------------------------------------------------------------------
401
//--------------------------------------------------------------------
402 31 robfinch
`ifdef USE_CLOCK_GATE
403
BUFHCE ucb1 (.I(dot_clk_i), .CE(controller_enable), .O(vclk));
404
`else
405
assign vclk = dot_clk_i;
406
`endif
407
 
408
//--------------------------------------------------------------------
409
// Video Memory
410
//--------------------------------------------------------------------
411
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
412
// Address Calculation:
413
//  - Simple: the row times the number of  cols plus the col plus the
414
//    base screen address
415
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
416
 
417
reg [15:0] rowcol;
418
always_ff @(posedge vclk)
419
        txtAddr <= startAddress + rowcol + col;
420
 
421
// Register read-back memory
422
// This core to be found under Memory-Cores folder
423
// Allows reading back of register values by shadowing them with ram
424
 
425
wire [3:0] rrm_adr = radr_i[6:3];
426
wire [63:0] rrm_o;
427
 
428
regReadbackMem #(.WID(8)) rrm0L
429
(
430
  .wclk(clk_i),
431
  .adr(rrm_adr),
432
  .wce(cs_reg),
433
  .we(rwr_i & rsel_i[0]),
434
  .i(rdat_i[7:0]),
435
  .o(rrm_o[7:0])
436
);
437
 
438
regReadbackMem #(.WID(8)) rrm0H
439
(
440
  .wclk(clk_i),
441
  .adr(rrm_adr),
442
  .wce(cs_reg),
443
  .we(rwr_i & rsel_i[1]),
444
  .i(rdat_i[15:8]),
445
  .o(rrm_o[15:8])
446
);
447
 
448
regReadbackMem #(.WID(8)) rrm1L
449
(
450
  .wclk(clk_i),
451
  .adr(rrm_adr),
452
  .wce(cs_reg),
453
  .we(rwr_i & rsel_i[2]),
454
  .i(rdat_i[23:16]),
455
  .o(rrm_o[23:16])
456
);
457
 
458
regReadbackMem #(.WID(8)) rrm1H
459
(
460
  .wclk(clk_i),
461
  .adr(rrm_adr),
462
  .wce(cs_reg),
463
  .we(rwr_i & rsel_i[3]),
464
  .i(rdat_i[31:24]),
465
  .o(rrm_o[31:24])
466
);
467
 
468
regReadbackMem #(.WID(8)) rrm2L
469
(
470
  .wclk(clk_i),
471
  .adr(rrm_adr),
472
  .wce(cs_reg),
473
  .we(rwr_i & rsel_i[4]),
474
  .i(rdat_i[39:32]),
475
  .o(rrm_o[39:32])
476
);
477
 
478
regReadbackMem #(.WID(8)) rrm2H
479
(
480
  .wclk(clk_i),
481
  .adr(rrm_adr),
482
  .wce(cs_reg),
483
  .we(rwr_i & rsel_i[5]),
484
  .i(rdat_i[47:40]),
485
  .o(rrm_o[47:40])
486
);
487
 
488
regReadbackMem #(.WID(8)) rrm3L
489
(
490
  .wclk(clk_i),
491
  .adr(rrm_adr),
492
  .wce(cs_reg),
493
  .we(rwr_i & rsel_i[6]),
494
  .i(rdat_i[55:48]),
495
  .o(rrm_o[55:48])
496
);
497
 
498
regReadbackMem #(.WID(8)) rrm3H
499
(
500
  .wclk(clk_i),
501
  .adr(rrm_adr),
502
  .wce(cs_reg),
503
  .we(rwr_i & rsel_i[7]),
504
  .i(rdat_i[63:56]),
505
  .o(rrm_o[63:56])
506
);
507
 
508 32 robfinch
wire [26:0] lfsr1_o;
509
lfsr27 #(.WID(27)) ulfsr1(rst_i, dot_clk_i, 1'b1, 1'b0, lfsr1_o);
510
wire [63:0] lfsr_o = {6'h10,
511 31 robfinch
                                                                                                lfsr1_o[26:24],4'b0,lfsr1_o[23:21],4'b0,lfsr1_o[20:18],4'b0,
512
                                                                                                lfsr1_o[17:15],4'b0,lfsr1_o[14:12],4'b0,lfsr1_o[11:9],4'b0,
513 32 robfinch
                                                                                                7'h00,lfsr1_o[8:0]
514 31 robfinch
                                                                                };
515 32 robfinch
wire [63:0] lfsr_o2 = {6'h10,
516
//                                                                                              lfsr1_o[26:24],4'b0,lfsr1_o[23:21],4'b0,lfsr1_o[20:18],4'b0,
517
//                                                                                              lfsr1_o[17:15],4'b0,lfsr1_o[14:12],4'b0,lfsr1_o[11:9],4'b0,
518
                                                                                                4'b0,lfsr1_o[26:24],4'b0,lfsr1_o[23:21],lfsr1_o[20:18],4'b0,
519
                                                                                                4'b0,lfsr1_o[17:15],4'b0,lfsr1_o[14:12],lfsr1_o[11:9],4'b0,
520
                                                                                                7'h00,lfsr1_o[8:0]
521
                                                                                };
522
wire [63:0] lfsr_o1 = {lfsr1_o[3:0],2'b00,
523
//                                                                                              lfsr1_o[26:24],4'b0,lfsr1_o[23:21],4'b0,lfsr1_o[20:18],4'b0,
524
//                                                                                              lfsr1_o[17:15],4'b0,lfsr1_o[14:12],4'b0,lfsr1_o[11:9],4'b0,
525
                                                                                                4'b0,lfsr1_o[26:24],4'b0,lfsr1_o[23:21],lfsr1_o[20:18],4'b0,
526
                                                                                                4'b0,lfsr1_o[17:15],lfsr1_o[14:12],4'b0,4'b0,lfsr1_o[11:9],
527
                                                                                                7'h00,lfsr1_o[8:0]
528
                                                                                };
529 31 robfinch
 
530
/* This snippit of code for performing burst accesses, under construction.
531
wire pe_cs;
532
edge_det u1(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(cs_text), .pe(pe_cs), .ne(), .ee() );
533
 
534
reg [14:0] ctr;
535
always @(posedge clk_i)
536
        if (pe_cs) begin
537
                if (cti_i==3'b000)
538
                        ctr <= adr_i[16:3];
539
                else
540
                        ctr <= adr_i[16:3] + 12'd1;
541
                cnt <= 3'b000;
542
        end
543
        else if (cs_text && cnt[2:0]!=3'b100 && cti_i!=3'b000) begin
544
                ctr <= ctr + 2'd1;
545
                cnt <= cnt + 3'd1;
546
        end
547
 
548
reg [13:0] radr;
549
always @(posedge clk_i)
550
        radr <= pe_cs ? adr_i[16:3] : ctr;
551
*/
552
 
553
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
554
// text screen RAM
555
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
556 32 robfinch
rfTextScreenRam #(
557
        .TEXT_CELL_COUNT(TEXT_CELL_COUNT)
558
)
559
screen_ram1
560 31 robfinch
(
561
        .clka_i(clk_i),
562
        .csa_i(cs_text),
563
        .wea_i(rwr_i),
564
        .sela_i(rsel_i),
565 32 robfinch
        .adra_i(radr_i[16:3]),
566 31 robfinch
        .data_i(rdat_i),
567
        .data_o(tdat_o),
568
        .clkb_i(vclk),
569
        .csb_i(ld_shft|por),
570
        .web_i(por),
571
        .selb_i(8'hFF),
572 32 robfinch
        .adrb_i(txtAddr[13:0]),
573
        .datb_i(lfsr_o),//txtAddr[12:0] > 13'd1664 ? lfsr_o1 : lfsr_o),
574 31 robfinch
        .datb_o(screen_ram_out)
575
);
576
 
577
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
578
// Character bitmap RAM
579
// - room for 8160 8x8 characters
580
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
581
wire [63:0] char_bmp;           // character ROM output
582
rfTextCharRam charRam0
583
(
584
        .clk_i(clk_i),
585
        .cs_i(cs_rom),
586
        .we_i(rwr_i & ~font_locked),
587
        .sel_i(rsel_i),
588
        .adr_i(radr_i[15:3]),
589
        .dat_i(rdat_i[63:0]),
590
        .dat_o(chdat_o),
591
        .dot_clk_i(vclk),
592
        .ce_i(ld_shft),
593
        .fontAddress_i(fontAddress),
594
        .char_code_i(screen_ram_out[12:0]),
595
        .maxScanpix_i(maxScanpix),
596
        .maxscanline_i(maxScanlinePlusOne),
597
        .scanline_i(rowscan[5:0]),
598
        .bmp_o(char_bmp)
599
);
600
 
601
// pipeline delay - sync color with character bitmap output
602
reg [20:0] txtBkCode1;
603
reg [20:0] txtFgCode1;
604
reg [5:0] txtZorder1;
605
always @(posedge vclk)
606
        if (ld_shft) txtBkCode1 <= screen_ram_out[36:16];
607
always @(posedge vclk)
608
        if (ld_shft) txtFgCode1 <= screen_ram_out[57:37];
609
always @(posedge vclk)
610
        if (ld_shft) txtZorder1 <= screen_ram_out[63:58];
611
 
612
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
613
// Register read port
614
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
615
always_comb
616
        if (cs_reg)
617
                rego <= rrm_o;
618
        else
619
                rego <= 64'h0000;
620
 
621
 
622
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
623
// Register write port
624
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
625
 
626
always_ff @(posedge clk_i)
627
        if (rst_i) begin
628
          por <= 1'b1;
629
          mcm <= 1'b0;
630 32 robfinch
          aam <= 1'b0;
631 31 robfinch
          controller_enable <= 1'b1;
632
    xscroll              <= 5'd0;
633
    yscroll              <= 5'd0;
634
    txtTcCode    <= 24'h1ff;
635
    bdrColor     <= 32'hFFBF2020;
636
    startAddress <= 16'h0000;
637 32 robfinch
    fontAddress  <= 16'h0008;
638 31 robfinch
    font_locked  <= 1'b1;
639
    fontAscent   <= 6'd12;
640
    cursorStart  <= 5'd00;
641
    cursorEnd    <= 5'd31;
642
    cursorPos    <= 16'h0003;
643
    cursorType   <= 3'd4;       // checker
644
// 104x63
645
/*
646
                windowTop    <= 12'd26;
647
                windowLeft   <= 12'd260;
648
                pixelWidth   <= 4'd0;
649
                pixelHeight  <= 4'd1;           // 525 pixels (408 with border)
650
*/
651
// 52x31
652
/*
653
                // 84x47
654
                windowTop    <= 12'd16;
655
                windowLeft   <= 12'd90;
656
                pixelWidth   <= 4'd1;           // 681 pixels
657
                pixelHeight  <= 4'd1;           // 384 pixels
658
*/
659
                // 64x32
660
                if (num==4'd1) begin
661
      windowTop    <= 12'd4058;//12'd16;
662 32 robfinch
      windowLeft   <= 12'd3918;//12'd3956;//12'd86;
663 31 robfinch
      pixelWidth   <= 4'd0;             // 800 pixels
664
      pixelHeight  <= 4'd0;             // 600 pixels
665
      numCols      <= COLS;
666
      numRows      <= ROWS;
667
      maxRowScan   <= 6'd17;
668
      maxScanpix   <= 6'd11;
669
      rBlink       <= 3'b111;           // 01 = non display
670 32 robfinch
      charOutDelay <= 8'd5;
671 31 robfinch
                end
672
                else if (num==4'd2) begin
673
      windowTop    <= 12'd4032;//12'd16;
674
      windowLeft   <= 12'd3720;//12'd86;
675
      pixelWidth   <= 4'd0;        // 800 pixels
676
      pixelHeight  <= 4'd0;        // 600 pixels
677
      numCols      <= 40;
678
      numRows      <= 25;
679
      maxRowScan   <= 5'd7;
680
      maxScanpix   <= 6'd7;
681
      rBlink       <= 3'b111;        // 01 = non display
682
      charOutDelay <= 8'd6;
683
                end
684
        end
685
        else begin
686
 
687
                if (bcnt > 6'd10)
688
                        por <= 1'b0;
689
 
690
                if (cs_reg & rwr_i) begin       // register write ?
691
                        $display("TC Write: r%d=%h", rrm_adr, rdat_i);
692
                        case(rrm_adr)
693
                        4'd0:   begin
694
                                        if (rsel_i[0]) numCols    <= rdat_i[7:0];
695
                                        if (rsel_i[1]) numRows    <= rdat_i[15:8];
696
                                        if (rsel_i[2]) charOutDelay <= rdat_i[23:16];
697
                                        if (rsel_i[4]) windowLeft[7:0] <= rdat_i[39:32];
698
                                        if (rsel_i[5]) windowLeft[11:8] <= rdat_i[43:40];
699
                                        if (rsel_i[6]) windowTop[7:0]  <= rdat_i[55:48];
700
                                        if (rsel_i[7]) windowTop[11:8]  <= rdat_i[59:56];
701
                                        end
702
                        4'd1:
703
                                begin
704
                                        if (rsel_i[0]) maxRowScan <= rdat_i[4:0];
705
                                        if (rsel_i[1]) begin
706
                                                pixelHeight <= rdat_i[15:12];
707
                                                pixelWidth  <= rdat_i[11:8];    // horizontal pixel width
708
                                        end
709
                                        if (rsel_i[2]) maxScanpix <= rdat_i[20:16];
710
                                        if (rsel_i[3]) por <= rdat_i[24];
711
                                        if (rsel_i[4]) controller_enable <= rdat_i[32];
712 32 robfinch
                                        if (rsel_i[5])
713
                                                begin
714
                                                        mcm <= rdat_i[40];
715
                                                        aam <= rdat_i[41];
716
                                                end
717 31 robfinch
                                        if (rsel_i[6]) yscroll <= rdat_i[52:48];
718
                                        if (rsel_i[7]) xscroll <= rdat_i[60:56];
719
                                end
720
                        4'd2:   // Color Control
721
                                begin
722
                                        if (rsel_i[0]) txtTcCode[7:0] <= rdat_i[7:0];
723
                                        if (rsel_i[1]) txtTcCode[15:8] <= rdat_i[15:8];
724
                                        if (rsel_i[2]) txtTcCode[23:16] <= rdat_i[23:16];
725
                                        if (rsel_i[3]) txtTcCode[30:24] <= rdat_i[30:24];
726 32 robfinch
                                        if (rsel_i[4]) bdrColor[7:0] <= rdat_i[39:32];
727
                                        if (rsel_i[5]) bdrColor[15:8] <= rdat_i[47:40];
728
                                        if (rsel_i[6]) bdrColor[23:16] <= rdat_i[55:48];
729
                                        if (rsel_i[7]) bdrColor[31:24] <= rdat_i[63:56];
730 31 robfinch
                                end
731
                        4'd3:   // Color Control 2
732
                                begin
733
                                        if (rsel_i[0]) tileColor1[7:0] <= rdat_i[7:0];
734
                                        if (rsel_i[1]) tileColor1[15:8] <= rdat_i[15:8];
735
                                        if (rsel_i[2]) tileColor1[23:16] <= rdat_i[23:16];
736
                                        if (rsel_i[3]) tileColor1[30:24] <= rdat_i[30:24];
737
                                        if (rsel_i[4]) tileColor2[7:0] <= rdat_i[39:32];
738
                                        if (rsel_i[5]) tileColor2[15:8] <= rdat_i[47:40];
739
                                        if (rsel_i[6]) tileColor2[23:16] <= rdat_i[55:48];
740
                                        if (rsel_i[7]) tileColor2[30:24] <= rdat_i[62:56];
741
                                end
742
                        4'd4:   // Cursor Control
743
                                begin
744
                                        if (rsel_i[0]) begin
745
                                                cursorEnd <= rdat_i[4:0];       // scan line sursor starts on
746
                                                rBlink      <= rdat_i[7:5];
747
                                        end
748
                                        if (rsel_i[1]) begin
749
                                                cursorStart <= rdat_i[12:8];    // scan line cursor ends on
750
                                                cursorType  <= rdat_i[15:13];
751
                                        end
752
                                        if (rsel_i[4]) cursorPos[7:0] <= rdat_i[39:32];
753
                                        if (rsel_i[5]) cursorPos[15:8] <= rdat_i[47:40];
754
                                end
755
                        4'd5:   // Page flipping / scrolling
756
                                begin
757
                                        if (rsel_i[0]) startAddress[7:0] <= rdat_i[7:0];
758
                                        if (rsel_i[1]) startAddress[15:8] <= rdat_i[15:8];
759
                                end
760
                        4'd6:   //
761
                                begin
762
                                        if (rsel_i[0]) fontAddress[7:0] <= rdat_i[7:0];
763
                                        if (rsel_i[1]) fontAddress[15:8] <= rdat_i[15:8];
764
                                        if (rsel_i[3]) fontAscent[5:0] <= rdat_i[5:0];
765
                                        if (&rsel_i[7:4]) begin
766
                                                if (rdat_i[63:32]=="LOCK")
767
                                                        font_locked <= 1'b1;
768
                                                else if (rdat_i[63:32]=="UNLK")
769
                                                        font_locked <= 1'b0;
770
                                        end
771
                                end
772
                        default: ;
773
                        endcase
774
                end
775
        end
776
 
777
 
778
//--------------------------------------------------------------------
779
// Cursor image is computed based on the font size, so the available
780
// hardware cursors are really simple. More sophisticated hardware
781
// cursors can be had via the sprite controller.
782
//--------------------------------------------------------------------
783
 
784
reg [31:0] curout;
785 32 robfinch
wire [31:0] curout1;
786 31 robfinch
always_ff @(posedge vclk)
787
if (ld_shft) begin
788
        curout = 'd0;
789
        case(cursorType)
790
        // No cursor
791
        3'd0:   ;
792
        // "Box" cursor
793
        3'd1:
794
                begin
795
                        case(rowscan)
796
                        maxRowScan,5'd0: curout = 32'hFFFFFFFF;
797
                        /*
798
                        maxRowScan-1:
799
                                if (rowscan==maxRowScan-1) begin
800
                                        curout[maxScanpix[5:1]] = 1'b1;
801
                                        curout[maxScanpix[5:1]+1] = 1'b1;
802
                                end
803
                        */
804
                        default:
805
                                begin
806
                                        curout[maxScanpix] = 1'b1;
807
                                        curout[0] = 1'b1;
808
                                end
809
                        endcase
810
                end
811
        // Vertical Line cursor
812
        3'd2:   curout[maxScanpix] = 1'b1;
813
        // Underline cursor
814
        3'd3:
815
                if (rowscan==fontAscent)
816
                        curout = 32'hFFFFFFFF;
817
        // Checker cursor
818
        3'd4:   curout = rowscan[1] ? 32'h33333333 : 32'hCCCCCCCC;
819
        // Solid cursor
820
        3'd7:   curout = 32'hFFFFFFFF;
821
        default:        curout = 32'hFFFFFFFF;
822
        endcase
823
end
824
 
825 32 robfinch
ft_delay
826
#(
827
        .WID(32),
828
        .DEP(3)
829
)
830
uftd1
831
(
832
        .clk(vclk),
833
        .ce(ld_shft),
834
        .i(curout),
835
        .o(curout1)
836
);
837
 
838 31 robfinch
//-------------------------------------------------------------
839
// Video Stuff
840
//-------------------------------------------------------------
841
 
842
wire pe_hsync;
843
wire pe_vsync;
844
edge_det edh1
845
(
846
        .rst(rst_i),
847
        .clk(vclk),
848
        .ce(1'b1),
849
        .i(hsync_i),
850
        .pe(pe_hsync),
851
        .ne(),
852
        .ee()
853
);
854
 
855
edge_det edv1
856
(
857
        .rst(rst_i),
858
        .clk(vclk),
859
        .ce(1'b1),
860
        .i(vsync_i),
861
        .pe(pe_vsync),
862
        .ne(),
863
        .ee()
864
);
865
 
866
// We generally don't care about the exact reset point, unless debugging in
867
// simulation. The counters will eventually cycle to a proper state. A little
868
// bit of logic / routing can be avoided by omitting the reset.
869
`ifdef SIM
870
wire sym_rst = rst_i;
871
`else
872
wire sym_rst = 1'b0;
873
`endif
874
 
875
// Raw scanline counter
876
vid_counter #(12) u_vctr (.rst(sym_rst), .clk(vclk), .ce(pe_hsync), .ld(pe_vsync), .d(windowTop), .q(scanline), .tc());
877
vid_counter #(12) u_hctr (.rst(sym_rst), .clk(vclk), .ce(1'b1), .ld(pe_hsync), .d(windowLeft), .q(hctr), .tc());
878
 
879
// Vertical pixel height counter, synchronized to scanline #0
880
reg [3:0] vpx;
881
wire nvp = vpx==pixelHeight;
882
always @(posedge vclk)
883
if (sym_rst)
884
        vpx <= 4'b0;
885
else begin
886
        if (pe_hsync) begin
887
                if (scanline==12'd0)
888
                        vpx <= 4'b0;
889
                else if (nvp)
890
                        vpx <= 4'd0;
891
                else
892
                        vpx <= vpx + 4'd1;
893
        end
894
end
895
 
896
reg [3:0] hpx;
897
assign nhp = hpx==pixelWidth;
898
always @(posedge vclk)
899
if (sym_rst)
900
        hpx <= 4'b0;
901
else begin
902
        if (hctr==12'd0)
903
                hpx <= 4'b0;
904
        else if (nhp)
905
                hpx <= 4'd0;
906
        else
907
                hpx <= hpx + 4'd1;
908
end
909
 
910
// The scanline row within a character bitmap
911
always @(posedge vclk)
912
if (sym_rst)
913
        rowscan <= 5'd0;
914
else begin
915
        if (pe_hsync & nvp) begin
916
                if (scanline==12'd0)
917
                        rowscan <= yscroll;
918
                else if (rowscan==maxRowScan)
919
                        rowscan <= 5'd0;
920
                else
921
                        rowscan <= rowscan + 5'd1;
922
        end
923
end
924
 
925
assign nxt_col = colscan==maxScanpix;
926
always @(posedge vclk)
927
if (sym_rst)
928
        colscan <= 5'd0;
929
else begin
930
        if (nhp) begin
931
                if (hctr==12'd0)
932
                        colscan <= xscroll;
933
                else if (nxt_col)
934
                        colscan <= 5'd0;
935
                else
936
                        colscan <= colscan + 5'd1;
937
        end
938
end
939
 
940
// The screen row
941
always @(posedge vclk)
942
if (sym_rst)
943
        row <= 8'd0;
944
else begin
945
        if (pe_hsync & nvp) begin
946
                if (scanline==12'd0)
947
                        row <= 8'd0;
948
                else if (rowscan==maxRowScan)
949
                        row <= row + 8'd1;
950
        end
951
end
952
 
953
// The screen column
954
always @(posedge vclk)
955
if (sym_rst)
956
        col <= 8'd0;
957
else begin
958
        if (hctr==12'd0)
959
                col <= 8'd0;
960
        else if (nhp) begin
961
                if (nxt_col)
962
                        col <= col + 8'd1;
963
        end
964
end
965
 
966
// More useful, the offset of the start of the text display on a line.
967
always @(posedge vclk)
968
if (sym_rst)
969
        rowcol <= 16'd0;
970
else begin
971
        if (pe_hsync & nvp) begin
972
                if (scanline==12'd0)
973
                        rowcol <= 8'd0;
974
                else if (rowscan==maxRowScan)
975
                        rowcol <= rowcol + numCols;
976
        end
977
end
978
 
979
// Takes 3 clock for scanline to become stable, but should be stable before any
980
// chars are displayed.
981
reg [13:0] rxmslp1;
982
always_ff @(posedge vclk)
983
        maxScanlinePlusOne <= maxRowScan + 4'd1;
984
 
985
 
986
// Blink counter
987
//
988
always_ff @(posedge vclk)
989
if (sym_rst)
990
        bcnt <= 6'd0;
991
else begin
992
        if (pe_vsync)
993
                bcnt <= bcnt + 6'd1;
994
end
995
 
996
reg blink_en;
997
always_ff @(posedge vclk)
998 32 robfinch
        blink_en <= (cursorPos+charOutDelay-2'd1==txtAddr);// && (rowscan[4:0] >= cursorStart) && (rowscan[4:0] <= cursorEnd);
999 31 robfinch
 
1000
VT151 ub2
1001
(
1002
        .e_n(!blink_en),
1003
        .s(rBlink),
1004
        .i0(1'b1), .i1(1'b0), .i2(bcnt[4]), .i3(bcnt[5]),
1005
        .i4(1'b1), .i5(1'b0), .i6(bcnt[4]), .i7(bcnt[5]),
1006
        .z(blink),
1007
        .z_n()
1008
);
1009
 
1010
always_ff @(posedge vclk)
1011
        if (ld_shft)
1012
                bkColor40 <= {txtZorder1[5:2],txtBkCode1[20:14],5'b0,txtBkCode1[13:7],5'b0,txtBkCode1[6:0],5'b0};
1013
always_ff @(posedge vclk)
1014
        if (ld_shft)
1015
                bkColor40d <= bkColor40;
1016
always_ff @(posedge vclk)
1017 32 robfinch
        if (ld_shft)
1018 31 robfinch
                bkColor40d2 <= bkColor40d;
1019
always_ff @(posedge vclk)
1020 32 robfinch
        if (nhp)
1021
                bkColor40d3 <= bkColor40d2;
1022
always_ff @(posedge vclk)
1023 31 robfinch
        if (ld_shft)
1024
                fgColor40 <= {txtZorder1[5:2],txtFgCode1[20:14],5'b0,txtFgCode1[13:7],5'b0,txtFgCode1[6:0],5'b0};
1025
always_ff @(posedge vclk)
1026
        if (ld_shft)
1027
                fgColor40d <= fgColor40;
1028
always_ff @(posedge vclk)
1029 32 robfinch
        if (ld_shft)
1030
                fgColor40d2 <= fgColor40d;
1031
always_ff @(posedge vclk)
1032 31 robfinch
        if (nhp)
1033 32 robfinch
                fgColor40d3 <= fgColor40d2;
1034 31 robfinch
 
1035
always_ff @(posedge vclk)
1036
        if (ld_shft)
1037
                bgt <= txtBkCode1=={txtTcCode[26:20],txtTcCode[17:11],txtTcCode[8:2]};
1038
always_ff @(posedge vclk)
1039
        if (ld_shft)
1040
                bgtd <= bgt;
1041
always_ff @(posedge vclk)
1042
        if (nhp)
1043
                bgtd2 <= bgtd;
1044
 
1045
// Convert character bitmap to pixels
1046
reg [63:0] charout1;
1047
always_ff @(posedge vclk)
1048 32 robfinch
        charout1 <= blink ? (char_bmp ^ curout1) : char_bmp;
1049 31 robfinch
 
1050
// Convert parallel to serial
1051
rfTextShiftRegister ups1
1052
(
1053
        .rst(rst_i),
1054
        .clk(vclk),
1055
        .mcm(mcm),
1056 32 robfinch
//      .aam(aam),
1057 31 robfinch
        .ce(nhp),
1058
        .ld(ld_shft),
1059
        .a(maxScanpix[5:0]),
1060
        .qin(2'b0),
1061
        .d(charout1),
1062
        .qh(pix)
1063
);
1064
 
1065
// Pipelining Effect:
1066
// - character output is delayed by 2 or 3 character times relative to the video counters
1067
//   depending on the resolution selected
1068
// - this means we must adapt the blanking signal by shifting the blanking window
1069
//   two or three character times.
1070
wire bpix = hctr[2] ^ rowscan[4];// ^ blink;
1071
always_ff @(posedge vclk)
1072
        if (nhp)
1073
                iblank <= (row >= numRows) || (col >= numCols + charOutDelay) || (col < charOutDelay);
1074
 
1075 32 robfinch
`ifdef SUPPORT_AAM
1076
function [11:0] fnBlendComponent;
1077
input [11:0] c1;
1078
input [11:0] c2;
1079
input [1:0] pix;
1080
case(pix)
1081
2'b00:  fnBlendComponent = c2;
1082
2'b01:  fnBlendComponent = ((c1 * 4'd5) + (c2 * 4'd11)) >> 4;
1083
2'b10:  fnBlendComponent = ((c1 * 4'd11) + (c2 * 4'd5)) >> 4;
1084
2'b11:  fnBlendComponent = c1;
1085
endcase
1086
endfunction
1087
 
1088
function [39:0] fnBlend;
1089
input [39:0] c1;
1090
input [39:0] c2;
1091
input [1:0] pix;
1092
fnBlend = {
1093
        |pix ? c1[39:36] : c2[39:36],
1094
        fnBlendComponent(c1[35:24],c2[35:24]),
1095
        fnBlendComponent(c1[23:12],c2[23:12]),
1096
        fnBlendComponent(c1[11: 0],c2[11: 0])
1097
};
1098
endfunction
1099
`endif
1100
 
1101 31 robfinch
// Choose between input RGB and controller generated RGB
1102
// Select between foreground and background colours.
1103
// Note the ungated dot clock must be used here, or output from other
1104
// controllers would not be visible if the clock were gated off.
1105
always_ff @(posedge dot_clk_i)
1106 32 robfinch
        casez({controller_enable&xonoff_i,blank_i,iblank,border_i,bpix,mcm,aam,pix})
1107
        9'b01???????:   zrgb_o <= 40'h00000000;
1108
        9'b11???????:   zrgb_o <= 40'h00000000;
1109
        9'b1001?????:   zrgb_o <= {bdrColor[30:27],bdrColor[26:18],3'b0,bdrColor[17:9],3'b0,bdrColor[8:0],3'b0};
1110
`ifdef SUPPORT_AAM
1111
        9'b1000?01??:   zrgb_o <= fnBlend(fgColor40d3,zrgb_i[39:36] > bkColor40d3[39:36]) ? zrgb_i : bkColor40d3, pix);
1112
`endif
1113
        9'b1000?000?:   zrgb_o <= (zrgb_i[39:36] > bkColor40d3[39:36]) ? zrgb_i : bkColor40d3;
1114
        9'b1000?001?:   zrgb_o <= fgColor40d3; // ToDo: compare z-order
1115
        9'b1000?1000:   zrgb_o <= (zrgb_i[39:36] > bkColor40d3[39:36]) ? zrgb_i : bkColor40d3;
1116
        9'b1000?1001:   zrgb_o <= fgColor40d3;
1117
        9'b1000?1010:   zrgb_o <= {tileColor1[30:27],tileColor1[26:18],3'b0,tileColor1[17:9],3'b0,tileColor1[8:0],3'b0};
1118
        9'b1000?1011:   zrgb_o <= {tileColor2[30:27],tileColor2[26:18],3'b0,tileColor2[17:9],3'b0,tileColor2[8:0],3'b0};
1119 31 robfinch
//      6'b1010?0:      zrgb_o <= bgtd ? zrgb_i : bkColor32d;
1120
        default:        zrgb_o <= zrgb_i;
1121
        endcase
1122
 
1123
endmodule
1124
 

powered by: WebSVN 2.1.0

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