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

Subversion Repositories rtfbitmapcontroller

[/] [rtfbitmapcontroller/] [trunk/] [rtl/] [verilog/] [rtfBitmapController5.v] - Blame information for rev 23

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

Line No. Rev Author Line
1 23 robfinch
// ============================================================================
2
// rtfBitmapController5
3
//  Bitmap Controller (Frame Buffer Display)
4
//  - Displays a bitmap from memory.
5
//
6
//
7
//        __
8
//   \\__/ o\    (C) 2008-2018  Robert Finch, Waterloo
9
//    \  __ /    All rights reserved.
10
//     \/_//     robfinch<remove>@finitron.ca
11
//       ||
12
//
13
//
14
// This source file is free software: you can redistribute it and/or modify 
15
// it under the terms of the GNU Lesser General Public License as published 
16
// by the Free Software Foundation, either version 3 of the License, or     
17
// (at your option) any later version.                                      
18
//                                                                          
19
// This source file is distributed in the hope that it will be useful,      
20
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
21
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
22
// GNU General Public License for more details.                             
23
//                                                                          
24
// You should have received a copy of the GNU General Public License        
25
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
26
//                                                                          
27
//
28
//  The default base screen address is:
29
//              $0200000 - the second 4MiB of RAM
30
//
31
//
32
//      Verilog 1995
33
//
34
// ============================================================================
35
 
36
//`define USE_CLOCK_GATE        1'b1
37
`define INTERNAL_SYNC_GEN       1'b1
38
 
39
`define ABITS   31:0
40
`define HIGH    1'b1
41
`define LOW             1'b0
42
 
43
module rtfBitmapController5(
44
        rst_i,
45
        s_clk_i, s_cs_i, s_cyc_i, s_stb_i, s_ack_o, s_we_i, s_sel_i, s_adr_i, s_dat_i, s_dat_o, irq_o,
46
        m_clk_i, m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, m_dat_o,
47
        dot_clk_i, zrgb_o, xonoff_i
48
`ifdef INTERNAL_SYNC_GEN
49
        , hsync_o, vsync_o, blank_o, border_o
50
`else
51
        , hsync_i, vsync_i, blank_i
52
`endif
53
);
54
parameter BM_BASE_ADDR1 = 32'h0020_0000;
55
parameter BM_BASE_ADDR2 = 32'h0028_0000;
56
parameter REG_CTRL = 9'd0;
57
parameter REG_DISPLAYED = 9'd1;
58
parameter REG_PAGE1ADDR = 9'd2;
59
parameter REG_PAGE2ADDR = 9'd3;
60
parameter REG_PXYZ = 9'd4;
61
parameter REG_PCOLCMD = 9'd5;
62
parameter REG_TOTAL = 9'd8;
63
parameter REG_SYNC_ONOFF = 9'd9;
64
parameter REG_BLANK_ONOFF = 9'd10;
65
parameter REG_BORDER_ONOFF = 9'd11;
66
 
67
parameter BPP4 = 3'd0;
68
parameter BPP8 = 3'd1;
69
parameter BPP12 = 3'd2;
70
parameter BPP16 = 3'd3;
71
parameter BPP20 = 3'd4;
72
parameter BPP32 = 3'd5;
73
 
74
parameter OPBLACK = 4'd0;
75
parameter OPCOPY = 4'd1;
76
parameter OPINV = 4'd2;
77
parameter OPAND = 4'd4;
78
parameter OPOR = 4'd5;
79
parameter OPXOR = 4'd6;
80
parameter OPANDN = 4'd7;
81
parameter OPNAND = 4'd8;
82
parameter OPNOR = 4'd9;
83
parameter OPXNOR = 4'd10;
84
parameter OPORN = 4'd11;
85
parameter OPWHITE = 4'd15;
86
 
87
// Sync Generator defaults: 800x600 60Hz
88
parameter phSyncOn  = 40;               //   40 front porch
89
parameter phSyncOff = 168;              //  128 sync
90
parameter phBlankOff = 252;     //256   //   88 back porch
91
//parameter phBorderOff = 336;  //   80 border
92
parameter phBorderOff = 256;    //   80 border
93
//parameter phBorderOn = 976;           //  640 display
94
parameter phBorderOn = 1056;            //  640 display
95
parameter phBlankOn = 1052;             //   80 border
96
parameter phTotal = 1056;               // 1056 total clocks
97
parameter pvSyncOn  = 1;                //    1 front porch
98
parameter pvSyncOff = 5;                //    4 vertical sync
99
parameter pvBlankOff = 28;              //   23 back porch
100
parameter pvBorderOff = 28;             //   44 border  0
101
//parameter pvBorderOff = 72;           //   44 border  0
102
parameter pvBorderOn = 628;             //  512 display
103
//parameter pvBorderOn = 584;           //  512 display
104
parameter pvBlankOn = 628;      //   44 border  0
105
parameter pvTotal = 628;                //  628 total scan lines
106
 
107
 
108
// SYSCON
109
input rst_i;                            // system reset
110
 
111
// Peripheral IO slave port
112
input s_clk_i;
113
input s_cs_i;
114
input s_cyc_i;
115
input s_stb_i;
116
output s_ack_o;
117
input s_we_i;
118
input [7:0] s_sel_i;
119
input [11:0] s_adr_i;
120
input [63:0] s_dat_i;
121
output [63:0] s_dat_o;
122
reg [63:0] s_dat_o;
123
output irq_o;
124
 
125
// Video Memory Master Port
126
// Used to read memory via burst access
127
input m_clk_i;                          // system bus interface clock
128
output m_cyc_o;                 // video burst request
129
output m_stb_o;
130
output reg m_we_o;
131
output [7:0] m_sel_o;
132
input  m_ack_i;                 // vid_acknowledge from memory
133
output [`ABITS] m_adr_o;        // address for memory access
134
input  [63:0] m_dat_i;   // memory data input
135
output reg [63:0] m_dat_o;
136
 
