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

Subversion Repositories rtfbitmapcontroller

[/] [rtfbitmapcontroller/] [trunk/] [rtl/] [verilog/] [rtfBitmapController3.v] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//  Bitmap Controller3
4
//  - Displays a bitmap from memory.
5
//
6
//
7
//        __
8
//   \\__/ o\    (C) 2008-2015  Robert Finch, Stratford
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
//              $0400000 - the second 4MiB of RAM
30
//
31
//
32
//      Verilog 1995
33
//
34
// ref: XC7a100t-1CSG324
35
// 600 LUTs / 3 BRAMs / 425 FF's
36
// 196 MHz
37
// ============================================================================
38
 
39
module rtfBitmapController3(
40
        rst_i,
41
        s_clk_i, s_cyc_i, s_stb_i, s_ack_o, s_we_i, s_adr_i, s_dat_i, s_dat_o, irq_o,
42
        m_clk_i, m_bte_o, m_cti_o, m_cyc_o, m_stb_o, m_ack_i, m_we_o, m_sel_o, m_adr_o, m_dat_i, m_dat_o,
43
        vclk, hsync, vsync, blank, rgbo, xonoff
44
);
45
parameter pIOAddress = 32'hFFDC5000;
46
parameter BM_BASE_ADDR1 = 32'h0040_0000;
47
parameter BM_BASE_ADDR2 = 32'h0050_0000;
48
parameter REG_CTRL = 10'd0;
49
parameter REG_CTRL2 = 10'd1;
50
parameter REG_HDISPLAYED = 10'd2;
51
parameter REG_VDISPLAYED = 10'd3;
52
parameter REG_PAGE1ADDR = 10'd5;
53
parameter REG_PAGE2ADDR = 10'd6;
54
parameter REG_REFDELAY = 10'd7;
55
 
56
parameter BPP6 = 3'd0;
57
parameter BPP8 = 3'd1;
58
parameter BPP9 = 3'd2;
59
parameter BPP12 = 3'd3;
60
parameter BPP15 = 3'd4;
61
parameter BPP16 = 3'd5;
62
parameter BPP24 = 3'd6;
63
parameter BPP32 = 3'd7;
64
 
65
// SYSCON
66
input rst_i;                            // system reset
67
 
68
// Peripheral slave port
69
input s_clk_i;
70
input s_cyc_i;
71
input s_stb_i;
72
output s_ack_o;
73
input s_we_i;
74
input [31:0] s_adr_i;
75
input [31:0] s_dat_i;
76
output [31:0] s_dat_o;
77
reg [31:0] s_dat_o;
78
output irq_o;
79
 
80
// Video Master Port
81
// Used to read memory via burst access
82
input m_clk_i;                          // system bus interface clock
83
output [1:0] m_bte_o;
84
output [2:0] m_cti_o;
85
output m_cyc_o;                 // video burst request
86
output m_stb_o;
87
output m_we_o;
88
output [15:0] m_sel_o;
89
input  m_ack_i;                 // vid_acknowledge from memory
90
output [31:0] m_adr_o;   // address for memory access
91
input  [127:0] m_dat_i;  // memory data input
92
output [127:0] m_dat_o;
93
 
94
// Video
95
input vclk;                             // Video clock 85.71 MHz
96
input hsync;                            // start/end of scan line
97
input vsync;                            // start/end of frame
98
input blank;                    // blank the output
99
output [23:0] rgbo;              // 24-bit RGB output
100
reg [23:0] rgbo;
101
 
102
input xonoff;
103
 
104
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105
// IO registers
106
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107
reg m_cyc_o;
108
reg [31:0] m_adr_o;
109
 
110
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
112
wire cs = s_cyc_i && s_stb_i && (s_adr_i[31:12]==pIOAddress[31:12]);
113
reg ack,ack1;
114
always @(posedge s_clk_i)
115
begin
116
        ack1 <= cs;
117
        ack <= ack1 & cs;
