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

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [rtl/] [terasic_de2_70/] [drv_vga.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright 2010, Aleksander Osman, alfik@poczta.fm. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without modification, are
5
 * permitted provided that the following conditions are met:
6
 *
7
 *  1. Redistributions of source code must retain the above copyright notice, this list of
8
 *     conditions and the following disclaimer.
9
 *
10
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list
11
 *     of conditions and the following disclaimer in the documentation and/or other materials
12
 *     provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
 
25
/*! \file
26
 * \brief ADV7123 Video DAC driver for VGA output.
27
 */
28
 
29
/*! \brief \copybrief drv_vga.v
30
*/
31
module drv_vga(
32
        //% \name Clock and reset
33
    //% @{
34
        input clk_30,
35
        input reset_n,
36
        //% @}
37
 
38
        //% \name On-Screen-Display management interface
39
    //% @{
40
        input               management_mode,
41
        input               on_screen_display,
42
        output [4:0]        osd_line,
43
        output [4:0]        osd_column,
44
        input [7:0]         character,
45
        //% @}
46
 
47
        //% \name Control signal for VGA capture
48
    //% @{
49
        output              display_valid,
50
        //% @}
51
 
52
        //% \name Direct drv_ssram burst read DMA video interface
53
    //% @{
54
        output reg          burst_read_request,
55
        output reg [31:2]   burst_read_address,
56
        input               burst_read_ready,
57
        input [35:0]        burst_read_data,
58
        //% @}
59
 
60
        //% \name ADV7123 Video DAC hardware interface
61
    //% @{
62
        output [9:0]        vga_r,
63
        output [9:0]        vga_g,
64
        output [9:0]        vga_b,
65
        output              vga_blank_n,
66
        output              vga_sync_n,
67
        output              vga_clock,
68
        output              vga_hsync,
69
        output              vga_vsync
70
        //% @}
71
);
72
 
73
`define VGA_VIDEO_BUFFER            32'h10180000
74
`define VGA_VIDEO_BUFFER_DIV_4      30'h04060000
75
 
76
assign vga_blank_n = 1'b1;
77
assign vga_sync_n = 1'b0;
78
assign vga_clock = clk_30;
79
 
80
reg [7:0] address_a;
81
reg [7:0] address_b;
82
wire [35:0] q_b;
83
altsyncram line_ram_inst(
84
        .clock0(clk_30),
85
        .address_a(address_a),
86
        .wren_a(burst_read_ready),
87
        .data_a(burst_read_data),
88
 
89
        .clock1(clk_30),
90
        .address_b(address_b),
91
        .q_b(q_b)
92
);
93
defparam        line_ram_inst.operation_mode = "DUAL_PORT",
94
                        line_ram_inst.width_a = 36,
95
                        line_ram_inst.widthad_a = 8,
96
                        line_ram_inst.width_b = 36,
97
                        line_ram_inst.widthad_b = 8;
98
 
99
 
100
wire burst_read_prepare;
101
assign burst_read_prepare = (
102
    // time to start of next line: 129 + 150 -> enough for ssram write and read
103
        h_counter == (10'd799-10'd129) &&
104
        (
105
                v_counter == 9'd18 || /* before first line */
106
                (v_counter != 9'd498 && line_counter != 9'd511 && {line_counter + 9'd1} == next_line) /* other valid lines, without last line */
107
        )
108
) ? 1'b1 : 1'b0;
109
 
110
//      0,      2,      4,      6,      8,      10,     12,     14,
111
//      15,     17,     19,     21,     23,     25,     27,     29,
112
//      30,     32,     34,     36,     38,     40,     42,     44,
113
//      45, ...
114
//      
115
 
116
reg [8:0] next_line;
117
reg [2:0] next_counter;
118
always @(posedge clk_30 or negedge reset_n) begin
119
        if(reset_n == 1'b0) begin
120
                burst_read_request <= 1'b0;
121
                burst_read_address <= 30'd0;
122
                address_a <= 8'd0;
123
 
124
                next_line <= 9'd0;
125
                next_counter <= 3'd0;
126
        end
127
        else if(v_counter == 9'd0) begin
128
                burst_read_address <= `VGA_VIDEO_BUFFER_DIV_4; // start of video buffer
129
                next_line <= 9'd0;
130
                next_counter <= 3'd0;
131
        end
132
        else if(burst_read_prepare == 1'b1) begin
133
                burst_read_request <= 1'b1;
134
                address_a <= 8'd0;
135
        end
136
        else if(burst_read_ready == 1'b1 && address_a <= 8'd211) begin
137
                address_a <= address_a + 8'd1;
138
        end
139
        else if(burst_read_ready == 1'b1 && address_a == 8'd212) begin
140
                address_a <= address_a + 8'd1;
141
                burst_read_request <= 1'b0;
142
                burst_read_address <= burst_read_address + 30'd216; // 640/3 = 213.(3) = 214 +2 for %4 = 0
143
 
144
                next_counter <= next_counter + 3'd1;
145
 
146
                if(next_counter == 3'd7)        next_line <= next_line + 9'd1;
147
                else                                            next_line <= next_line + 9'd2;
148
        end
149
end
150
 
151
reg [1:0] three_counter;
152
always @(posedge clk_30 or negedge reset_n) begin
153
        if(reset_n == 1'b0) begin
154
                address_b <= 8'd0;
155
                three_counter <= 2'd0;
156
        end
157
        else if(display_valid == 1'b0) begin
158
                address_b <= 8'd0;
159
                three_counter <= 2'd1;
160
        end
161
        else if(three_counter == 2'd1) begin
162
                three_counter <= three_counter + 2'd1;
163
        end
164
        else if(three_counter == 2'd2) begin
165
            three_counter <= three_counter + 2'd1;
166
            address_b <= address_b + 8'd1;
167
        end
168
        else if(three_counter == 2'd3) begin
169
                three_counter <= 2'd1;
170
        end
171
end
172
 
173
wire [9:0] red =
174
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[31:29], 7'b0 } :
175
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[22:20], 7'b0 } :
176
        (management_mode == 1'b1)? { q_b[13:11], 7'b0 } :
177
    (three_counter == 2'd1) ? { q_b[35:32], 6'b0 } :
178
    (three_counter == 2'd2) ? { q_b[23:20], 6'b0 } :
179
    { q_b[11:8], 6'b0 };
180
 
181
wire [9:0] green =
182
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[28:26], 7'b0 } :
183
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[19:17], 7'b0 } :
184
        (management_mode == 1'b1)? { q_b[10:8], 7'b0 } :
185
        (three_counter == 2'd1) ? { q_b[31:28], 6'b0 } :
186
        (three_counter == 2'd2) ? { q_b[19:16], 6'b0 } :
187
        { q_b[7:4], 6'b0 };
188
 
189
wire [9:0] blue =
190
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[25:23], 7'b0 } :
191
        (management_mode == 1'b1 && three_counter == 2'd1)? { q_b[16:14], 7'b0 } :
192
        (management_mode == 1'b1)? { q_b[7:5], 7'b0 } :
193
    (three_counter == 2'd1) ? { q_b[27:24], 6'b0 } :
194
    (three_counter == 2'd2) ? { q_b[15:12], 6'b0 } :
195
    { q_b[3:0], 6'b0 };
196
 
197
//------------------------------------------------------------------------------ on screen display: 24 columns, 18 lines start
198
wire [8:0] line_counter_for_osd;
199
assign line_counter_for_osd     = line_counter - 9'd176;
200
wire [10:0] column_counter_for_osd;
201
assign column_counter_for_osd   = column_counter - 11'd8;
202
 
203
assign osd_line     = (line_counter >= 9'd176 /* 480-16-16x18 */ && line_counter < 9'd464 /* 480-16*/)? line_counter_for_osd[8:4]  : 5'd31;
204
assign osd_column   = (column_counter >= 11'd8 && column_counter < 11'd200 /* 8+24x8 */)?               column_counter_for_osd[7:3]: 5'd31;
205
 
206
reg [7:0] char_saved;
207
always @(posedge clk_30 or negedge reset_n) begin
208
    if(reset_n == 1'b0)                             char_saved <= 8'd0;
209
    else if(column_counter_for_osd[2:0] == 3'd6)    char_saved <= character;
210
end
211
 
212
//****************** Font
213
wire [8:0] font_line;
214
assign font_line = v_counter - 9'd3;
215
 
216
wire [9:0] font_column;
217
assign font_column = h_counter - 10'd6;
218
 
219
wire [7:0] font;
220
altsyncram font_rom_inst(
221
        .clock0(clk_30),
222
        .address_a({char_saved[6:0], font_line[3:0]}),
223
        .q_a(font)
224
);
225
defparam font_rom_inst.operation_mode = "ROM";
226
defparam font_rom_inst.width_a = 8;
227
defparam font_rom_inst.widthad_a = 11;
228
defparam font_rom_inst.init_file = "drv_vga_font.mif";
229
 
230
wire font_pixel;
231
assign font_pixel = char_saved[7] ^ font[font_column[2:0]];
232
 
233
wire osd_active;
234
assign osd_active = (on_screen_display == 1'b1 && osd_line != 5'd31 && osd_column != 5'd31);
235
//------------------------------------------------------------------------------ on screen display end
236
 
237
// 640x480@75Hz
238
reg [9:0] h_counter;
239
reg [8:0] v_counter;
240
always @(posedge clk_30 or negedge reset_n) begin
241
        if(reset_n == 1'b0) begin
242
            h_counter <= 10'd0;
243
            v_counter <= 9'd0;
244
        end
245
        else if(h_counter == 10'd799) begin
246
                h_counter <= 10'd0;
247
 
248
                if(v_counter == 9'd499)         v_counter <= 9'd0;
249
                else                                            v_counter <= v_counter + 9'd1;
250
        end
251
        else begin
252
                h_counter <= h_counter + 10'd1;
253
        end
254
end
255
 
256
assign vga_hsync = (h_counter >= 10'd0 && h_counter <= 10'd63) ? 1'b0 : 1'b1;
257
assign vga_vsync = (v_counter >= 9'd0 && v_counter <= 9'd2) ? 1'b0 : 1'b1;
258
 
259
wire [8:0] line_counter;
260
assign line_counter = (v_counter >= 9'd19 && v_counter <= 9'd498)? v_counter - 9'd19 : 9'd511;
261
 
262
wire [10:0] column_counter;
263
assign column_counter = (h_counter >= 10'd150 && h_counter <= 10'd789)? h_counter - 10'd150 : 10'd1023;
264
 
265
assign display_valid = (line_counter != 9'd511 && column_counter != 10'd1023);
266
 
267
assign vga_r = display_valid ? ((osd_active == 1'b0) ? red      : {10{font_pixel}}) : 10'd0;
268
assign vga_g = display_valid ? ((osd_active == 1'b0) ? green    : {10{font_pixel}}) : 10'd0;
269
assign vga_b = display_valid ? ((osd_active == 1'b0) ? blue     : {10{font_pixel}}) : 10'd0;
270
 
271
endmodule
272
 

powered by: WebSVN 2.1.0

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