OpenCores
URL https://opencores.org/ocsvn/a-z80/a-z80/trunk

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [host/] [zxspectrum_de1/] [ula/] [video.sv] - Blame information for rev 8

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

Line No. Rev Author Line
1 8 gdevic
//============================================================================
2
// Implementation of the Sinclair ZX Spectrum ULA
3
//
4
// This module contains video support.
5
//
6
// Note: There is no reset signal in this VGA design since all relevant
7
//       counters will reset themselves within one display frame as the
8
//       pixel clock keeps ticking.
9
//
10
//  Copyright (C) 2014-2016  Goran Devic
11
//
12
//  This program is free software; you can redistribute it and/or modify it
13
//  under the terms of the GNU General Public License as published by the Free
14
//  Software Foundation; either version 2 of the License, or (at your option)
15
//  any later version.
16
//
17
//  This program is distributed in the hope that it will be useful, but WITHOUT
18
//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20
//  more details.
21
//
22
//  You should have received a copy of the GNU General Public License along
23
//  with this program; if not, write to the Free Software Foundation, Inc.,
24
//  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
//============================================================================
26
module video
27
(
28
    input wire clk_pix,         // Input VGA pixel clock of 25.175 MHz
29
 
30
    output wire [3:0] VGA_R,    // Output VGA R component
31
    output wire [3:0] VGA_G,    // Output VGA G component
32
    output wire [3:0] VGA_B,    // Output VGA B component
33
    output reg VGA_HS,          // Output VGA horizontal sync
34
    output reg VGA_VS,          // Output VGA vertical sync
35
    output wire vs_nintr,       // Vertical retrace interrupt
36
 
37
    output wire [12:0] vram_address,// Address request to the video RAM
38
    input wire [7:0] vram_data, // Data read from the video RAM
39
 
40
    input wire [2:0] border     // Border color index value
41
);
42
 
43
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44
// VGA 640x480 Sync pulses generator
45
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46
reg [9:0] vga_hc;               // Horizontal counter
47
reg [9:0] vga_vc;               // Vertical counter
48
reg [4:0] frame;                // Frame counter, used for the flash attribute
49
 
50
always @(posedge clk_pix)
51
begin
52
    vga_hc <= vga_hc + 10'b1;   // With each pixel clock, advance the horizontal counter
53
    //---------------------------------------------------------------
54
    // Horizontal sync and line end timings
55
    //---------------------------------------------------------------
56
    case (vga_hc)
57
        96:     VGA_HS <= 1;
58
        800: begin
59
                VGA_HS <= 0;
60
                vga_hc <= 0;
61
                vga_vc <= vga_vc + 10'b1;
62
             end
63
    endcase
64
    //---------------------------------------------------------------
65
    // Vertical sync and display end timings
66
    //---------------------------------------------------------------
67
    case (vga_vc)
68
        2:      VGA_VS <= 1;
69
        525: begin
70
                VGA_VS <= 0;
71
                vga_vc <= 0;
72
                frame  <= frame + 5'b1;
73
             end
74
    endcase
75
end
76
 
77
// Generate interrupt at around the time of the vertical retrace start
78
assign vs_nintr = (vga_vc=='0 && vga_hc[9:7]=='0)? '0 : '1;
79
 
80
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81
// VGA active display area 640x480
82
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
83
wire disp_enable;
84
assign disp_enable = vga_hc>=144 && vga_hc<784 && vga_vc>=35 && vga_vc<515;
85
 
86
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87
// Fetch screen data from RAM based on the current video counters
88
// Spectrum resolution of 256x192 is line-doubled to 512x384 sub-frame
89
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90
wire screen_en;
91
assign screen_en = vga_hc>=208 && vga_hc<720 && vga_vc>=83 && vga_vc<467;
92
 
93
reg [7:0] bits_prefetch;        // Line bitmap data prefetch register
94
reg [7:0] attr_prefetch;        // Attribute data prefetch register
95
 
96
// At the first clock of each new character, prefetch values are latched into these:
97
reg [7:0] bits;                 // Current line bitmap data register
98
reg [7:0] attr;                 // Current attribute data register
99
 
