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

Subversion Repositories layer2

[/] [layer2/] [trunk/] [vhdl/] [vga/] [rtl/] [vga.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 idiolatrie
--------------------------------------------------------------------------------
2
-- 8-Color 100x37 Textmode Video Controller                                   --
3
--------------------------------------------------------------------------------
4
--                                                                            --
5
-- IMPORTANT NOTICE                                                           --
6
--                                                                            --
7
--    I've spent alot of time to get the controller to work correctly. For    --
8
--    all those who try to implement their own: be strict with the sync       --
9
--    timing and don't paint outside the display area. To avoid a blurry      --
10
--    image, paint all 100px per line. I've painted only 99px and some        --
11
--    characters startet blinking on the edges. This happend because I didn't --
12
--    latch the sync and visible signals to synchronize them with the         --
13
--    character output (2 additional cycles). Another reason, why a character --
14
--    binks is due to the fact that the color needs to latched one cycle as   --
15
--    well.                                                                   --
16
--    If you want to save registers however, you can set the display boundary --
17
--    comparators to '<= H_DISP' and '<= V_DISP'. The display then has        --
18
--    801x601px but you can delete the 'hsync', 'vsync' and 'vis' shift regs. --
19
--    Hard to explain. If you get problems just contact me :)                 --
20
--                                                                            --
21
--------------------------------------------------------------------------------
22
-- Copyright (C)2011  Mathias Hörtnagl <mathias.hoertnagl@gmail.comt>         --
23
--                                                                            --
24
-- This program is free software: you can redistribute it and/or modify       --
25
-- it under the terms of the GNU General Public License as published by       --
26
-- the Free Software Foundation, either version 3 of the License, or          --
27
-- (at your option) any later version.                                        --
28
--                                                                            --
29
-- This program is distributed in the hope that it will be useful,            --
30
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
31
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              --
32
-- GNU General Public License for more details.                               --
33
--                                                                            --
34
-- You should have received a copy of the GNU General Public License          --
35
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.      --
36
--------------------------------------------------------------------------------
37
library ieee;
38
use ieee.std_logic_1164.all;
39
use ieee.numeric_std.all;
40
 
41
library work;
42
use work.iwb.all;
43
 
44
entity vga is
45
   port(
46
      si        : in  slave_in_t;
47
      so        : out slave_out_t;
48
   -- Non Wishbone Signals
49
      VGA_HSYNC : out std_logic;
50
      VGA_VSYNC : out std_logic;
51
      VGA_RED   : out std_logic;
52
      VGA_GREEN : out std_logic;
53
      VGA_BLUE  : out std_logic
54
   );
55
end vga;
56
 
57
architecture rtl of vga is
58
 
59
   -----------------------------------------------------------------------------
60
   -- Display settingss for 800x600@72Hz.                                     --
61
   -----------------------------------------------------------------------------
62
   constant H_MAX       : natural := 1040;   -- Complete horizontal width.
63
   constant H_DISP      : natural := 800;    -- Visible Display size.
64
   constant H_LOW_START : natural := 856;    -- H_DISP + front porch.
65
   constant H_LOW_END   : natural := 976;    -- H_LOW_START + sync low.
66
 
67
   constant V_MAX       : natural := 666;
68
   constant V_DISP      : natural := 600;
69
   constant V_LOW_START : natural := 637;
70
   constant V_LOW_END   : natural := 643;
71
 
72
 
73
   component rom is
74
      port(
75
         clk      : in  std_logic;
76
         rom_addr : in  std_logic_vector(11 downto 0);
77
         rom_word : out std_logic_vector(7 downto 0)
78
      );
79
   end component;
80
 
81
   attribute RAM_STYLE : string;
82
   attribute RAM_STYLE of rom : component is "BLOCK";
83
 
84
   component ram is
85
      port(
86
         clk  : in  std_logic;
87
         adrs : in  std_logic_vector(11 downto 0);
88
         adru : in  std_logic_vector(11 downto 0);
89
         we   : in  std_logic;
90
         stb  : in  std_logic;
91
         din  : in  std_logic_vector(15 downto 0);
92
         chr  : out std_logic_vector(7 downto 0);
93
         fgc  : out std_logic_vector(2 downto 0);
94
         bgc  : out std_logic_vector(2 downto 0);
95
         datu : out std_logic_vector(15 downto 0);
96
         ack  : out std_logic
97
      );
98
   end component;
99
 
100
   type video_t is record
101
      h     : unsigned(10 downto 0);
102
      v     : unsigned(9 downto 0);
103
      hsync : std_logic_vector(1 downto 0);
104
      vsync : std_logic_vector(1 downto 0);
105
      vis   : std_logic_vector(1 downto 0);
106
      fgc   : std_logic_vector(2 downto 0);
107
      bgc   : std_logic_vector(2 downto 0);
108
   end record;
109
 
110
   signal vidin, vid : video_t;
111
 
112
   signal adrs : unsigned(11 downto 0);             -- VGA display address.
113
   signal dat  : std_logic_vector(15 downto 0);     -- User write data.
114
   signal datu : std_logic_vector(15 downto 0);     -- User read data.
115
   signal chr  : std_logic_vector(7 downto 0);      -- Character ISO code.
116
   signal cbit : std_logic;                         -- One bit of 'chr'.
117
 
118
   signal rom_addr : std_logic_vector(11 downto 0); -- Character lines address.
119
   signal rom_word : std_logic_vector(7 downto 0);    -- One line of a character.
120
 
121
   signal red   : std_logic;
122
   signal green : std_logic;
123
   signal blue  : std_logic;
124
 
125
   -- Split up into ram and rom addresses for convinience.
126
   alias ah : unsigned(7 downto 0) is vid.h(10 downto 3);