137
// Video
138
input dot_clk_i;                // Video clock 80 MHz
139
`ifdef INTERNAL_SYNC_GEN
140
output hsync_o;
141
output vsync_o;
142
output blank_o;
143
output border_o;
144
`else
145
input hsync_i;                  // start/end of scan line
146
input vsync_i;                  // start/end of frame
147
input blank_i;                  // blank the output
148
`endif
149
output [31:0] zrgb_o;            // 24-bit RGB output + z-order
150
reg [31:0] zrgb_o;
151
 
152
input xonoff_i;
153
 
154
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
155
// IO registers
156
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
157
reg m_cyc_o;
158
reg [31:0] m_adr_o;
159
 
160
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162
wire cs = s_cyc_i & s_stb_i & s_cs_i;
163
reg ack,ack1;
164
always @(posedge s_clk_i)
165
begin
166
        ack1 <= cs;
167
        ack <= ack1 & cs;
168
end
169
assign s_ack_o = cs ? (s_we_i ? 1'b1 : ack) : 1'b0;
170
 
171
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
172
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
173
integer n;
174
wire vclk;
175
reg [11:0] hDisplayed,vDisplayed;
176
reg [`ABITS] bm_base_addr1,bm_base_addr2;
177
reg [2:0] color_depth;
178
wire [7:0] fifo_cnt;
179
reg onoff;
180
reg [2:0] hres,vres;
181
reg greyscale;
182
reg page;
183
reg pals;                               // palette select
184
reg [11:0] hrefdelay;
185
reg [11:0] vrefdelay;
186
reg [11:0] map;     // memory access period
187
reg [11:0] mapctr;
188
reg [`ABITS] baseAddr;  // base address register
189
wire [127:0] rgbo1;
190
reg [11:0] pixelRow;
191
reg [11:0] pixelCol;
192
wire [31:0] pal_wo;
193
wire [31:0] pal_o;
194
reg [11:0] px;
195
reg [11:0] py;
196
reg [7:0] pz;
197
reg [1:0] pcmd,pcmd_o;
198
reg [3:0] raster_op;
199
reg [31:0] color;
200
reg [31:0] color_o;
201
reg rstcmd,rstcmd1;
202
reg [11:0] hTotal = phTotal;
203
reg [11:0] vTotal = pvTotal;
204
reg [11:0] hSyncOn = phSyncOn, hSyncOff = phSyncOff;
205
reg [11:0] vSyncOn = pvSyncOn, vSyncOff = pvSyncOff;
206
reg [11:0] hBlankOn = phBlankOn, hBlankOff = phBlankOff;
207
reg [11:0] vBlankOn = pvBlankOn, vBlankOff = pvBlankOff;
208
reg [11:0] hBorderOn = phBorderOn, hBorderOff = phBorderOff;
209
reg [11:0] vBorderOn = pvBorderOn, vBorderOff = pvBorderOff;
210
reg sgLock;
211
 
212
`ifdef INTERNAL_SYNC_GEN
213
wire hsync_i, vsync_i, blank_i;
214
 
215
VGASyncGen usg1
216
(
217
        .rst(rst_i),
218
        .clk(vclk),
219
        .eol(),
220
        .eof(),
221
        .hSync(hsync_o),
222
        .vSync(vsync_o),
223
        .hCtr(),
224
        .vCtr(),
225
  .blank(blank_o),
226
  .vblank(vblank),
227
  .vbl_int(),
228
  .border(border_o),
229
  .hTotal_i(hTotal),
230
  .vTotal_i(vTotal),
231
  .hSyncOn_i(hSyncOn),
232
  .hSyncOff_i(hSyncOff),
233
  .vSyncOn_i(vSyncOn),
234
  .vSyncOff_i(vSyncOff),
235
  .hBlankOn_i(hBlankOn),
236
  .hBlankOff_i(hBlankOff),
237
  .vBlankOn_i(vBlankOn),
238
  .vBlankOff_i(vBlankOff),
239
  .hBorderOn_i(hBorderOn),
240
  .hBorderOff_i(hBorderOff),
241
  .vBorderOn_i(vBorderOn),
242
  .vBorderOff_i(vBorderOff)
243
);
244
assign hsync_i = hsync_o;
245
assign vsync_i = vsync_o;
246
assign blank_i = blank_o;
247
`endif
248
 
249
edge_det edcs1
250
(
251
        .rst(rst_i),
252
        .clk(s_clk_i),
253
        .ce(1'b1),
254
        .i(cs),
255
        .pe(cs_edge),
256
        .ne(),
257
        .ee()
258
);
259
 
260
 
261
always @(page or bm_base_addr1 or bm_base_addr2)
262
        baseAddr = page ? bm_base_addr2 : bm_base_addr1;
263
 
264
// Color palette RAM for 8bpp modes
265
syncRam512x32_1rw1r upal1
266
(
267
        .wrst(1'b0),
268
        .wclk(s_clk_i),
269
        .wce(cs & s_adr_i[11]),
270
        .we(s_we_i),
271
        .wadr({2'b0,s_adr_i[9:3]}),
272
        .i(s_dat_i[31:0]),
273
        .wo(pal_wo),
274
        .rrst(1'b0),
275
        .rclk(vclk),
276
        .rce(1'b1),
277
        .radr({2'b0,pals,rgbo4[5:0]}),
278
        .o(pal_o)
279
);
280
 
281
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
283
always @(posedge s_clk_i)
284
if (rst_i) begin
285
        page <= 1'b0;
286
        pals <= 1'b0;
287
        hres <= 3'd2;
288
        vres <= 3'd2;
289
        hDisplayed <= 12'd400;
290
        vDisplayed <= 12'd300;
291
        onoff <= 1'b1;
292
        color_depth <= BPP16;
293
        greyscale <= 1'b0;
294
        bm_base_addr1 <= BM_BASE_ADDR1;
295
        bm_base_addr2 <= BM_BASE_ADDR2;
296
        hrefdelay <= 12'd154;//12'd218;
297
        vrefdelay <= 12'd10;//12'd27;
298
        map <= 12'd0;
299
        pcmd <= 2'b00;
300
        rstcmd1 <= 1'b0;
301
end
302
else begin
303
        rstcmd1 <= rstcmd;
304
  if (rstcmd & ~rstcmd1)
305
    pcmd <= 2'b00;
306
        if (cs_edge) begin
307
                if (s_we_i) begin
308
                        case(s_adr_i[11:3])
309
                        REG_CTRL:
310
                                begin
311
                                        if (s_sel_i[0]) onoff <= s_dat_i[0];
312
                                        if (s_sel_i[1]) begin
313
                                        color_depth <= s_dat_i[10:8];
314
                                        greyscale <= s_dat_i[11];
315
                                        end
316
                                        if (s_sel_i[2]) begin
317
                                        hres <= s_dat_i[18:16];
318
                                        vres <= s_dat_i[21:19];
319
                                        end
320
                                        if (s_sel_i[3]) begin
321
                                        page <= s_dat_i[24];
322
                                        pals <= s_dat_i[25];
323
                                        end
324
                                        if (|s_sel_i[7:6]) map <= s_dat_i[59:48];
325
                                end
326
                        REG_DISPLAYED:
327
                                begin
328
                                        if (|s_sel_i[1:0])       hDisplayed <= s_dat_i[11:0];
329
                                        if (|s_sel_i[3:2])  vDisplayed <= s_dat_i[27:16];
330
                                        if (|s_sel_i[5:4])      hrefdelay <= s_dat_i[43:32];
331
                                        if (|s_sel_i[7:6])  vrefdelay <= s_dat_i[59:48];
332
                                end
333
                        REG_PAGE1ADDR:  bm_base_addr1 <= s_dat_i;
334
                        REG_PAGE2ADDR:  bm_base_addr2 <= s_dat_i;
335
                        REG_PXYZ:
336
                                begin
337
                                        if (|s_sel_i[1:0])       px <= s_dat_i[11:0];
338
                                        if (|s_sel_i[3:2])      py <= s_dat_i[27:16];
339
                                        if (|s_sel_i[  4])      pz <= s_dat_i[39:32];
340
                                end
341
                        REG_PCOLCMD:
342
                                begin
343
                                        if (s_sel_i[0]) pcmd <= s_dat_i[1:0];
344
                            if (s_sel_i[2]) raster_op <= s_dat_i[19:16];
345
                            if (|s_sel_i[7:4]) color <= s_dat_i[63:32];
346
                          end
347
`ifdef INTERNAL_SYNC_GEN
348
                        REG_TOTAL:
349
                                begin
350
                                        if (!sgLock) begin
351
                                                if (|s_sel_i[1:0]) hTotal <= s_dat_i[11:0];
352
                                                if (|s_sel_i[3:2]) vTotal <= s_dat_i[27:16];
353
                                        end
354
                                        if (|s_sel_i[7:4]) begin
355
                                                if (s_dat_i[63:32]==32'hA1234567)
356
                                                        sgLock <= 1'b0;
357
                                                else if (s_dat_i[63:32]==32'h7654321A)
358
                                                        sgLock <= 1'b1;
359
                                        end
360
                                end
361
                        REG_SYNC_ONOFF:
362
                                if (!sgLock) begin
363
                                        if (|s_sel_i[1:0]) hSyncOff <= s_dat_i[11:0];
364
                                        if (|s_sel_i[3:2]) hSyncOn <= s_dat_i[27:16];
365
                                        if (|s_sel_i[5:4]) vSyncOff <= s_dat_i[43:32];
366
                                        if (|s_sel_i[7:6]) vSyncOn <= s_dat_i[59:48];
367
                                end
368
                        REG_BLANK_ONOFF:
369
                                if (!sgLock) begin
370
                                        if (|s_sel_i[1:0]) hBlankOff <= s_dat_i[11:0];
371
                                        if (|s_sel_i[3:2]) hBlankOn <= s_dat_i[27:16];
372
                                        if (|s_sel_i[5:4]) vBlankOff <= s_dat_i[43:32];
373
                                        if (|s_sel_i[7:6]) vBlankOn <= s_dat_i[59:48];
374
                                end
375
                        REG_BORDER_ONOFF:
376
                                begin
377
                                        if (|s_sel_i[1:0]) hBorderOff <= s_dat_i[11:0];
378
                                        if (|s_sel_i[3:2]) hBorderOn <= s_dat_i[27:16];
379
                                        if (|s_sel_i[5:4]) vBorderOff <= s_dat_i[43:32];
380
                                        if (|s_sel_i[7:6]) vBorderOn <= s_dat_i[59:48];
381
                                end
382
`endif
383
      default:  ;
384
                        endcase
385
                end
386
        end
387
  casez(s_adr_i[11:3])
388
  REG_CTRL:
389
      begin
390
          s_dat_o[0] <= onoff;
391
          s_dat_o[10:8] <= color_depth;
392
          s_dat_o[11] <= greyscale;
393
          s_dat_o[18:16] <= hres;
394
          s_dat_o[21:19] <= vres;
395
          s_dat_o[24] <= page;
396
          s_dat_o[25] <= pals;
397
          s_dat_o[59:48] <= map;
398
      end
399
  REG_DISPLAYED:        s_dat_o <= {4'h0,vrefdelay,4'h0,hrefdelay,4'h0,vDisplayed,4'h0,hDisplayed};
400
  REG_PAGE1ADDR:        s_dat_o <= bm_base_addr1;
401
  REG_PAGE2ADDR:        s_dat_o <= bm_base_addr2;
402
  REG_PXYZ:                 s_dat_o <= {20'h0,pz,4'h0,py,4'h0,px};
403
  REG_PCOLCMD:    s_dat_o <= {color_o,12'd0,raster_op,14'd0,pcmd};
404
  9'b10??_????_?:       s_dat_o <= {32'h0,pal_wo};
405
  default:        s_dat_o <= 64'd0;
406
  endcase
407
end
408
 
409
assign irq_o = 1'b0;
410
 
411
`ifdef USE_CLOCK_GATE
412
BUFHCE ucb1
413
(
414
        .I(dot_clk_i),
415
        .CE(onoff),
416
        .O(vclk)
417
);
418
`else
419
assign vclk = dot_clk_i;
420
`endif
421
 
422
 
423
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
424
// Horizontal and Vertical timing reference counters
425
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
426
 
427
wire pe_hsync, pe_hsync2;
428
wire pe_vsync;
429
edge_det edh1
430
(
431
        .rst(rst_i),
432
        .clk(vclk),
433
        .ce(1'b1),
434
        .i(hsync_i),
435
        .pe(pe_hsync),
436
        .ne(),
437
        .ee()
438
);
439
 
440
edge_det edh2
441
(
442
        .rst(rst_i),
443
        .clk(m_clk_i),
444
        .ce(1'b1),
445
        .i(hsync_i),
446
        .pe(pe_hsync2),
447
        .ne(),
448
        .ee()
449
);
450
 
451
edge_det edv1
452
(
453
        .rst(rst_i),
454
        .clk(vclk),
455
        .ce(1'b1),
456
        .i(vsync_i),
457
        .pe(pe_vsync),
458
        .ne(),
459
        .ee()
460
);
461
 
462
reg [3:0] hc;
463
always @(posedge vclk)
464
if (rst_i)
465
        hc <= 4'd1;
466
else if (pe_hsync) begin
467
        hc <= 4'd1;
468
        pixelCol <= -hrefdelay;
469
end
470
else begin
471
        if (hc==hres) begin
472
                hc <= 4'd1;
473
                pixelCol <= pixelCol + 1;
474
        end
475
        else
476
                hc <= hc + 4'd1;
477
end
478
 
479
reg [3:0] vc;
480
always @(posedge vclk)
481
if (rst_i)
482
        vc <= 4'd1;
483
else if (pe_vsync) begin
484
        vc <= 4'd1;
485
        pixelRow <= -vrefdelay;
486
end
487
else begin
488
        if (pe_hsync) begin
489
                vc <= vc + 4'd1;
490
                if (vc==vres) begin
491
                        vc <= 4'd1;
492
                        pixelRow <= pixelRow + 1;
493
                end
494
        end
495
end
496
 
497
// Bits per pixel minus one.
498
reg [4:0] bpp;
499
always @(color_depth)
500
case(color_depth)
501
BPP4: bpp = 3;
502
BPP8:   bpp = 7;
503
BPP12: bpp = 11;
504
BPP16:  bpp = 15;
505
BPP20:  bpp = 19;
506
BPP32:  bpp = 31;
507
endcase
508
 
509
reg [5:0] shifts;
510
always @(color_depth)
511
case(color_depth)
512
BPP4:   shifts = 6'd16;
513
BPP8:   shifts = 6'd8;
514
BPP12:  shifts = 6'd5;
515
BPP16:  shifts = 6'd4;
516
BPP20:  shifts = 6'd3;
517
BPP32:  shifts = 6'd2;
518
default:  shifts = 6'd4;
519
endcase
520
 
521
wire vFetch = pixelRow < vDisplayed;
522
wire fifo_rrst = pixelCol==12'hFFF;
523
wire fifo_wrst = pe_hsync2;
524
 
525
wire[31:0] grAddr,xyAddr;
526
reg [11:0] fetchCol;
527
wire [5:0] mb,me,ce;
528
reg [63:0] mem_strip;
529
wire [63:0] mem_strip_o;
530
wire [31:0] mem_color;
531
 
532
gfx_CalcAddress6 u1
533
(
534
  .clk(m_clk_i),
535
        .base_address_i(baseAddr),
536
        .color_depth_i(color_depth),
537
        .hdisplayed_i(hDisplayed),
538
        .x_coord_i(12'b0),
539
        .y_coord_i(pixelRow),
540
        .address_o(grAddr),
541
        .mb_o(),
542
        .me_o(),
543
        .ce_o()
544
);
545
 
546
gfx_CalcAddress6 u2
547
(
548
  .clk(m_clk_i),
549
        .base_address_i(baseAddr),
550
        .color_depth_i(color_depth),
551
        .hdisplayed_i(hDisplayed),
552
        .x_coord_i(px),
553
        .y_coord_i(py),
554
        .address_o(xyAddr),
555
        .mb_o(mb),
556
        .me_o(me),
557
        .ce_o(ce)
558
);
559
 
560
always @(posedge m_clk_i)
561
if (pe_hsync2)
562
  mapctr <= 12'hFFE;
563
else begin
564
  if (mapctr == map)
565
    mapctr <= 12'd0;
566
  else
567
    mapctr <= mapctr + 12'd1;
568
end
569
wire memreq = mapctr==12'd0;
570
 
571
// The following bypasses loading the fifo when all the pixels from a scanline
572
// are buffered in the fifo and the pixel row doesn't change. Since the fifo
573
// pointers are reset at the beginning of a scanline, the fifo can be used like
574
// a cache.
575
wire blankEdge;
576
edge_det ed2(.rst(rst_i), .clk(m_clk_i), .ce(1'b1), .i(blank_i), .pe(blankEdge), .ne(), .ee() );
577
reg do_loads;
578
reg [11:0] opixelRow;
579
reg load_fifo;
580
always @(posedge m_clk_i)
581
        //load_fifo <= fifo_cnt < 10'd1000 && vFetch && onoff && xonoff && !m_cyc_o && do_loads;
582
        load_fifo <= /*fifo_cnt < 8'd224 &&*/ vFetch && onoff && xonoff_i && fetchCol < hDisplayed && !m_cyc_o && do_loads && memreq;
583
// The following table indicates the number of pixel that will fit into the
584
// video fifo. 
585
reg [11:0] hCmp;
586
always @(color_depth)
587
case(color_depth)
588
BPP4: hCmp = 12'd4095;    // must be 12 bits
589
BPP8:   hCmp = 12'd2048;
590
BPP12: hCmp = 12'd1536;
591
BPP16:  hCmp = 12'd1024;
592
BPP20:  hCmp = 12'd768;
593
BPP32:  hCmp = 12'd512;
594
default:        hCmp = 12'd1024;
595
endcase
596
always @(posedge m_clk_i)
597
        // if hDisplayed > hCmp we always load because the fifo isn't large enough to act as a cache.
598
        if (!(hDisplayed < hCmp))
599
                do_loads <= 1'b1;
600
        // otherwise load the fifo only when the row changes to conserve memory bandwidth
601
        else if (vc==4'd1)//pixelRow != opixelRow)
602
                do_loads <= 1'b1;
603
        else if (blankEdge)
604
                do_loads <= 1'b0;
605
 
606
assign m_stb_o = m_cyc_o;
607
assign m_sel_o = 8'hFF;
608
 
609
reg [31:0] adr;
610
reg [3:0] state;
611
reg [127:0] icolor1;
612
parameter IDLE = 4'd0;
613
parameter LOADCOLOR = 4'd2;
614
parameter LOADSTRIP = 4'd3;
615
parameter STORESTRIP = 4'd4;
616
parameter ACKSTRIP = 4'd5;
617
parameter WAITLOAD = 4'd6;
618
parameter WAITRST = 4'd7;
619
parameter ICOLOR1 = 4'd8;
620
parameter ICOLOR2 = 4'd9;
621
parameter ICOLOR3 = 4'd10;
622
parameter ICOLOR4 = 4'd11;
623
parameter WAIT_NACK = 4'd12;
624
 
625
function rastop;
626
input [3:0] op;
627
input a;
628
input b;
629
case(op)
630
OPBLACK: rastop = 1'b0;
631
OPCOPY:  rastop = b;
632
OPINV:   rastop = ~a;
633
OPAND:   rastop = a & b;
634
OPOR:    rastop = a | b;
635
OPXOR:   rastop = a ^ b;
636
OPANDN:  rastop = a & ~b;
637
OPNAND:  rastop = ~(a & b);
638
OPNOR:   rastop = ~(a | b);
639
OPXNOR:  rastop = ~(a ^ b);
640
OPORN:   rastop = a | ~b;
641
OPWHITE: rastop = 1'b1;
642
endcase
643
endfunction
644
 
645
always @(posedge m_clk_i)
646
        if (fifo_wrst)
647
                adr <= grAddr;
648
  else begin
649
    if (state==WAITLOAD && m_ack_i)
650
      adr <= adr + 32'd8;
651
  end
652
 
653
always @(posedge m_clk_i)
654
        if (fifo_wrst)
655
                fetchCol <= 12'd0;
656
  else begin
657
    if (state==WAITLOAD && m_ack_i)
658
      fetchCol <= fetchCol + shifts;
659
  end
660
 
661
always @(posedge m_clk_i)
662
if (rst_i) begin
663
        wb_nack();
664
  rstcmd <= 1'b0;
665
  state <= IDLE;
666
end
667
else begin
668
        case(state)
669
  WAITRST:
670
    if (pcmd==2'b00 && ~m_ack_i) begin
671
      rstcmd <= 1'b0;
672
      state <= IDLE;
673
    end
674
    else
675
      rstcmd <= 1'b1;
676
  IDLE:
677
    if (load_fifo) begin
678
      m_cyc_o <= `HIGH;
679
      m_we_o <= `LOW;
680
      m_adr_o <= adr;
681
      state <= WAITLOAD;
682
    end
683
    // The adr_o[5:3]==3'b111 causes the controller to wait until all eight
684
    // 64 bit strips from the memory controller have been processed. Otherwise
685
    // there would be cache thrashing in the memory controller and the memory
686
    // bandwidth available would be greatly reduced. However fetches are also
687
    // allowed when loads are not active or all strips for the current scan-
688
    // line have been fetched.
689
    else if (pcmd!=2'b00 && (m_adr_o[5:3]==3'b111 || !(vFetch && onoff && xonoff_i && fetchCol < hDisplayed) || !do_loads)) begin
690
      m_cyc_o <= `HIGH;
691
      m_we_o <= `LOW;
692
      m_adr_o <= xyAddr;
693
      state <= LOADSTRIP;
694
    end
695
  LOADSTRIP:
696
    if (m_ack_i) begin
697
      wb_nack();
698
      mem_strip <= m_dat_i;
699
      icolor1 <= {32'b0,color} << mb;
700
      rstcmd <= 1'b1;
701
      if (pcmd==2'b01)
702
        state <= ICOLOR3;
703
      else if (pcmd==2'b10)
704
        state <= ICOLOR2;
705
      else begin
706
        state <= WAITRST;
707
      end
708
    end
709
  // Registered inline mem2color
710
  ICOLOR3:
711
    begin
712
      color_o <= mem_strip >> mb;
713
      state <= ICOLOR4;
714
    end
715
  ICOLOR4:
716
    begin
717
      for (n = 0; n < 32; n = n + 1)
718
        color_o[n] <= (n <= bpp) ? color_o[n] : 1'b0;
719
      state <= pcmd == 2'b0 ? (~m_ack_i ? IDLE : WAITRST) : WAITRST;
720
      if (pcmd==2'b00)
721
        rstcmd <= 1'b0;
722
    end
723
  // Registered inline color2mem
724
  ICOLOR2:
725
    begin
726
      for (n = 0; n < 64; n = n + 1)
727
        m_dat_o[n] <= (n >= mb && n <= me)
728
                ? ((n <= ce) ?  rastop(raster_op, mem_strip[n], icolor1[n]) : icolor1[n])
729
                : mem_strip[n];
730
      state <= STORESTRIP;
731
    end
732
  STORESTRIP:
733
    if (~m_ack_i) begin
734
      m_cyc_o <= `HIGH;
735
      m_we_o <= `HIGH;
736
      state <= ACKSTRIP;
737
    end
738
  ACKSTRIP:
739
    if (m_ack_i) begin
740
      wb_nack();
741
      state <= pcmd == 2'b0 ? WAIT_NACK : WAITRST;
742
      if (pcmd==2'b00)
743
        rstcmd <= 1'b0;
744
    end
745
  WAITLOAD:
746
    if (m_ack_i) begin
747
      wb_nack();
748
      state <= WAIT_NACK;
749
    end
750
  WAIT_NACK:
751
        if (~m_ack_i)
752
                state <= IDLE;
753
  default:      state <= IDLE;
754
  endcase
755
end
756
 
757
task wb_nack;
758
begin
759
        m_cyc_o <= `LOW;
760
        m_we_o <= `LOW;
761
end
762
endtask
763
 
764
reg [11:0] pixelColD1;
765
reg [31:0] rgbo2,rgbo4;
766
reg [63:0] rgbo3;
767
always @(posedge vclk)
768
case(color_depth)
769
BPP4:   rgbo4 <= {rgbo3[3],7'h00,21'd0,rgbo3[2:0]};      // feeds into palette
770
BPP8:   rgbo4 <= {rgbo3[7:6],6'h00,18'h0,rgbo3[5:0]};            // feeds into palette
771
BPP12:  rgbo4 <= {rgbo3[11:9],5'd0,rgbo3[8:6],5'd0,rgbo3[5:3],5'd0,rgbo3[2:0],5'd0};
772
BPP16:  rgbo4 <= {rgbo3[15:12],4'b0,rgbo3[11:8],4'b0,rgbo3[7:4],4'b0,rgbo3[3:0],4'b0};
773
BPP20:  rgbo4 <= {rgbo3[19:15],3'b0,rgbo3[14:10],4'b0,rgbo3[9:5],3'b0,rgbo3[4:0],3'b0};
774
BPP32:  rgbo4 <= rgbo3;
775
default:        rgbo4 <= {rgbo3[15:12],4'b0,rgbo3[11:8],4'b0,rgbo3[7:4],4'b0,rgbo3[3:0],4'b0};
776
endcase
777
 
778
reg rd_fifo,rd_fifo1,rd_fifo2;
779
reg de;
780
always @(posedge vclk)
781
        if (rd_fifo1)
782
                de <= ~blank_i;
783
 
784
always @(posedge vclk)
785
        if (onoff && xonoff_i && !blank_i) begin
786
                if (color_depth[2:1]==2'b00) begin
787
                        if (!greyscale)
788
                                zrgb_o <= pal_o[31:0];
789
                        else
790
                                zrgb_o <= {pal_o[31:24],{3{pal_o[7:0]}}};
791
                end
792
                else
793
                        zrgb_o <= rgbo4;
794
        end
795
        else
796
                zrgb_o <= 32'd0;
797
 
798
// Before the hrefdelay expires, pixelCol will be negative, which is greater
799
// than hDisplayed as the value is unsigned. That means that fifo reading is
800
// active only during the display area 0 to hDisplayed.
801
wire shift1 = hc==hres;
802
reg [4:0] shift_cnt;
803
always @(posedge vclk)
804
if (pe_hsync)
805
        shift_cnt <= 5'd1;
806
else begin
807
        if (shift1) begin
808
                if (pixelCol==12'hFFF)
809
                        shift_cnt <= shifts;
810
                else if (!pixelCol[11]) begin
811
                        shift_cnt <= shift_cnt + 5'd1;
812
                        if (shift_cnt==shifts)
813
                                shift_cnt <= 5'd1;
814
                end
815
                else
816
                        shift_cnt <= 5'd1;
817
        end
818
end
819
 
820
wire next_strip = (shift_cnt==shifts) && (hc==hres);
821
 
822
wire vrd;
823
always @(posedge vclk) pixelColD1 <= pixelCol;
824
reg shift,shift2;
825
always @(posedge vclk) shift2 <= shift1;
826
always @(posedge vclk) shift <= shift2;
827
always @(posedge vclk) rd_fifo2 <= next_strip;
828
always @(posedge vclk) rd_fifo <= rd_fifo2;
829
always @(posedge vclk)
830
        if (rd_fifo)
831
                rgbo3 <= rgbo1;
832
        else if (shift) begin
833
                case(color_depth)
834
                BPP4:   rgbo3 <= {4'h0,rgbo3[63:4]};
835
                BPP8:   rgbo3 <= {8'h0,rgbo3[63:8]};
836
                BPP12: rgbo3 <= {12'h0,rgbo3[63:12]};
837
                BPP16:  rgbo3 <= {16'h0,rgbo3[63:16]};
838
                BPP20:  rgbo3 <= {20'h0,rgbo3[63:20]};
839
                BPP32:  rgbo3 <= {32'h0,rgbo3[63:32]};
840
                endcase
841
        end
842
 
843
 
844
/* Debugging
845
wire [127:0] dat;
846
assign dat[11:0] = pixelRow[0] ? 12'hEA4 : 12'h000;
847
assign dat[23:12] = pixelRow[1] ? 12'hEA4 : 12'h000;
848
assign dat[35:24] = pixelRow[2] ? 12'hEA4 : 12'h000;
849
assign dat[47:36] = pixelRow[3] ? 12'hEA4 : 12'h000;
850
assign dat[59:48] = pixelRow[4] ? 12'hEA4 : 12'h000;
851
assign dat[71:60] = pixelRow[5] ? 12'hEA4 : 12'h000;
852
assign dat[83:72] = pixelRow[6] ? 12'hEA4 : 12'h000;
853
assign dat[95:84] = pixelRow[7] ? 12'hEA4 : 12'h000;
854
assign dat[107:96] = pixelRow[8] ? 12'hEA4 : 12'h000;
855
assign dat[119:108] = pixelRow[9] ? 12'hEA4 : 12'h000;
856
*/
857
 
858
rtfVideoFifo3 #(64) uf1
859
(
860
        .wrst(fifo_wrst),
861
        .wclk(m_clk_i),
862
        .wr(m_ack_i && state==WAITLOAD),
863
        .di(m_dat_i),
864
        .rrst(fifo_rrst),
865
        .rclk(vclk),
866
        .rd(rd_fifo),
867
        .dout(rgbo1),
868
        .cnt(fifo_cnt)
869
);
870
 
871
endmodule

powered by: WebSVN 2.1.0

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