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

Subversion Repositories rtfbitmapcontroller

[/] [rtfbitmapcontroller/] [trunk/] [rtl/] [verilog/] [rtfBitmapController.v] - Blame information for rev 13

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

Line No. Rev Author Line
1 9 robfinch
`timescale 1ns / 1ps
2 4 robfinch
// ============================================================================
3 9 robfinch
//  Bitmap Controller
4 4 robfinch
//  - Displays a bitmap from memory.
5
//
6
//
7 9 robfinch
//        __
8
//   \\__/ o\    (C) 2008-2013  Robert Finch, Stratford
9
//    \  __ /    All rights reserved.
10
//     \/_//     robfinch<remove>@opencores.org
11
//       ||
12 4 robfinch
//
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 9 robfinch
//              $4100000 - the second 4MiB of RAM
30 4 robfinch
//
31
//
32
//      Verilog 1995
33
//
34 12 robfinch
// ref: XC6SLX45-3
35
// 600 LUTs / 2 BRAMs / 410 FF's
36
// 150 MHz
37 4 robfinch
// ============================================================================
38
 
39
module rtfBitmapController(
40 9 robfinch
        rst_i, 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,
41
        clk_i, bte_o, cti_o, bl_o, cyc_o, stb_o, ack_i, we_o, sel_o, adr_o, dat_i, dat_o,
42
        vclk, hSync, vSync, blank, rgbo, xonoff
43 4 robfinch
);
44 9 robfinch
parameter pIOAddress = 32'hFFDC5000;
45
parameter BM_BASE_ADDR1 = 32'h0410_0000;
46
parameter BM_BASE_ADDR2 = 32'h0420_0000;
47
parameter REG_CTRL = 12'd0;
48
parameter REG_CTRL2 = 12'd1;
49
parameter REG_HDISPLAYED = 12'd2;
50
parameter REG_VDISPLAYED = 12'd3;
51
parameter REG_PAGE1ADDR = 12'd5;
52
parameter REG_PAGE2ADDR = 12'd6;
53
parameter REG_REFDELAY = 12'd7;
54 4 robfinch
 
55
// SYSCON
56
input rst_i;                            // system reset
57
 
58 9 robfinch
// Peripheral slave port
59
input s_clk_i;
60
input s_cyc_i;
61
input s_stb_i;
62
output s_ack_o;
63
input s_we_i;
64
input [33:0] s_adr_i;
65
input [31:0] s_dat_i;
66
output [31:0] s_dat_o;
67
reg [31:0] s_dat_o;
68
output irq_o;
69
 
70 4 robfinch
// Video Master Port
71
// Used to read memory via burst access
72 9 robfinch
input clk_i;                            // system bus interface clock
73 4 robfinch
output [1:0] bte_o;
74
output [2:0] cti_o;
75 9 robfinch
output [5:0] bl_o;
76 4 robfinch
output cyc_o;                   // video burst request
77
output stb_o;
78
input  ack_i;                   // vid_acknowledge from memory
79
output we_o;
80 9 robfinch
output [ 3:0] sel_o;
81
output [33:0] adr_o;     // address for memory access
82
input  [31:0] dat_i;     // memory data input
83
output [31:0] dat_o;
84 4 robfinch
 
85
// Video
86 9 robfinch
input vclk;                             // Video clock 85.71 MHz
87
input hSync;                    // start/end of scan line
88
input vSync;                    // start/end of frame
89 4 robfinch
input blank;                    // blank the output
90 9 robfinch
output [23:0] rgbo;              // 8-bit RGB output
91
reg [23:0] rgbo;
92 4 robfinch
 
93 9 robfinch
input xonoff;
94 4 robfinch
 
95
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96
// IO registers
97
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98
reg [1:0] bte_o;
99
reg [2:0] cti_o;
100 9 robfinch
reg [5:0] bl_o;
101
reg sync_o;
102 4 robfinch
reg cyc_o;
103
reg stb_o;
104
reg we_o;
105 9 robfinch
reg [3:0] sel_o;
106
reg [33:0] adr_o;
107
reg [31:0] dat_o;
108 4 robfinch
 
109
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111 9 robfinch
wire cs = s_cyc_i && s_stb_i && (s_adr_i[33:14]==pIOAddress[31:12]);
112
reg ack,ack1;
113
always @(posedge clk_i)
114
begin
115
        ack1 <= cs;
116
        ack <= ack1 & cs;
117
end
118
assign s_ack_o = cs ? (s_we_i ? 1'b1 : ack) : 1'b0;
119
 
120
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122
reg [11:0] hDisplayed,vDisplayed;
123
reg [33:0] bm_base_addr1,bm_base_addr2;
124
reg [1:0] color_depth;
125
wire [8:0] fifo_cnt;
126
reg onoff;
127 12 robfinch
reg [1:0] vbl;                   // video burst length
128 9 robfinch
reg [1:0] hres,vres;
129 12 robfinch
reg greyscale;
130 9 robfinch
reg page;
131 12 robfinch
reg pals;                               // palette select
132 9 robfinch
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 [33:0] baseAddr;     // base address register
139
wire [31:0] rgbo1;
140 4 robfinch
reg [11:0] pixelRow;
141
reg [11:0] pixelCol;
142 9 robfinch
wire [31:0] pal_wo;
143
wire [31:0] pal_o;
144 4 robfinch
 
145 9 robfinch
always @(page or bm_base_addr1 or bm_base_addr2)
146
        baseAddr = page ? bm_base_addr2 : bm_base_addr1;
147 4 robfinch
 
148 12 robfinch
// Color palette RAM for 8bpp modes
149 9 robfinch
syncRam512x32_1rw1r upal1
150
(
151
        .wrst(1'b0),
152
        .wclk(s_clk_i),
153
        .wce(cs & s_adr_i[13]),
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 12 robfinch
        .radr({pals,rgbo4[7:0]}),
162 9 robfinch
        .o(pal_o)
163
);
164
 
165 4 robfinch
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
166 9 robfinch
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
167
always @(posedge s_clk_i)
168
if (rst_i) begin
169
        page <= 1'b0;
170 12 robfinch
        pals <= 1'b0;
171
        hres <= 2'b01;
172
        vres <= 2'b01;
173
        hDisplayed <= 12'd680;
174
        vDisplayed <= 12'd384;
175 9 robfinch
        onoff <= 1'b1;
176 12 robfinch
        vbl <= 2'b11;
177 9 robfinch
        color_depth <= 2'b00;
178 12 robfinch
        greyscale <= 1'b0;
179 9 robfinch
        bm_base_addr1 <= {BM_BASE_ADDR1,2'b00};
180
        bm_base_addr2 <= {BM_BASE_ADDR2,2'b00};
181
        hrefdelay <= 12'd218;
182
        vrefdelay <= 12'd27;
183
end
184
else begin
185
        if (cs) begin
186
                if (s_we_i) begin
187
                        casex(s_adr_i[13:2])
188
                        REG_CTRL:
189
                                begin
190
                                        onoff <= s_dat_i[0];
191 12 robfinch
                                        vbl <= s_dat_i[8:7];
192 9 robfinch
                                        color_depth <= s_dat_i[10:9];
193 12 robfinch
                                        greyscale <= s_dat_i[11];
194 9 robfinch
                                        hres <= s_dat_i[17:16];
195
                                        vres <= s_dat_i[19:18];
196
                                end
197
                        REG_CTRL2:
198
                                begin
199
                                        page <= s_dat_i[16];
200 12 robfinch
                                        pals <= s_dat_i[17];
201 9 robfinch
                                end
202
                        REG_HDISPLAYED: hDisplayed <= s_dat_i[11:0];
203
                        REG_VDISPLAYED: vDisplayed <= s_dat_i[11:0];
204
                        REG_PAGE1ADDR:  bm_base_addr1 <= {s_dat_i,2'b00};
205
                        REG_PAGE2ADDR:  bm_base_addr2 <= {s_dat_i,2'b00};
206
                        REG_REFDELAY:
207
                                begin
208
                                        hrefdelay <= s_dat_i[11:0];
209
                                        vrefdelay <= s_dat_i[27:16];
210
                                end
211
                        endcase
212
                end
213
                casex(s_adr_i[13:2])
214
                REG_CTRL:
215
                        begin
216
                                s_dat_o[0] <= onoff;
217 12 robfinch
                                s_dat_o[8:7] <= vbl;
218 9 robfinch
                                s_dat_o[10:9] <= color_depth;
219 12 robfinch
                                s_dat_o[11] <= greyscale;
220 9 robfinch
                                s_dat_o[17:16] <= hres;
221
                                s_dat_o[19:18] <= vres;
222
                        end
223
                REG_CTRL2:
224
                        begin
225
                                s_dat_o[16] <= page;
226 12 robfinch
                                s_dat_o[17] <= pals;
227 9 robfinch
                        end
228
                REG_HDISPLAYED: s_dat_o <= hDisplayed;
229
                REG_VDISPLAYED: s_dat_o <= vDisplayed;
230
                REG_PAGE1ADDR:  s_dat_o <= bm_base_addr1;
231
                REG_PAGE2ADDR:  s_dat_o <= bm_base_addr2;
232
                REG_REFDELAY:   s_dat_o <= {vrefdelay,4'h0,hrefdelay};
233
                12'b100x_xxxx_xxxx:     s_dat_o <= pal_wo;
234
                endcase
235
        end
236
        else
237
                s_dat_o <= 32'd0;
238
end
239
 
240
assign irq_o = 1'b0;
241
 
242
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
243 4 robfinch
// Horizontal and Vertical timing reference counters
244
// - The memory fetch address is determined from these counters.
245
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
246 9 robfinch
wire hSyncEdge, vSyncEdge;
247
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
248
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
249 4 robfinch
 
250 9 robfinch
always @(posedge vclk)
251
if (rst_i)              hctr <= 1;
252
else if (hSyncEdge) hctr <= 1;
253
else                    hctr <= hctr + 1;
254 4 robfinch
 
255 9 robfinch
always @(posedge vclk)
256
if (rst_i)              vctr <= 1;
257
else if (vSyncEdge) vctr <= 1;
258
else if (hSyncEdge) vctr <= vctr + 1;
259 4 robfinch
 
260 9 robfinch
 
261 4 robfinch
// Pixel row and column are derived from the horizontal and vertical counts.
262
 
263 12 robfinch
always @(posedge vclk)
264 9 robfinch
        case(vres)
265
        2'b00:          pixelRow <= vctr1[11:0];
266
        2'b01:          pixelRow <= vctr1[11:1];
267
        2'b10:          pixelRow <= vctr1[11:2];
268
        default:        pixelRow <= vctr1[11:2];
269
        endcase
270
always @(hctr1)
271
        case(hres)
272
        2'b00:          pixelCol = hctr1[11:0];
273
        2'b01:          pixelCol = hctr1[11:1];
274
        2'b10:          pixelCol = hctr1[11:2];
275
        default:        pixelCol = hctr1[11:2];
276
        endcase
277 4 robfinch
 
278 12 robfinch
wire vFetch = pixelRow < vDisplayed;
279 9 robfinch
wire fifo_rst = hctr[11:4]==8'h00;
280 4 robfinch
 
281 9 robfinch
wire[23:0] rowOffset = pixelRow * hDisplayed;
282
reg [11:0] fetchCol;
283 4 robfinch
 
284 12 robfinch
// The following bypasses loading the fifo when all the pixels from a scanline
285
// are buffered in the fifo and the pixel row doesn't change. Since the fifo
286
// pointers are reset at the beginning of a scanline, the fifo can be used like
287
// a cache.
288
wire blankEdge;
289
edge_det ed2(.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(blank), .pe(blankEdge), .ne(), .ee() );
290
reg do_loads;
291
reg [11:0] opixelRow;
292
reg load_fifo;
293
always @(posedge clk_i)
294
        load_fifo <= fifo_cnt < 9'd500 && vFetch && onoff && xonoff && fetchCol < hDisplayed && !cyc_o && do_loads;
295
always @(posedge clk_i)
296
        if (!(hDisplayed < (12'd2048 >> color_depth)))
297
                do_loads <= 1'b1;
298
        else if (pixelRow != opixelRow)
299
                do_loads <= 1'b1;
300
        else if (blankEdge)
301
                do_loads <= 1'b0;
302
 
303 4 robfinch
// - read from assigned video memory address, using burst mode reads
304 12 robfinch
// - 32 bytes (8 words) at a time are read
305 4 robfinch
//
306 9 robfinch
reg [5:0] bcnt;
307
wire [5:0] bcnt_inc = bcnt + 6'd1;
308
reg [33:0] adr;
309 4 robfinch
always @(posedge clk_i)
310
if (rst_i) begin
311 9 robfinch
        wb_nack();
312
        fetchCol <= 12'd0;
313
        bcnt <= 6'd0;
314 12 robfinch
        opixelRow <= 12'hFFF;
315 4 robfinch
end
316
else begin
317 9 robfinch
        if (fifo_rst) begin
318
                fetchCol <= 12'd0;
319
                adr <= baseAddr + rowOffset;
320 12 robfinch
                opixelRow <= pixelRow;
321 9 robfinch
        end
322 12 robfinch
        else if (load_fifo) begin
323
                cti_o <= vbl==2'b00 ? 3'b000 : 3'b001;  // constant address burst
324 4 robfinch
                cyc_o <= 1'b1;
325
                stb_o <= 1'b1;
326 9 robfinch
                sel_o <= 4'b1111;
327
                bcnt <= 6'd0;
328 12 robfinch
                case(vbl)
329
                2'b00:  bl_o <= 6'd0;
330
                2'b01:  bl_o <= 6'd1;
331
                2'b10:  bl_o <= 6'd3;
332
                2'b11:  bl_o <= 6'd7;
333
                endcase
334 9 robfinch
                adr_o <= adr;
335 4 robfinch
        end
336
        if (cyc_o & ack_i) begin
337 9 robfinch
                case(color_depth)
338
                2'b00:  fetchCol <= fetchCol + 12'd4;
339
                2'b01:  fetchCol <= fetchCol + 12'd2;
340
                2'b11:  fetchCol <= fetchCol + 12'd1;
341
                default:        fetchCol <= 12'hFF0;
342
                endcase
343
                bcnt <= bcnt_inc;
344
                if (bl_o==bcnt_inc)
345 12 robfinch
                        cti_o <= 3'b111;                // end of burst
346 9 robfinch
                else if (bl_o==bcnt) begin
347
                        wb_nack();
348
                        adr <= adr + 34'd32;
349 4 robfinch
                end
350
        end
351
end
352
 
353 9 robfinch
task wb_nack;
354
begin
355
        bte_o <= 2'b00;         // linear burst
356
        cti_o <= 3'b000;        // classic cycle
357
        bl_o <= 6'd0;
358
        cyc_o <= 1'b0;
359
        stb_o <= 1'b0;
360
        sel_o <= 4'b0000;
361
        we_o <= 1'b0;
362
        adr_o <= 34'h0000_0000;
363
        dat_o <= 32'h0000_0000;
364
end
365
endtask
366 4 robfinch
 
367 9 robfinch
reg [11:0] pixelColD1;
368
reg [31:0] rgbo2,rgbo3,rgbo4;
369 4 robfinch
always @(posedge vclk)
370 9 robfinch
        if (color_depth==2'b00)
371 12 robfinch
                rgbo4 <= greyscale ? {3{rgbo2[7:0]}} : rgbo2;
372 9 robfinch
        else if (color_depth==2'b01)
373
                rgbo4 <= {rgbo3[14:10],3'b0,rgbo3[9:5],3'b0,rgbo3[4:0],3'b0};
374
        else
375
                rgbo4 <= rgbo1;
376 4 robfinch
 
377
 
378 9 robfinch
reg rd_fifo,rd_fifo1,rd_fifo2;
379
reg de;
380
always @(posedge vclk)
381
        if (rd_fifo1)
382
                de <= ~blank;
383 4 robfinch
 
384 9 robfinch
always @(posedge vclk)
385
        if (onoff & xonoff & de) begin
386 12 robfinch
                if (color_depth==2'b00 && !greyscale)
387 9 robfinch
                        rgbo <= pal_o;
388
                else
389
                        rgbo <= rgbo4;
390
        end
391
        else
392
                rgbo <= 24'd0;
393
 
394
wire vrd;
395
always @(posedge vclk) pixelColD1 <= pixelCol;
396
always @(posedge vclk)
397
if (pixelCol < hDisplayed + 12'd8)
398
        case({color_depth,hres})
399
        4'b0000:        rd_fifo1 <= hctr[1:0]==2'b00;    // 4 clocks
400
        4'b0001:        rd_fifo1 <= hctr[2:0]==3'b000;   // 8 clocks
401
        4'b0010:        rd_fifo1 <= hctr[3:0]==4'b0000;  // 16 clocks
402
        4'b0011:        rd_fifo1 <= hctr[3:0]==4'b0000;  // unsupported
403
        4'b0100:        rd_fifo1 <= hctr[0]==1'b0;               // 2 clocks
404
        4'b0101:        rd_fifo1 <= hctr[1:0]==2'b00;    // 4 clocks
405
        4'b0110:        rd_fifo1 <= hctr[2:0]==3'b000;   // 8 clocks (twice as often as a byte)
406
        4'b0111:        rd_fifo1 <= hctr[2:0]==3'b000;
407
        4'b1000:        rd_fifo1 <= 1'b0;
408
        4'b1001:        rd_fifo1 <= 1'b0;
409
        4'b1010:        rd_fifo1 <= 1'b0;
410
        4'b1011:        rd_fifo1 <= 1'b0;
411
        4'b1100:        rd_fifo1 <= 1'b1;
412
        4'b1101:        rd_fifo1 <= hctr[0]==1'b0;
413
        4'b1110:        rd_fifo1 <= hctr[1:0]==2'b00;
414
        4'b1111:        rd_fifo1 <= hctr[1:0]==2'b00;
415
        endcase
416
reg shift,shift1,shift2;
417
always @(posedge vclk)
418
if (pixelCol < hDisplayed + 12'd8)
419
        case({color_depth,hres})
420
        // shift four times as often as a load
421
        4'b0000:        shift1 <= 1'b1;
422
        4'b0001:        shift1 <= hctr[0]==1'b0;
423
        4'b0010:        shift1 <= hctr[1:0]==2'b00;
424
        4'b0011:        shift1 <= hctr[1:0]==2'b00;
425
        // shift twice as often as a load
426
        4'b0100:        shift1 <= 1'b1;
427
        4'b0101:        shift1 <= hctr[0]==1'b0;
428
        4'b0110:        shift1 <= hctr[1:0]==2'b00;
429
        4'b0111:        shift1 <= hctr[1:0]==2'b00;
430
        // unsupported color depth
431
        4'b1000:        shift1 <= 1'b0;
432
        4'b1001:        shift1 <= 1'b0;
433
        4'b1010:        shift1 <= 1'b0;
434
        4'b1011:        shift1 <= 1'b0;
435
        // nothing to shift (all loads)
436
        4'b1100:        shift1 <= 1'b0;
437
        4'b1101:        shift1 <= 1'b0;
438
        4'b1110:        shift1 <= 1'b0;
439
        4'b1111:        shift1 <= 1'b0;
440
        endcase
441
always @(posedge vclk) shift2 <= shift1;
442
always @(posedge vclk) shift <= shift2;
443
always @(posedge vclk) rd_fifo2 <= rd_fifo1;
444
always @(posedge vclk) rd_fifo <= rd_fifo2;
445
always @(posedge vclk)
446
        if (rd_fifo)
447
                rgbo2 <= rgbo1;
448
        else if (shift)
449
                rgbo2 <= {8'h00,rgbo2[31:8]};
450
always @(posedge vclk)
451
        if (rd_fifo)
452
                rgbo3 <= rgbo1;
453
        else if (shift)
454
                rgbo3 <= {16'h0000,rgbo3[31:16]};
455
 
456
rtfVideoFifo uf1
457 4 robfinch
(
458 9 robfinch
        .rst(fifo_rst),
459
        .wclk(clk_i),
460
        .wr(cyc_o & ack_i),
461
        .di(dat_i),
462
        .rclk(vclk),
463
        .rd(rd_fifo),
464
        .do(rgbo1),
465
        .cnt(fifo_cnt)
466 4 robfinch
);
467
 
468
endmodule
469 9 robfinch
 

powered by: WebSVN 2.1.0

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