100
wire [4:0] pix_x;               // Column 0-31
101
wire [7:0] pix_y;               // Active display pixel Y coordinate
102
// We use 16 clocks for 1 byte of display; also prefetch 1 byte (+16)
103
wire [9:0] xd = vga_hc-10'd192; // =vga_hc-208+16
104
assign pix_x = xd[8:4];         // Effectively divide by 16
105
wire [9:0] yd = vga_vc-10'd83;  // Lines are (also) doubled vertically
106
assign pix_y = yd[8:1];         // Effectively divide by 2
107
 
108
always @(posedge clk_pix)
109
begin
110
    case (vga_hc[3:0])
111
                // Format the address into the bitmap which is a swizzle of coordinate parts
112
        10:     vram_address <= {pix_y[7:6], pix_y[2:0], pix_y[5:3], pix_x};
113
        12:     begin
114
                    bits_prefetch <= vram_data;
115
                    // Format the address into the attribute map
116
                    vram_address <= {3'b110, pix_y[7:3], pix_x};
117
                end
118
        14:     attr_prefetch <= vram_data;
119
        // Last tick before a new character: load working bitmap and attribute registers
120
        15:     begin
121
                    attr <= attr_prefetch;
122
                    bits <= bits_prefetch;
123
                end
124
    endcase
125
end
126
 
127
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128
// Pixel data generator
129
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130
wire [2:0] ink;                 // INK color (index into the palette)
131
wire [2:0] paper;               // PAPER color
132
wire bright;                    // BRIGHT attribute bit
133
wire flash;                     // FLASH attribute bit
134
wire pixbit;                    // Current pixel to render
135
wire inverted;                  // Are the pixel's attributes inverted?
136
 
137
// Output a pixel bit based on the VGA horizontal counter. This could have been
138
// a shift register but a mux works as well since we are writing out each pixel
139
// twice (required by this VGA clock rate)
140
always @(*) // always_comb
141
begin
142
    case (vga_hc[3:1])
143
        0:      pixbit = bits[7];
144
        1:      pixbit = bits[6];
145
        2:      pixbit = bits[5];
146
        3:      pixbit = bits[4];
147
        4:      pixbit = bits[3];
148
        5:      pixbit = bits[2];
149
        6:      pixbit = bits[1];
150
        7:      pixbit = bits[0];
151
    endcase
152
end
153
 
154
assign flash  = attr[7];
155
assign bright = attr[6];
156
assign inverted = flash & frame[4];
157
assign ink    = inverted? attr[5:3] : attr[2:0];
158
assign paper  = inverted? attr[2:0] : attr[5:3];
159
 
160
// The final color index depends on where we are (active display area, border) and
161
// whether we are rendering INK or PAPER color, including the brightness bit
162
assign cindex = screen_en? pixbit? {bright,ink} : {bright,paper} : {1'b0,border[2:0]};
163
 
164
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165
// Color lookup table
166
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167
wire [3:0] cindex;
168
wire [11:0] pix_rgb;
169
 
170
always @(*) // always_comb
171
begin
172
    case (cindex[3:0])
173
        // Normal color
174
        0:   pix_rgb = 12'h000; // BLACK
175
        1:   pix_rgb = 12'h00D; // BLUE
176
        2:   pix_rgb = 12'hD00; // RED
177
        3:   pix_rgb = 12'hD0D; // MAGENTA
178
        4:   pix_rgb = 12'h0D0; // GREEN
179
        5:   pix_rgb = 12'h0DD; // CYAN
180
        6:   pix_rgb = 12'hDD0; // YELLOW
181
        7:   pix_rgb = 12'hDDD; // WHITE
182
        // "Bright" bit is set
183
        8:   pix_rgb = 12'h000; // BLACK remains black
184
        9:   pix_rgb = 12'h00F;
185
        10:  pix_rgb = 12'hF00;
186
        11:  pix_rgb = 12'hF0F;
187
        12:  pix_rgb = 12'h0F0;
188
        13:  pix_rgb = 12'h0FF;
189
        14:  pix_rgb = 12'hFF0;
190
        15:  pix_rgb = 12'hFFF;
191
    endcase
192
end
193
 
194
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195
// VGA RGB output drivers
196
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197
assign VGA_R[3:0] = disp_enable? pix_rgb[11:8] : '0;
198
assign VGA_G[3:0] = disp_enable? pix_rgb[7:4]  : '0;
199
assign VGA_B[3:0] = disp_enable? pix_rgb[3:0]  : '0;
200
 
201
endmodule

powered by: WebSVN 2.1.0

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