118
end
119
assign s_ack_o = cs ? (s_we_i ? 1'b1 : ack) : 1'b0;
120
 
121
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123
reg [11:0] hDisplayed,vDisplayed;
124
reg [31:0] bm_base_addr1,bm_base_addr2;
125
reg [2:0] color_depth;
126
wire [7:0] fifo_cnt;
127
reg onoff;
128
reg [2:0] hres,vres;
129
reg greyscale;
130
reg page;
131
reg pals;                               // palette select
132
reg [11:0] hrefdelay;
133
reg [11:0] vrefdelay;
134
reg [11:0] hctr;         // horizontal reference counter
135
wire [11:0] hctr1 = hctr - hrefdelay;
136
reg [11:0] vctr;         // vertical reference counter
137
wire [11:0] vctr1 = vctr - vrefdelay;
138
reg [31:0] baseAddr;     // base address register
139
wire [127:0] rgbo1;
140
reg [11:0] pixelRow;
141
reg [11:0] pixelCol;
142
wire [31:0] pal_wo;
143
wire [31:0] pal_o;
144
 
145
always @(page or bm_base_addr1 or bm_base_addr2)
146
        baseAddr = page ? bm_base_addr2 : bm_base_addr1;
147
 
148
// Color palette RAM for 8bpp modes
149
syncRam512x32_1rw1r upal1
150
(
151
        .wrst(1'b0),
152
        .wclk(s_clk_i),
153
        .wce(cs & s_adr_i[11]),
154
        .we(s_we_i),
155
        .wadr(s_adr_i[10:2]),
156
        .i(s_dat_i),
157
        .wo(pal_wo),
158
        .rrst(1'b0),
159
        .rclk(vclk),
160
        .rce(1'b1),
161
        .radr({pals,rgbo4[7:0]}),
162
        .o(pal_o)
163
);
164
 
165
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
166
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
167
always @(posedge s_clk_i)
168
if (rst_i) begin
169
        page <= 1'b0;
170
        pals <= 1'b0;
171
        hres <= 3'd4;
172
        vres <= 3'd3;
173
        hDisplayed <= 12'd340;
174
        vDisplayed <= 12'd256;
175
        onoff <= 1'b1;
176
        color_depth <= BPP12;
177
        greyscale <= 1'b0;
178
        bm_base_addr1 <= BM_BASE_ADDR1;
179
        bm_base_addr2 <= BM_BASE_ADDR2;
180
        hrefdelay <= 12'd54;//12'd218;
181
        vrefdelay <= 12'd16;//12'd27;
182
end
183
else begin
184
        if (cs) begin
185
                if (s_we_i) begin
186
                        casex(s_adr_i[11:2])
187
                        REG_CTRL:
188
                                begin
189
                                        onoff <= s_dat_i[0];
190
                                        color_depth <= s_dat_i[10:8];
191
                                        greyscale <= s_dat_i[11];
192
                                        hres <= s_dat_i[18:16];
193
                                        vres <= s_dat_i[21:19];
194
                                end
195
                        REG_CTRL2:
196
                                begin
197
                                        page <= s_dat_i[16];
198
                                        pals <= s_dat_i[17];
199
                                end
200
                        REG_HDISPLAYED: hDisplayed <= s_dat_i[11:0];
201
                        REG_VDISPLAYED: vDisplayed <= s_dat_i[11:0];
202
                        REG_PAGE1ADDR:  bm_base_addr1 <= s_dat_i;
203
                        REG_PAGE2ADDR:  bm_base_addr2 <= s_dat_i;
204
                        REG_REFDELAY:
205
                                begin
206
                                        hrefdelay <= s_dat_i[11:0];
207
                                        vrefdelay <= s_dat_i[27:16];
208
                                end
209
                        endcase
210
                end
211
                casex(s_adr_i[11:2])
212
                REG_CTRL:
213
                        begin
214
                                s_dat_o[0] <= onoff;
215
                                s_dat_o[10:8] <= color_depth;
216
                                s_dat_o[11] <= greyscale;
217
                                s_dat_o[18:16] <= hres;
218
                                s_dat_o[21:19] <= vres;
219
                        end
220
                REG_CTRL2:
221
                        begin
222
                                s_dat_o[16] <= page;
223
                                s_dat_o[17] <= pals;
224
                        end
225
                REG_HDISPLAYED: s_dat_o <= hDisplayed;
226
                REG_VDISPLAYED: s_dat_o <= vDisplayed;
227
                REG_PAGE1ADDR:  s_dat_o <= bm_base_addr1;
228
                REG_PAGE2ADDR:  s_dat_o <= bm_base_addr2;
229
                REG_REFDELAY:   s_dat_o <= {vrefdelay,4'h0,hrefdelay};
230
                10'b1xxx_xxxx_xx:        s_dat_o <= pal_wo;
231
                endcase
232
        end
233
        else
234
                s_dat_o <= 32'd0;
235
end
236
 
237
assign irq_o = 1'b0;
238
 
239
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
240
// Horizontal and Vertical timing reference counters
241
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
242
 
243
wire pe_hsync;
244
wire pe_vsync;
245
edge_det edh1
246
(
247
        .rst(rst_i),
248
        .clk(vclk),
249
        .ce(1'b1),
250
        .i(hsync),
251
        .pe(pe_hsync),
252
        .ne(),
253
        .ee()
254
);
255
 
256
edge_det edv1
257
(
258
        .rst(rst_i),
259
        .clk(vclk),
260
        .ce(1'b1),
261
        .i(vsync),
262
        .pe(pe_vsync),
263
        .ne(),
264
        .ee()
265
);
266
 
267
reg [3:0] hc;
268
always @(posedge vclk)
269
if (rst_i)
270
        hc <= 4'd1;
271
else if (pe_hsync) begin
272
        hc <= 4'd1;
273
        pixelCol <= -hrefdelay;
274
end
275
else begin
276
        if (hc==hres) begin
277
                hc <= 4'd1;
278
                pixelCol <= pixelCol + 1;
279
        end
280
        else
281
                hc <= hc + 4'd1;
282
end
283
 
284
reg [3:0] vc;
285
always @(posedge vclk)
286
if (rst_i)
287
        vc <= 4'd1;
288
else if (pe_vsync) begin
289
        vc <= 4'd1;
290
        pixelRow <= -vrefdelay;
291
end
292
else begin
293
        if (pe_hsync) begin
294
                vc <= vc + 4'd1;
295
                if (vc==vres) begin
296
                        vc <= 4'd1;
297
                        pixelRow <= pixelRow + 1;
298
                end
299
        end
300
end
301
 
302
reg [4:0] shifts;
303
always @(color_depth)
304
case(color_depth)
305
BPP6:   shifts = 5'd21;
306
BPP8:   shifts = 5'd16;
307
BPP9:   shifts = 5'd14;
308
BPP12:  shifts = 5'd10;
309
BPP15:  shifts = 5'd8;
310
BPP16:  shifts = 5'd8;
311
BPP24:  shifts = 5'd5;
312
BPP32:  shifts = 5'd4;
313
endcase
314
 
315
wire vFetch = pixelRow < vDisplayed;
316
wire fifo_rrst = pixelCol==12'hFFE;
317
wire fifo_wrst = pe_hsync;
318
 
319
wire[31:0] grAddr;
320
reg [11:0] fetchCol;
321
 
322
gfx_CalcAddress u1
323
(
324
        .base_address_i(baseAddr),
325
        .color_depth_i(color_depth),
326
        .hdisplayed_i(hDisplayed),
327
        .x_coord_i(0),
328
        .y_coord_i(pixelRow),
329
        .address_o(grAddr),
330
        .mb_o(),
331
        .me_o()
332
);
333
 
334
// The following bypasses loading the fifo when all the pixels from a scanline
335
// are buffered in the fifo and the pixel row doesn't change. Since the fifo
336
// pointers are reset at the beginning of a scanline, the fifo can be used like
337
// a cache.
338
wire blankEdge;
339
edge_det ed2(.rst(rst_i), .clk(m_clk_i), .ce(1'b1), .i(blank), .pe(blankEdge), .ne(), .ee() );
340
reg do_loads;
341
reg [11:0] opixelRow;
342
reg load_fifo;
343
always @(posedge m_clk_i)
344
        //load_fifo <= fifo_cnt < 10'd1000 && vFetch && onoff && xonoff && !m_cyc_o && do_loads;
345
        load_fifo <= fifo_cnt < 8'd224 && vFetch && onoff && xonoff && fetchCol < hDisplayed && !m_cyc_o && do_loads;
346
reg [11:0] hCmp;
347
always @(color_depth)
348
case(color_depth)
349
BPP6:   hCmp = 12'd5120;
350
BPP8:   hCmp = 12'd4096;
351
BPP9:   hCmp = 12'd3583;
352
BPP12:  hCmp = 12'd2559;
353
BPP15:  hCmp = 12'd2048;
354
BPP16:  hCmp = 12'd2048;
355
BPP24:  hCmp = 12'd1279;
356
BPP32:  hCmp = 12'd1024;
357
default:        hCmp = 12'd1024;
358
endcase
359
always @(posedge m_clk_i)
360
        // if hDisplayed > hCmp we always load because the fifo isn't large enough to act as a cache.
361
        if (!(hDisplayed < hCmp))
362
                do_loads <= 1'b1;
363
        // otherwise load the fifo only when the row changes to conserve memory bandwidth
364
        else if (pixelRow != opixelRow)
365
                do_loads <= 1'b1;
366
        else if (blankEdge)
367
                do_loads <= 1'b0;
368
 
369
assign m_bte_o = 2'b00;
370
assign m_cti_o = 3'b000;
371
assign m_stb_o = 1'b1;
372
assign m_we_o = 1'b0;
373
assign m_sel_o = 16'hFFFF;
374
assign m_dat_o = 128'd0;
375
 
376
reg [31:0] adr;
377
always @(posedge m_clk_i)
378
if (rst_i) begin
379
        wb_nack();
380
        fetchCol <= 12'd0;
381
        opixelRow <= 12'hFFF;
382
end
383
else begin
384
        if (fifo_wrst) begin
385
                fetchCol <= 12'd0;
386
                adr <= grAddr;
387
                opixelRow <= pixelRow;
388
        end
389
        else if (load_fifo) begin
390
                m_cyc_o <= 1'b1;
391
                m_adr_o <= adr;
392
        end
393
        if (m_cyc_o & m_ack_i) begin
394
                fetchCol <= fetchCol + shifts;
395
                wb_nack();
396
                adr <= adr + 32'd16;
397
        end
398
end
399
 
400
task wb_nack;
401
begin
402
        m_cyc_o <= 1'b0;
403
end
404
endtask
405
 
406
reg [11:0] pixelColD1;
407
reg [23:0] rgbo2,rgbo4;
408
reg [127:0] rgbo3;
409
always @(posedge vclk)
410
        case(color_depth)
411
        BPP6:   rgbo4 <= greyscale ? {3{rgbo3[5:0],2'b00}} : {2'b00,rgbo3[5:0]};
412
        BPP8:   rgbo4 <= greyscale ? {3{rgbo3[7:0]}} : rgbo3[7:0];
413
        BPP9:   rgbo4 <= {rgbo3[8:6],5'b0,rgbo3[5:3],5'b0,rgbo3[2:0],5'b0};
414
        BPP12:  rgbo4 <= {rgbo3[11:8],4'h0,rgbo3[7:4],4'h0,rgbo3[3:0],4'h0};
415
        BPP15:  rgbo4 <= {rgbo3[14:10],3'b0,rgbo3[9:5],3'b0,rgbo3[4:0],3'b0};
416
        BPP16:  rgbo4 <= {rgbo3[15:11],3'b0,rgbo3[10:5],2'b0,rgbo3[4:0],3'b0};
417
        BPP24:  rgbo4 <= rgbo3;
418
        BPP32:  rgbo4 <= rgbo3[23:0];
419
        endcase
420
 
421
reg rd_fifo,rd_fifo1,rd_fifo2;
422
reg de;
423
always @(posedge vclk)
424
        if (rd_fifo1)
425
                de <= ~blank;
426
 
427
always @(posedge vclk)
428
        if (onoff && xonoff && !blank) begin
429
                if (color_depth[2:1]==2'b00 && !greyscale)
430
                        rgbo <= pal_o;
431
                else
432
                        rgbo <= rgbo4[23:0];
433
        end
434
        else
435
                rgbo <= 24'd0;
436
 
437
// Before the hrefdelay expires, pixelCol will be negative, which is greater
438
// than hDisplayed as the value is unsigned. That means that fifo reading is
439
// active only during the display area 0 to hDisplayed.
440
wire shift1 = hc==hres;
441
reg [4:0] shift_cnt;
442
always @(posedge vclk)
443
if (pe_hsync)
444
        shift_cnt <= 5'd1;
445
else begin
446
        if (shift1) begin
447
                if (pixelCol==12'hFFF)
448
                        shift_cnt <= shifts;
449
                else if (!pixelCol[11]) begin
450
                        shift_cnt <= shift_cnt + 5'd1;
451
                        if (shift_cnt==shifts)
452
                                shift_cnt <= 5'd1;
453
                end
454
                else
455
                        shift_cnt <= 5'd1;
456
        end
457
end
458
 
459
wire next_strip = (shift_cnt==shifts) && (hc==hres);
460
 
461
wire vrd;
462
always @(posedge vclk) pixelColD1 <= pixelCol;
463
reg shift,shift2;
464
always @(posedge vclk) shift2 <= shift1;
465
always @(posedge vclk) shift <= shift2;
466
always @(posedge vclk) rd_fifo2 <= next_strip;
467
always @(posedge vclk) rd_fifo <= rd_fifo2;
468
always @(posedge vclk)
469
        if (rd_fifo)
470
                rgbo3 <= rgbo1;
471
        else if (shift) begin
472
                case(color_depth)
473
                BPP6:   rgbo3 <= {rgbo3[127:6]};
474
                BPP8:   rgbo3 <= {rgbo3[127:8]};
475
                BPP9:   rgbo3 <= {rgbo3[127:9]};
476
                BPP12:  rgbo3 <= {rgbo3[127:12]};
477
                BPP15:  rgbo3 <= {rgbo3[127:16]};
478
                BPP16:  rgbo3 <= {rgbo3[127:16]};
479
                BPP24:  rgbo3 <= {rgbo3[127:24]};
480
                BPP32:  rgbo3 <= {rgbo3[127:32]};
481
                endcase
482
        end
483
 
484
 
485
rtfVideoFifo3 uf1
486
(
487
        .wrst(fifo_wrst),
488
        .wclk(m_clk_i),
489
        .wr(m_cyc_o & m_ack_i),
490
        .di(m_dat_i),
491
        .rrst(fifo_rrst),
492
        .rclk(vclk),
493
        .rd(rd_fifo),
494
        .dout(rgbo1),
495
        .cnt(fifo_cnt)
496
);
497
 
498
endmodule
499
 

powered by: WebSVN 2.1.0

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