127
   alias av : unsigned(5 downto 0) is vid.v(9 downto 4);
128
   alias ch : unsigned(2 downto 0) is vid.h(2 downto 0);
129
   alias cv : unsigned(3 downto 0) is vid.v(3 downto 0);
130
begin
131
 
132
   -----------------------------------------------------------------------------
133
   -- SYNCHRONIZATION                                                         --
134
   -----------------------------------------------------------------------------
135
   reg : process(si.clk)
136
   begin
137
      if rising_edge(si.clk) then
138
         vid <= vidin;
139
         if si.rst = '1' then
140
            vid.h <= "00000000000";
141
            vid.v <= "0000000000";
142
         end if;
143
      end if;
144
   end process;
145
 
146
   nsl : process(vid.h, vid.v, vid.hsync, vid.vsync, vid.vis)
147
   begin
148
 
149
      -- Horizontal counter.
150
      if vid.h = H_MAX-1 then
151
         vidin.h <= "00000000000";
152
      else
153
         vidin.h <= vid.h + 1;
154
      end if;
155
 
156
      -- Vertical counter.
157
      if (vid.v = V_MAX-1) and (vid.h >= H_LOW_START) then
158
         vidin.v <= "0000000000";
159
      elsif vid.h = H_MAX-1 then
160
         vidin.v <= vid.v + 1;
161
      else
162
         vidin.v <= vid.v;
163
      end if;
164
 
165
      -- The following 3 signals are implemented as shift registers. A character
166
      -- read takes 2 cycles. To set the sync and visible signals in time, we
167
      -- shift them once.
168
 
169
      -- Horizontal sync pulse.
170
      vidin.hsync(1) <= vid.hsync(0);
171
      if (vid.h >= H_LOW_START) and (vid.h < H_LOW_END) then
172
         vidin.hsync(0) <= '0';
173
      else
174
         vidin.hsync(0) <= '1';
175
      end if;
176
 
177
      -- Vertical sync pulse.
178
      vidin.vsync(1) <= vid.vsync(0);
179
      if (vid.v >= V_LOW_START) and (vid.v < V_LOW_END)  then
180
         vidin.vsync(0) <= '0';
181
      else
182
         vidin.vsync(0) <= '1';
183
      end if;
184
 
185
      -- Visible area is limited vertically and horizontally limited by V_DISP
186
      -- and H_DISP respectively. Drawing outside results in strange display
187
      -- behaviour.
188
      vidin.vis(1) <= vid.vis(0);
189
      if (vid.h < H_DISP) and (vid.v < V_DISP) then
190
         vidin.vis(0) <= '1';
191
      else
192
         vidin.vis(0) <= '0';
193
      end if;
194
   end process;
195
 
196
   -- Horizontal and vertical synchronization signals.
197
   VGA_HSYNC <= vid.hsync(1);
198
   VGA_VSYNC <= vid.vsync(1);
199
 
200
   -----------------------------------------------------------------------------
201
   -- DATAPATH                                                                --
202
   -----------------------------------------------------------------------------
203
   -- Calculate array loaction of a character the short way: y*100 + x.
204
   adrs <= (av&"000000") + (av&"00000") + (av&"00") + (ah);
205
 
206
   -- NOTE: Select either upper or lower halfword according to si.sel signal.
207
   -- Other signals then "1100" will store lower 16 bits!
208
   dat <= si.dat(31 downto 16) when si.sel = "1100" else si.dat(15 downto 0);
209
 
210
   video_ram : ram port map(
211
      clk  => si.clk,
212
      adrs => std_logic_vector(adrs),
213
      adru => si.adr(12 downto 1),
214
      we   => si.we,
215
      stb  => si.stb,
216
      din  => dat,
217
      chr  => chr,
218
      fgc  => vidin.fgc,
219
      bgc  => vidin.bgc,
220
      datu => datu,
221
      ack  => so.ack
222
   );
223
 
224
   -- Read vga memory.
225
   so.dat <= datu & x"0000" when si.sel = "1100" else x"0000" & datu;
226
 
227
   -- The current pixel row of a char is determined by its ASCII (or ISO) number
228
   -- and the row offset y (a character is 16 rows high).
229
   rom_addr <= chr & std_logic_vector(cv);
230
 
231
   char_table : rom port map(
232
      clk      => si.clk,
233
      rom_addr => rom_addr,
234
      rom_word => rom_word
235
   );
236
 
237
   -- The Python script <chars.py> creates the <rom.vhd> automatically by
238
   -- translating a <*.bdf> file. The resulting characters in <rom.vhd> are
239
   -- in reverese order and rotated 2 positions forward.
240
   -- The reversal is necessary, since the letters would be printed vertically
241
   -- inverted. Because of the delay due to the two memory stages (video ram,
242
   -- character rom), the x position pointer is 2 cycles ahead. By permanently
243
   -- rotating the character data 2px to the left, we do not need to subtract
244
   -- the x index by 2.
245
   cbit <= rom_word( to_integer(ch) );
246
 
247
   -- Determine color bit either foreground if cbit is set, background else.
248
   red   <= vid.fgc(2) when cbit = '1' else vid.bgc(2);
249
   green <= vid.fgc(1) when cbit = '1' else vid.bgc(1);
250
   blue  <= vid.fgc(0) when cbit = '1' else vid.bgc(0);
251
 
252
   -- Check if we are whtin the display area, pull to '0' if not. Otherwise we
253
   -- get weird behavior.
254
   VGA_RED   <= red   when vid.vis(1) = '1' else '0';
255
   VGA_GREEN <= green when vid.vis(1) = '1' else '0';
256
   VGA_BLUE  <= blue  when vid.vis(1) = '1' else '0';
257
end rtl;

powered by: WebSVN 2.1.0

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