1 |
2 |
ndumitrach |
//////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// This file is part of the Next186 Soc PC project
|
4 |
|
|
// http://opencores.org/project,next186
|
5 |
|
|
//
|
6 |
|
|
// Filename: vga.v
|
7 |
|
|
// Description: Part of the Next186 SoC PC project, VGA module
|
8 |
|
|
// customized VGA, only modes 3 (25x80x256 text), 13h (320x200x256 graphic)
|
9 |
|
|
// and VESA 101h (640x480x256) implemented
|
10 |
|
|
// Version 1.0
|
11 |
|
|
// Creation date: Jan2012
|
12 |
|
|
//
|
13 |
|
|
// Author: Nicolae Dumitrache
|
14 |
|
|
// e-mail: ndumitrache@opencores.org
|
15 |
|
|
//
|
16 |
|
|
/////////////////////////////////////////////////////////////////////////////////
|
17 |
|
|
//
|
18 |
|
|
// Copyright (C) 2012 Nicolae Dumitrache
|
19 |
|
|
//
|
20 |
|
|
// This source file may be used and distributed without
|
21 |
|
|
// restriction provided that this copyright statement is not
|
22 |
|
|
// removed from the file and that any derivative work contains
|
23 |
|
|
// the original copyright notice and the associated disclaimer.
|
24 |
|
|
//
|
25 |
|
|
// This source file is free software; you can redistribute it
|
26 |
|
|
// and/or modify it under the terms of the GNU Lesser General
|
27 |
|
|
// Public License as published by the Free Software Foundation;
|
28 |
|
|
// either version 2.1 of the License, or (at your option) any
|
29 |
|
|
// later version.
|
30 |
|
|
//
|
31 |
|
|
// This source is distributed in the hope that it will be
|
32 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
33 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
34 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more
|
35 |
|
|
// details.
|
36 |
|
|
//
|
37 |
|
|
// You should have received a copy of the GNU Lesser General
|
38 |
|
|
// Public License along with this source; if not, download it
|
39 |
|
|
// from http://www.opencores.org/lgpl.shtml
|
40 |
|
|
//
|
41 |
|
|
///////////////////////////////////////////////////////////////////////////////////
|
42 |
|
|
// Additional Comments:
|
43 |
|
|
//
|
44 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
45 |
|
|
|
46 |
|
|
`timescale 1 ns / 1 ps
|
47 |
|
|
|
48 |
|
|
module VGA_SG
|
49 |
|
|
(
|
50 |
|
|
input wire [9:0] tc_hsblnk,
|
51 |
|
|
input wire [9:0] tc_hssync,
|
52 |
|
|
input wire [9:0] tc_hesync,
|
53 |
|
|
input wire [9:0] tc_heblnk,
|
54 |
|
|
|
55 |
|
|
output reg [9:0] hcount = 0,
|
56 |
|
|
output reg hsync,
|
57 |
|
|
output reg hblnk = 0,
|
58 |
|
|
|
59 |
|
|
input wire [9:0] tc_vsblnk,
|
60 |
|
|
input wire [9:0] tc_vssync,
|
61 |
|
|
input wire [9:0] tc_vesync,
|
62 |
|
|
input wire [9:0] tc_veblnk,
|
63 |
|
|
|
64 |
|
|
output reg [9:0] vcount = 0,
|
65 |
|
|
output reg vsync,
|
66 |
|
|
output reg vblnk = 0,
|
67 |
|
|
|
68 |
|
|
input wire clk,
|
69 |
|
|
input wire ce
|
70 |
|
|
);
|
71 |
|
|
|
72 |
|
|
//******************************************************************//
|
73 |
|
|
// This logic describes a 10-bit horizontal position counter. //
|
74 |
|
|
//******************************************************************//
|
75 |
|
|
always @(posedge clk)
|
76 |
|
|
if(ce) begin
|
77 |
|
|
if(hcount >= tc_heblnk) begin
|
78 |
|
|
hcount <= 0;
|
79 |
|
|
hblnk <= 0;
|
80 |
|
|
end else begin
|
81 |
|
|
hcount <= hcount + 1;
|
82 |
|
|
hblnk <= (hcount >= tc_hsblnk);
|
83 |
|
|
end
|
84 |
|
|
hsync <= (hcount >= tc_hssync) && (hcount < tc_hesync);
|
85 |
|
|
end
|
86 |
|
|
|
87 |
|
|
//******************************************************************//
|
88 |
|
|
// This logic describes a 10-bit vertical position counter. //
|
89 |
|
|
//******************************************************************//
|
90 |
|
|
always @(posedge clk)
|
91 |
|
|
if(ce && hcount == tc_heblnk) begin
|
92 |
|
|
if (vcount >= tc_veblnk) begin
|
93 |
|
|
vcount <= 0;
|
94 |
|
|
vblnk <= 0;
|
95 |
|
|
end else begin
|
96 |
|
|
vcount <= vcount + 1;
|
97 |
|
|
vblnk <= (vcount >= tc_vsblnk);
|
98 |
|
|
end
|
99 |
|
|
vsync <= (vcount >= tc_vssync) && (vcount < tc_vesync);
|
100 |
|
|
end
|
101 |
|
|
|
102 |
|
|
//******************************************************************//
|
103 |
|
|
// This is the logic for the horizontal outputs. Active video is //
|
104 |
|
|
// always started when the horizontal count is zero. Example: //
|
105 |
|
|
//
|
106 |
|
|
//
|
107 |
|
|
// tc_hsblnk = 03 //
|
108 |
|
|
// tc_hssync = 07 //
|
109 |
|
|
// tc_hesync = 11 //
|
110 |
|
|
// tc_heblnk = 15 (htotal) //
|
111 |
|
|
// //
|
112 |
|
|
// hcount 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 //
|
113 |
|
|
// hsync ________________________------------____________ //
|
114 |
|
|
// hblnk ____________------------------------------------ //
|
115 |
|
|
// //
|
116 |
|
|
// hsync time = (tc_hesync - tc_hssync) pixels //
|
117 |
|
|
// hblnk time = (tc_heblnk - tc_hsblnk) pixels //
|
118 |
|
|
// active time = (tc_hsblnk + 1) pixels //
|
119 |
|
|
// //
|
120 |
|
|
//******************************************************************//
|
121 |
|
|
|
122 |
|
|
//******************************************************************//
|
123 |
|
|
// This is the logic for the vertical outputs. Active video is //
|
124 |
|
|
// always started when the vertical count is zero. Example: //
|
125 |
|
|
// //
|
126 |
|
|
// tc_vsblnk = 03 //
|
127 |
|
|
// tc_vssync = 07 //
|
128 |
|
|
// tc_vesync = 11 //
|
129 |
|
|
// tc_veblnk = 15 (vtotal) //
|
130 |
|
|
// //
|
131 |
|
|
// vcount 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 //
|
132 |
|
|
// vsync ________________________------------____________ //
|
133 |
|
|
// vblnk ____________------------------------------------ //
|
134 |
|
|
// //
|
135 |
|
|
// vsync time = (tc_vesync - tc_vssync) lines //
|
136 |
|
|
// vblnk time = (tc_veblnk - tc_vsblnk) lines //
|
137 |
|
|
// active time = (tc_vsblnk + 1) lines //
|
138 |
|
|
// //
|
139 |
|
|
//******************************************************************//
|
140 |
|
|
|
141 |
|
|
|
142 |
|
|
endmodule
|
143 |
|
|
|
144 |
|
|
|
145 |
|
|
module VGA_DAC(
|
146 |
|
|
input CE,
|
147 |
|
|
input WR,
|
148 |
|
|
input [3:0]addr,
|
149 |
|
|
input [7:0]din,
|
150 |
|
|
output OE,
|
151 |
|
|
output [7:0]dout,
|
152 |
|
|
input CLK,
|
153 |
|
|
input VGA_CLK,
|
154 |
|
|
input [7:0]vga_addr,
|
155 |
|
|
input setindex,
|
156 |
|
|
output [11:0]color,
|
157 |
|
|
output reg vgatext = 1,
|
158 |
|
|
output reg vga400 = 1,
|
159 |
|
|
output reg vgaflash = 0
|
160 |
|
|
);
|
161 |
|
|
|
162 |
|
|
reg [7:0]mask = 8'hff;
|
163 |
|
|
reg [9:0]index = 0;
|
164 |
|
|
reg mode = 0;
|
165 |
|
|
reg a0mode = 0;
|
166 |
|
|
reg a0data = 0;
|
167 |
|
|
wire [7:0]pal_dout;
|
168 |
|
|
wire [31:0]pal_out;
|
169 |
|
|
wire addr6 = addr == 6;
|
170 |
|
|
wire addr7 = addr == 7;
|
171 |
|
|
wire addr8 = addr == 8;
|
172 |
|
|
wire addr9 = addr == 9;
|
173 |
|
|
wire addr0 = addr == 0;
|
174 |
|
|
|
175 |
|
|
DAC_SRAM vga_dac
|
176 |
|
|
(
|
177 |
|
|
.clka(CLK), // input clka
|
178 |
|
|
.wea(CE & WR & addr9), // input [0 : 0] wea
|
179 |
|
|
.addra(index), // input [9 : 0] addra
|
180 |
|
|
.dina(din), // input [7 : 0] dina
|
181 |
|
|
.douta(pal_dout), // output [7 : 0] douta
|
182 |
|
|
.clkb(VGA_CLK), // input clkb
|
183 |
|
|
.web(1'b0), // input [0 : 0] web
|
184 |
|
|
.addrb(vga_addr & mask), // input [7 : 0] addrb
|
185 |
|
|
.dinb(32'hxxxxxxxx), // input [31 : 0] dinb
|
186 |
|
|
.doutb(pal_out) // output [31 : 0] doutb
|
187 |
|
|
);
|
188 |
|
|
|
189 |
|
|
assign color = {pal_out[21:18], pal_out[13:10], pal_out[5:2]};
|
190 |
|
|
assign dout = addr6 ? mask : addr7 ? {6'bxxxxxx, mode, mode} : addr8 ? index[9:2] : pal_dout;
|
191 |
|
|
assign OE = CE & (addr6 | addr7 | addr8 | addr9);
|
192 |
|
|
|
193 |
|
|
always @(posedge CLK) begin
|
194 |
|
|
|
195 |
|
|
if(setindex) a0data <= 0;
|
196 |
|
|
else if(CE && addr0 && WR) a0data <= ~a0data;
|
197 |
|
|
|
198 |
|
|
if(CE) begin
|
199 |
|
|
if(addr0) begin
|
200 |
|
|
if(WR) begin
|
201 |
|
|
if(~a0data && (din[4:0] == 5'h10)) a0mode <= 1;
|
202 |
|
|
else a0mode <= 0;
|
203 |
|
|
if(a0mode) begin
|
204 |
|
|
vgatext <= ~din[0];
|
205 |
|
|
vga400 <= din[6];
|
206 |
|
|
vgaflash <= din[3];
|
207 |
|
|
end
|
208 |
|
|
end
|
209 |
|
|
end
|
210 |
|
|
if(addr6 && WR) mask <= din;
|
211 |
|
|
if(addr7 | addr8) begin
|
212 |
|
|
if(WR) index <= {din, 2'b00};
|
213 |
|
|
mode <= addr8;
|
214 |
|
|
end else if(addr9) index <= index + (index[1:0] == 2'b10 ? 2 : 1);
|
215 |
|
|
end
|
216 |
|
|
end
|
217 |
|
|
|
218 |
|
|
endmodule
|
219 |
|
|
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
module VGA_CRT(
|
223 |
|
|
input CE,
|
224 |
|
|
input WR,
|
225 |
|
|
input [7:0]din,
|
226 |
|
|
input addr,
|
227 |
|
|
output [7:0]dout,
|
228 |
|
|
input CLK,
|
229 |
|
|
output reg oncursor,
|
230 |
|
|
output wire [11:0]cursorpos,
|
231 |
|
|
output wire [15:0]scraddr
|
232 |
|
|
);
|
233 |
|
|
|
234 |
|
|
reg [7:0]crtc[3:0];
|
235 |
|
|
reg [2:0]index = 0;
|
236 |
|
|
assign dout = crtc[index[1:0]];
|
237 |
|
|
assign cursorpos = {crtc[2][3:0], crtc[3]};
|
238 |
|
|
assign scraddr = {crtc[0], crtc[1]};
|
239 |
|
|
|
240 |
|
|
always @(posedge CLK) if(CE && WR) begin
|
241 |
|
|
if(addr) begin
|
242 |
|
|
if(index[2]) crtc[index[1:0]] <= din;
|
243 |
|
|
else if(index[1:0] == 2'b10) oncursor <= din[5];
|
244 |
|
|
end else index <= din[2:0];
|
245 |
|
|
end
|
246 |
|
|
endmodule
|