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

Subversion Repositories rtfbitmapcontroller

[/] [rtfbitmapcontroller/] [trunk/] [rtl/] [verilog/] [rtfBitmapController2.v] - Blame information for rev 15

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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