OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [vga.vhd] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 howe.r.j.8
-------------------------------------------------------------------------------
2
--| @file vga.vhd
3
--| @brief      Text Mode Video Controller VHDL Module and VT100
4
--|             Terminal Emulator
5
--| @author     Javier Valcarce García
6
--| @author     Richard James Howe
7
--| @copyright  Copyright 2007 Javier Valcarce García, 2017 Richard James Howe
8
--| @license    LGPL version 3
9
--| @email      javier.valcarce@gmail.com
10
--| @note       (Modifications and repackaging by Richard James Howe)
11
--|
12
--| This is a modified version of the text terminal available at
13
--| <https://opencores.org/project,interface_vga80x40>. Additions include per
14
--| character attributes information and a VT100 terminal interface.
15
--|
16
--| @todo Make a VT100 test bench
17
--| @todo Fix/Remove processing of semi-colon separated attribute values
18
--| @todo Add scrolling by changing the base address "text_a", adding
19
--| a line
20
--| @todo Turn this into a stand alone project
21
-------------------------------------------------------------------------------
22
 
23
----- VGA Package -------------------------------------------------------------
24
library ieee,work;
25
use ieee.std_logic_1164.all;
26
use ieee.numeric_std.all;
27
 
28
package vga_pkg is
29
        type vga_physical_interface is record
30
                red:   std_ulogic_vector(2 downto 0);
31
                green: std_ulogic_vector(2 downto 0);
32
                blue:  std_ulogic_vector(1 downto 0);
33
                hsync: std_ulogic;
34
                vsync: std_ulogic;
35
        end record;
36
 
37
        type vga_control_registers_we_interface is record
38
                crx: std_ulogic; -- Write enable for cursor X position register
39
                cry: std_ulogic; -- Write enable for VGA control register
40
                ctl: std_ulogic; -- Write enable for cursor Y position register
41
        end record;
42
 
43
        type vga_control_registers_interface is record
44
                crx:    std_ulogic_vector(6 downto 0); -- Cursor position X
45
                cry:    std_ulogic_vector(5 downto 0); -- Cursor position Y
46
                ctl:    std_ulogic_vector(4 downto 0); -- Control register
47
        end record;
48
 
49
        constant vga_control_registers_initialize: vga_control_registers_interface := (
50
                        cry => (others => '0'),
51
                        crx => (others => '0'),
52
                        ctl => (others => '0'));
53
 
54
        constant vga_control_registers_we_initialize: vga_control_registers_we_interface := (
55
                        cry => '0',
56
                        crx => '0',
57
                        ctl => '0');
58
 
59
        component vga_top is
60
        port(
61
                clk:         in  std_ulogic;
62
                clk25MHz:    in  std_ulogic;
63
                rst:         in  std_ulogic;
64
 
65
                -- VGA Text buffer interface
66
                vga_we_ram:  in  std_ulogic; -- Write enable RAM
67
                vga_din:     in  std_ulogic_vector(15 downto 0);
68
                vga_addr:    in  std_ulogic_vector(12 downto 0);
69
                vga_dout:    out std_ulogic_vector(15 downto 0):= (others => '0');
70
 
71
                -- VGA control registers
72
                i_vga_control_we: in vga_control_registers_we_interface;
73
                i_vga_control:    in vga_control_registers_interface;
74
 
75
                o_vga:    out vga_physical_interface);
76
        end component;
77
 
78
        -- VGA test bench, not-synthesizeable
79
        component vga_core is
80
        port (
81
                rst:       in  std_ulogic;
82
                clk25MHz:  in  std_ulogic;
83
                text_a:    out std_ulogic_vector(11 downto 0); -- text buffer
84
                text_d:    in  std_ulogic_vector( 7 downto 0);
85
                font_a:    out std_ulogic_vector(11 downto 0); -- font buffer
86
                font_d:    in  std_ulogic_vector( 7 downto 0);
87
                 --
88
                ocrx:      in  std_ulogic_vector(6 downto 0);
89
                ocry:      in  std_ulogic_vector(5 downto 0);
90
                octl:      in  std_ulogic_vector(3 downto 0);
91
                --
92
                foreground_draw: out std_ulogic;
93
                background_draw: out std_ulogic;
94
                hsync:     out std_ulogic;
95
                vsync:     out std_ulogic);
96
        end component;
97
 
98
        component losr is
99
        generic (N: positive := 4);
100
        port
101
        (
102
                rst:  in  std_ulogic;
103
                clk:  in  std_ulogic;
104
                load: in  std_ulogic;
105
                ce:   in  std_ulogic;
106
                do:   out std_ulogic := '0';
107
                di:   in  std_ulogic_vector(N - 1 downto 0));
108
        end component;
109
 
110
        component ctrm is
111
        generic (M: positive := 8);
112
        port (
113
                rst: in  std_ulogic; -- asynchronous rst
114
                clk: in  std_ulogic;
115
                ce:  in  std_ulogic; -- enable counting
116
                rs:  in  std_ulogic; -- synchronous rst
117
                do:  out integer range (M-1) downto 0 := 0);
118
        end component;
119
 
120
        component vt100 is
121
        port(
122
                clk:        in  std_ulogic;
123
                clk25MHz:   in  std_ulogic;
124
                rst:        in  std_ulogic;
125
                we:         in  std_ulogic;
126
                char:       in  std_ulogic_vector(7 downto 0);
127
 
128
                busy:       out std_ulogic;
129
                o_vga:      out vga_physical_interface);
130
        end component;
131
 
132
        component vt100_tb is
133
                generic(clock_frequency: positive);
134
        end component;
135
 
136
        component atoi is
137
                generic(
138
                        N:      positive := 16);
139
                port(
140
                        clk:    in  std_ulogic;
141
                        rst:    in  std_ulogic;
142
                        we:     in  std_ulogic;
143
                        init:   in  std_ulogic;
144
                        char:   in  std_ulogic_vector(7 downto 0);
145
                        char_o: out std_ulogic_vector(7 downto 0);
146
                        done_o: out std_ulogic;
147
                        ready:  out std_ulogic;
148
                        n_o:    out unsigned(N - 1 downto 0));
149
        end component;
150
 
151
end package;
152
 
153
----- VGA Package -------------------------------------------------------------
154
 
155
----- VGA Test Bench ----------------------------------------------------------
156
 
157
library ieee;
158
use ieee.std_logic_1164.all;
159
use ieee.numeric_std.all;
160
use work.vga_pkg.all;
161
use ieee.math_real.all;
162
use work.util.all;
163
 
164
entity vt100_tb is
165
        generic(clock_frequency: positive);
166
end entity;
167
 
168
architecture behav of vt100_tb is
169
        constant clock_period: time := 1000 ms / clock_frequency;
170
        signal clk, rst: std_ulogic := '0';
171
        signal stop:     std_ulogic := '0';
172
        signal clk25MHz, rst25MHz: std_ulogic := '0';
173
 
174
        signal char:     std_ulogic_vector(7 downto 0);
175
        signal we:       std_ulogic := '0';
176
        signal busy:     std_ulogic := '0';
177
        signal physical: vga_physical_interface;
178
 
179
        -- NB. 'string' range is (1 to X), not (X-1 downto 0)
180
        -- HT = Horizontal Tab
181
        -- LF = Line Feed
182
        -- CR = Carriage Return
183
        -- ESC = Escape
184
        constant CSI: string := ESC & "[";
185
        constant RESET: string := CSI & "0m";
186
        constant RED:   string := CSI & "31m";
187
        constant GREEN: string := CSI & "32m";
188
        constant NL:  string := CR & LF;
189
        constant test_string: string := "Hello!" & HT & "World!" & RED & NL & "How are you?" & RESET & NL ;
190
        shared variable test_vector: ulogic_string(test_string'range) := to_std_ulogic_vector(test_string);
191
        shared variable index: integer := 1; -- starts at '1' due to string range
192
begin
193
        cs: entity work.clock_source_tb
194
                generic map(clock_frequency => clock_frequency, hold_rst => 2)
195
                port map(stop => stop, clk => clk, rst => rst);
196
 
197
        cs25MHz: entity work.clock_source_tb
198
                generic map(clock_frequency => 25000000, hold_rst => 2)
199
                port map(stop => stop, clk => clk25MHz, rst => rst25MHz);
200
 
201
 
202
        uut: work.vga_pkg.vt100
203
        port map(
204
                clk      => clk,
205
                clk25MHz => clk25MHz,
206
                rst      => rst,
207
                we       => we,
208
                char     => char,
209
                busy     => busy,
210
                o_vga    => physical);
211
 
212
        stimulus_process: process
213
        begin
214
                char <= test_vector(index);
215
                we <= '0';
216
                wait for clock_period * 20;
217
 
218
                for i in test_vector'range loop
219
                        we <= '1';
220
                        char <= test_vector(index);
221
                        wait for clock_period;
222
                        we <= '0';
223
                        wait for clock_period;
224
 
225
                        while busy = '1' loop
226
                                wait until busy = '0';
227
                                wait for clock_period;
228
                        end loop;
229
 
230
                        -- wait for clock_period * 20;
231
                        -- wait until busy = '0';
232
                        -- report integer'image(index);
233
                        if index < (test_vector'high - 1) then
234
                                index := index + 1;
235
                        else
236
                                index := 1;
237
                        end if;
238
                end loop;
239
 
240
                stop <= '1';
241
                wait;
242
        end process;
243
end architecture;
244
 
245
----- VGA Test Bench ----------------------------------------------------------
246
 
247
----- ATOI --------------------------------------------------------------------
248
-- The purpose of this module is to read in numeric characters ('0' through
249
-- '9') and convert the string into a binary number ('n_o'). On the first non-
250
-- numeric character the module stops and outputs that non-numeric character
251
-- as well as the converted number string. The module waits in the FINISHED
252
-- state until the module is reset by an external signal ('init').
253
--
254
-- The module is named after the C function, 'atoi', for converting a string
255
-- into an integer.
256
--
257
 
258
library ieee,work;
259
use ieee.std_logic_1164.all;
260
use ieee.numeric_std.all;
261
use work.vga_pkg.all;
262
 
263
entity atoi is
264
        generic(
265
                N:      positive := 16);
266
        port(
267
                clk:    in  std_ulogic;
268
                rst:    in  std_ulogic;
269
                we:     in  std_ulogic;
270
                init:   in  std_ulogic;
271
                char:   in  std_ulogic_vector(7 downto 0);
272
                char_o: out std_ulogic_vector(7 downto 0);
273
                done_o: out std_ulogic;
274
                ready:  out std_ulogic;
275
                n_o:    out unsigned(N - 1 downto 0));
276
end entity;
277
 
278
architecture rlt of atoi is
279
        type state_type is (RESET, WAITING, COMMAND, ACCUMULATE, WRITE, FINISHED);
280
        signal state_c, state_n: state_type   := RESET;
281
        signal c_c, c_n: unsigned(char'range) := (others => '0');
282
        signal n_c, n_n: unsigned(n_o'range)  := (others => '0');
283
        signal f_c, f_n: boolean              := true;
284
begin
285
        char_o <= std_ulogic_vector(c_c);
286
        n_o    <= n_c;
287
        ready  <= '1' when state_c = WAITING else '0';
288
 
289
        process(clk, rst)
290
                variable akk: unsigned((2 * N) - 1 downto 0) := (others => '0');
291
        begin
292
                if rst = '1' then
293
                        state_n   <= RESET;
294
                elsif rising_edge(clk) then
295
                        state_c <= state_n;
296
                        c_c     <= c_n;
297
                        n_c     <= n_n;
298
                        f_c     <= f_n;
299
                        done_o  <= '0';
300
 
301
                        if state_c = RESET then
302
                                c_n     <= (others => '0');
303
                                n_n     <= (others => '0');
304
                                f_n     <= true;
305
                                state_n <= WAITING;
306
                        elsif state_c = WAITING then
307
                                if we = '1' then
308
                                        c_n     <= unsigned(char);
309
                                        state_n <= COMMAND;
310
                                end if;
311
                        elsif state_c = COMMAND then
312
                                state_n <= ACCUMULATE;
313
                                case c_c is
314
                                when x"30"  =>
315
                                when x"31"  =>
316
                                when x"32"  =>
317
                                when x"33"  =>
318
                                when x"34"  =>
319
                                when x"35"  =>
320
                                when x"36"  =>
321
                                when x"37"  =>
322
                                when x"38"  =>
323
                                when x"39"  =>
324
                                when others =>
325
                                        state_n <= WRITE;
326
                                end case;
327
                        elsif state_c = ACCUMULATE then
328
                                if f_c then
329
                                        f_n <= false;
330
                                        n_n <= n_c + (c_c - x"30");
331
                                else
332
                                        akk := n_c * to_unsigned(10, N);
333
                                        n_n <= akk(N - 1 downto 0) + (c_c - x"30");
334
                                end if;
335
                                state_n <= WAITING;
336
                        elsif state_c = WRITE then
337
                                done_o  <= '1';
338
                                state_n <= FINISHED;
339
                        elsif state_c = FINISHED then
340
                                null; -- wait for a reset
341
                        else
342
                                state_n <= RESET;
343
                                report "Invalid State" severity failure;
344
                        end if;
345
 
346
                        if init = '1' then
347
                                assert state_c = FINISHED report "Lost Conversion" severity error;
348
                                state_n <= RESET;
349
                        end if;
350
                end if;
351
        end process;
352
 
353
end architecture;
354
----- ATOI --------------------------------------------------------------------
355
 
356
----- VT100 Terminal Emulator -------------------------------------------------
357
-- This module contains the VGA module and wraps it in a terminal emulator,
358
-- based on the VT100 <https://en.wikipedia.org/wiki/VT100>, it only implements
359
-- a subset of the commands supplied by the VT100. This simplifies the usage
360
-- of the VGA text mode display, other VHDL components only have to write bytes
361
-- and do not have to worry about cursor position or implementing new lines,
362
-- tabs, and other very basic features.
363
--
364
-- The interface is designed to act like a UART, simply write a byte to it
365
-- and so long as the interface is not busy, it will be written to the screen
366
-- (or interpreter as part of a command sequence).
367
 
368
library ieee,work;
369
use ieee.std_logic_1164.all;
370
use ieee.numeric_std.all;
371
use work.vga_pkg.all;
372
 
373
entity vt100 is
374
        port(
375
                clk:        in  std_ulogic;
376
                clk25MHz:   in  std_ulogic;
377
                rst:        in  std_ulogic;
378
                we:         in  std_ulogic;
379
                char:       in  std_ulogic_vector(7 downto 0);
380
 
381
                busy:       out std_ulogic;
382
                o_vga:      out vga_physical_interface);
383
end entity;
384
 
385
-- A better way of structuring this would be to process numbers in parallel
386
-- with different components, one processing potential attributes, one holding
387
-- one to two numbers - the results are then used. This would deal with runs
388
-- of attributes, which is allowed.
389
architecture rtl of vt100 is
390
        constant width:  positive := 80;
391
        constant height: positive := 40;
392
        constant number: positive := 8;
393
 
394
        type state_type is (RESET, ACCEPT, NORMAL, WRAP, LIMIT, CSI, COMMAND,
395
        NUMBER1, NUMBER2, COMMAND1, COMMAND2, WRITE, ERASING, ATTRIB1, ATTRIB2, ADVANCE);
396
        signal state_c, state_n: state_type := RESET;
397
 
398
        constant esc:          unsigned(char'range) := x"1b";
399
        constant lsqb:         unsigned(char'range) := x"5b"; -- '['
400
        constant tab:          unsigned(char'range) := x"09";
401
        constant cr:           unsigned(char'range) := x"0d";
402
        constant lf:           unsigned(char'range) := x"0a";
403
        constant backspace:    unsigned(char'range) := x"08";
404
        constant blank:        unsigned(char'range) := x"20";
405
        constant ascii_c:      unsigned(char'range) := x"63"; -- c
406
        constant attr_default: unsigned(7 downto 0) := "00111000";
407
        constant ctl_default:  unsigned(4 downto 0) := "01111";
408
 
409
        signal addr:           std_ulogic_vector(12 downto 0) := (others => '0');
410
        signal data_we:        std_ulogic                     := '0';
411
        signal x:              std_ulogic_vector(6 downto 0)  := (others => '0');
412
        signal y:              std_ulogic_vector(5 downto 0)  := (others => '0');
413
        signal cursor_we:      std_ulogic                     := '0';
414
 
415
        signal x_n, x_c:       unsigned(x'range)    := (others => '0');
416
        signal y_n, y_c:       unsigned(y'range)    := (others => '0');
417
        signal c_n, c_c:       unsigned(char'range) := (others => '0');
418
 
419
        signal attr_c, attr_n: unsigned(attr_default'range) := attr_default;
420
        signal ctl_c, ctl_n:   unsigned(ctl_default'range)  := ctl_default;
421
 
422
        signal n1_n, n1_c:     unsigned(7 downto 0) := (others => '0');
423
        signal n2_n, n2_c:     unsigned(6 downto 0) := (others => '0');
424
 
425
        signal conceal_n, conceal_c: boolean := false;
426
 
427
        signal x_minus_one:         unsigned(x'range) := (others => '0');
428
        signal x_minus_one_limited: unsigned(x'range) := (others => '0');
429
        signal x_underflow:         boolean           := false;
430
        signal x_plus_one:          unsigned(x'range) := (others => '0');
431
        signal x_plus_one_limited:  unsigned(x'range) := (others => '0');
432
        signal x_overflow:          boolean           := false;
433
 
434
        signal y_minus_one:         unsigned(y'range) := (others => '0');
435
        signal y_minus_one_limited: unsigned(y'range) := (others => '0');
436
        signal y_underflow:         boolean           := false;
437
        signal y_plus_one:          unsigned(y'range) := (others => '0');
438
        signal y_plus_one_limited:  unsigned(y'range) := (others => '0');
439
        signal y_overflow:          boolean           := false;
440
 
441
        signal count_c, count_n:    unsigned(addr'range) := (others => '0');
442
        signal limit_c, limit_n:    unsigned(addr'high - 3 downto 0) := (others => '0');
443
 
444
        signal akk_done_o:  std_ulogic := '0';
445
        signal akk_ready_o: std_ulogic := '0';
446
        signal akk_init:    std_ulogic := '0';
447
        signal n_o:         unsigned(number - 1 downto 0) := (others => '0');
448
        signal akk_char_o:  std_ulogic_vector(char'range)  := (others => '0');
449
begin
450
        accumulator_0: work.vga_pkg.atoi
451
                generic map(N => number)
452
                port map(
453
                        clk    => clk,
454
                        rst    => rst,
455
                        we     => we,
456
                        init   => akk_init,
457
                        char   => char,
458
                        char_o => akk_char_o,
459
                        done_o => akk_done_o,
460
                        ready  => akk_ready_o,
461
                        n_o    => n_o);
462
 
463
        address: block
464
                signal addr_int: unsigned(addr'range) := (others => '0');
465
                signal mul: unsigned(15 downto 0)     := (others => '0');
466
        begin
467
                mul      <= to_unsigned(to_integer(y_c) * width, mul'length);
468
                addr_int <= mul(addr_int'range) + ("000000" & x_c);
469
                addr     <= std_ulogic_vector(addr_int) when state_c /= ERASING else std_ulogic_vector(count_c);
470
        end block;
471
 
472
        x_minus_one         <= x_c - 1;
473
        x_plus_one          <= x_c + 1;
474
        x_underflow         <= true when x_minus_one > width  - 1 else false;
475
        x_overflow          <= true when x_c         > width  - 1 else false;
476
        x_minus_one_limited <= (others => '0') when x_underflow else x_minus_one;
477
        x_plus_one_limited  <= to_unsigned(width - 1, x_c'length) when x_overflow else x_plus_one;
478
 
479
        y_plus_one          <= y_c + 1;
480
        y_minus_one         <= y_c - 1;
481
        y_overflow          <= true when y_c         > height - 1 else false;
482
        y_underflow         <= true when y_minus_one > height - 1 else false;
483
        y_minus_one_limited <= (others => '0') when y_underflow else y_minus_one;
484
        y_plus_one_limited  <= to_unsigned(height - 1, y_c'length) when y_overflow else y_plus_one;
485
 
486
        busy                <= '0' when state_c = ACCEPT
487
                                       or state_c = CSI
488
                                       or state_c = NUMBER1
489
                                       or state_c = NUMBER2 else '1';
490
 
491
        vga_blk: block
492
                signal vga_din:    std_ulogic_vector(15 downto 0)     := (others => '0');
493
                signal vga_ctr_we: vga_control_registers_we_interface := vga_control_registers_we_initialize;
494
                signal vga_ctr:    vga_control_registers_interface    := vga_control_registers_initialize;
495
                signal attr:       unsigned(attr_c'range)             := attr_default;
496
                signal char:       std_ulogic_vector(c_c'range)       := (others => '0');
497
        begin
498
                char           <= x"2a" when conceal_c else std_ulogic_vector(c_c);
499
                attr           <= attr_c when state_c /= ERASING else attr_default;
500
                vga_din        <= std_ulogic_vector(attr) & char;
501
                vga_ctr.crx    <= std_ulogic_vector(x_plus_one);
502
                vga_ctr.cry    <= std_ulogic_vector(y_c);
503
                vga_ctr.ctl    <= std_ulogic_vector(ctl_c);
504
                vga_ctr_we.crx <= cursor_we;
505
                vga_ctr_we.cry <= cursor_we;
506
                vga_ctr_we.ctl <= cursor_we;
507
 
508
                vga_0: work.vga_pkg.vga_top
509
                port map(
510
                        clk               =>  clk,
511
                        clk25MHz          =>  clk25MHz,
512
                        rst               =>  rst,
513
                        vga_we_ram        =>  data_we,
514
                        vga_din           =>  vga_din,
515
                        vga_addr          =>  addr,
516
                        i_vga_control_we  =>  vga_ctr_we,
517
                        i_vga_control     =>  vga_ctr,
518
                        o_vga             =>  o_vga);
519
        end block;
520
 
521
        -- Subset of commands implemented:
522
        -- ED  - Erase Display, CSI n 'J'
523
        -- RIS - Erase Display, ESC 'c'
524
        -- SGR - Select Graphic Rendition - for colors, CSI n 'm'
525
        -- HVP - Horizontal and Vertical Position - CSI n ; m 'f'
526
        -- The cursor commands are also supported: CUU, CUD, CUF,
527
        -- CUB, CNL, CPL and CHA
528
        fsm: process(clk, rst)
529
                variable limit_value: unsigned(addr'range) := (others => '0');
530
                variable repeat:      boolean    := false;
531
                variable exit_repeat: state_type := RESET;
532
        begin
533
                if rst = '1' then
534
                        state_c <= RESET;
535
                elsif rising_edge(clk) then
536
                        x_c       <= x_n;
537
                        y_c       <= y_n;
538
                        c_c       <= c_n;
539
                        count_c   <= count_n;
540
                        limit_c   <= limit_n;
541
                        state_c   <= state_n;
542
                        n1_c      <= n1_n;
543
                        n2_c      <= n2_n;
544
                        data_we   <= '0';
545
                        cursor_we <= '0';
546
                        akk_init  <= '0';
547
                        attr_c    <= attr_n;
548
                        ctl_c     <= ctl_n;
549
                        conceal_c <= conceal_n;
550
 
551
                        if state_c = RESET then
552
                                n1_n      <= (others => '0');
553
                                n2_n      <= (others => '0');
554
                                x_n       <= (others => '0');
555
                                y_n       <= (others => '0');
556
                                c_n       <= (others => '0');
557
                                count_n   <= (others => '0');
558
                                limit_n   <= (others => '0');
559
                                state_n   <= ACCEPT;
560
                                attr_n    <= attr_default;
561
                                ctl_n     <= ctl_default;
562
                                conceal_n <= false;
563
                        elsif state_c = ACCEPT then
564
                                if we = '1' then
565
                                        c_n   <= unsigned(char);
566
                                        state_n <= NORMAL;
567
                                end if;
568
                        elsif state_c = NORMAL then
569
                                case c_c is
570
                                when tab =>
571
                                        x_n     <= (x_c and "1111000") + 8;
572
                                        state_n <= ERASING;
573
                                        c_n     <= blank;
574
                                        limit_value := unsigned(addr and "1111111111000") + 8;
575
                                        limit_n <= limit_value(limit_n'high + 3 downto limit_n'low + 3);
576
                                        count_n <= unsigned(addr);
577
                                when cr =>
578
                                        y_n     <= y_plus_one;
579
                                        state_n <= WRAP;
580
                                when lf =>
581
                                        x_n     <= (others => '0');
582
                                        state_n <= WRITE;
583
                                when backspace =>
584
                                        x_n     <= x_minus_one_limited;
585
                                        state_n <= WRITE;
586
                                when esc =>
587
                                        state_n <= CSI;
588
                                when others =>
589
                                        data_we <= '1';
590
                                        state_n <= ADVANCE;
591
                                end case;
592
                        elsif state_c = ADVANCE then
593
                                x_n     <= x_plus_one;
594
                                state_n <= WRAP;
595
                        elsif state_c = CSI then
596
                                if we = '1' then
597
                                        c_n <= unsigned(char);
598
                                        state_n <= COMMAND;
599
                                end if;
600
                        elsif state_c = COMMAND then
601
                                case c_c is
602
                                when ascii_c => -- @todo Erase screen as well
603
                                        state_n <= RESET;
604
                                when lsqb =>
605
                                        state_n  <= NUMBER1;
606
                                        akk_init <= '1';
607
                                when others => -- Error
608
                                        state_n <= ACCEPT;
609
                                end case;
610
                        elsif state_c = NUMBER1 then
611
                                if akk_done_o = '1' then
612
                                        state_n <= COMMAND1;
613
                                        n1_n    <= n_o(n1_n'range);
614
                                end if;
615
                        elsif state_c = COMMAND1 then
616
                                repeat := false;
617
                                case akk_char_o is
618
                                when x"41" => -- CSI n 'A' : CUU Cursor up
619
                                        y_n         <= y_minus_one_limited;
620
                                        exit_repeat := WRITE;
621
                                        repeat      := true;
622
                                when x"42" => -- CSI n 'B' : CUD Cursor Down
623
                                        y_n         <= y_plus_one_limited;
624
                                        exit_repeat := LIMIT;
625
                                        repeat      := true;
626
                                when x"43" => -- CSI n 'C' : CUF Cursor Forward
627
                                        x_n         <= x_plus_one_limited;
628
                                        exit_repeat := LIMIT;
629
                                        repeat      := true;
630
                                when x"44" => -- CSI n 'D' : CUB Cursor Back
631
                                        x_n         <= x_minus_one_limited;
632
                                        exit_repeat := WRITE;
633
                                        repeat      := true;
634
                                when x"45" => -- CSI n 'E'
635
                                        y_n         <= y_minus_one_limited;
636
                                        x_n         <= (others => '0');
637
                                        exit_repeat := WRITE;
638
                                        repeat      := true;
639
                                when x"46" => -- CSI n 'F'
640
                                        y_n         <= y_plus_one_limited;
641
                                        x_n         <= (others => '0');
642
                                        exit_repeat := LIMIT;
643
                                        repeat      := true;
644
                                when x"47" => -- CSI n 'G' : CHA Cursor Horizontal Absolute
645
                                        x_n      <= n1_c(x_n'range);
646
                                        state_n  <= LIMIT;
647
                                when x"4a" => -- CSI n 'J'
648
                                        x_n       <= (others => '0');
649
                                        y_n       <= (others => '0');
650
                                        cursor_we <= '1';
651
                                        state_n   <= ERASING;
652
                                        c_n       <= blank;
653
                                        count_n   <= (others => '0');
654
                                        limit_n   <= "1000000000";
655
                                when x"3b" => -- ESC n ';' ...
656
                                        state_n <= NUMBER2;
657
                                        akk_init <= '1';
658
                                when x"6d" => -- CSI n 'm' : SGR
659
                                        state_n <= ATTRIB1;
660
                                when x"53" => -- CSI n 'S' : scroll up
661
                                        ctl_n(4) <= '0';
662
                                        state_n  <= WRITE;
663
                                when x"54" => -- CSI n 'T' : scroll down
664
                                        ctl_n(4) <= '1';
665
                                        state_n  <= WRITE;
666
                                -- when x"3f" => -- ESC ? 25 (l,h)
667
                                --      state_n  <= NUMBER2;
668
                                --      akk_init <= '1';
669
 
670
                                -- @warning This is an extension! It is for setting the
671
                                -- control lines of the VGA module directly.
672
                                when x"78" => -- ESC n 'x' : Set VGA control registers directly
673
                                        ctl_n    <= n1_c(ctl_n'range);
674
                                        state_n  <= WRITE;
675
                                when others => -- Error
676
                                        state_n <= ACCEPT;
677
                                end case;
678
 
679
                                if repeat then
680
                                        if n1_c = 0 then
681
                                                state_n <= exit_repeat;
682
                                        else
683
                                                n1_n <= n1_c - 1;
684
                                        end if;
685
                                end if;
686
                        elsif state_c = NUMBER2 then
687
                                if akk_done_o = '1' then
688
                                        state_n <= COMMAND2;
689
                                        n2_n    <= n_o(n2_n'range);
690
                                end if;
691
                        elsif state_c = COMMAND2 then
692
                                case akk_char_o is
693
                                when x"66" => -- f
694
                                        y_n       <= n1_c(y_n'range) - 1;
695
                                        x_n       <= n2_c(x_n'range) - 1;
696
                                        cursor_we <= '1';
697
                                        state_n   <= LIMIT;
698
                                when x"48" => -- H
699
                                        y_n       <= n1_c(y_n'range) - 1;
700
                                        x_n       <= n2_c(x_n'range) - 1;
701
                                        cursor_we <= '1';
702
                                        state_n   <= LIMIT;
703
                                when x"6d" => -- ESC n ';' m 'm'
704
                                        state_n <= ATTRIB1;
705
                                when others =>
706
                                        state_n <= ACCEPT;
707
                                end case;
708
                        elsif state_c = WRAP then
709
                                if x_overflow then
710
                                        x_n <= (others => '0');
711
                                        y_n <= y_plus_one;
712
                                elsif y_overflow then
713
                                        x_n     <= (others => '0');
714
                                        y_n     <= (others => '0');
715
                                        state_n <= ERASING;
716
                                        c_n     <= blank;
717
                                        count_n <= (others => '0');
718
                                        limit_n <= "1000000000";
719
                                else
720
                                        state_n <= WRITE;
721
                                end if;
722
                        elsif state_c = LIMIT then
723
                                if x_overflow then
724
                                        x_n <= to_unsigned(width - 1, x_n'high + 1);
725
                                end if;
726
                                if y_overflow then
727
                                        y_n <= to_unsigned(height - 1, y_n'high + 1);
728
                                end if;
729
                                state_n <= WRITE;
730
                        elsif state_c = WRITE then
731
                                state_n   <= ACCEPT;
732
                                cursor_we <= '1';
733
                        elsif state_c = ERASING then
734
                                if count_c(limit_c'high + 3 downto limit_c'low + 3) /= limit_c then
735
                                        count_n <= count_c + 1;
736
                                        data_we <= '1';
737
                                else
738
                                        state_n <= WRAP;
739
                                end if;
740
                        elsif state_c = ATTRIB1 then
741
                                case n1_c is
742
                                when x"00"  =>
743
                                        attr_n    <= attr_default;
744
                                        conceal_n <= false;
745
                                when x"01"  => attr_n(6) <= '1'; -- bold
746
                                when x"07"  => attr_n(7) <= '1'; -- reverse video
747
                                when x"08"  => conceal_n <= true;
748
 
749
                                -- when x"6c" => if n2_c = x"19" then ctl_n(2) <= '0'; end if; -- l, hide cursor
750
                                -- when x"68" => if n2_c = x"19" then ctl_n(2) <= '1'; end if; -- h, show cursor
751
 
752
                                -- @todo This should make the _text_ blink, not the cursor!
753
                                when x"05"  => ctl_n(1) <= '1'; -- blink slow
754
                                when x"19"  => ctl_n(1) <= '0'; -- blink off
755
 
756
                                when x"1E"  => attr_n(5 downto 3) <= "000"; -- 30
757
                                when x"1F"  => attr_n(5 downto 3) <= "001";
758
                                when x"20"  => attr_n(5 downto 3) <= "010";
759
                                when x"21"  => attr_n(5 downto 3) <= "011";
760
                                when x"22"  => attr_n(5 downto 3) <= "100";
761
                                when x"23"  => attr_n(5 downto 3) <= "101";
762
                                when x"24"  => attr_n(5 downto 3) <= "110";
763
                                when x"25"  => attr_n(5 downto 3) <= "111";
764
 
765
                                when x"28"  => attr_n(2 downto 0) <= "000"; -- 40
766
                                when x"29"  => attr_n(2 downto 0) <= "001";
767
                                when x"2A"  => attr_n(2 downto 0) <= "010";
768
                                when x"2B"  => attr_n(2 downto 0) <= "011";
769
                                when x"2C"  => attr_n(2 downto 0) <= "100";
770
                                when x"2D"  => attr_n(2 downto 0) <= "101";
771
                                when x"2E"  => attr_n(2 downto 0) <= "110";
772
                                when x"2F"  => attr_n(2 downto 0) <= "111";
773
                                when others =>
774
                                end case;
775
                                state_n <= ATTRIB2;
776
                        elsif state_c = ATTRIB2 then
777
                                -- @todo Implement two attributes in a row
778
                                state_n <= ACCEPT;
779
                        else
780
                                state_n <= RESET;
781
                                report "Invalid State" severity failure;
782
                        end if;
783
                end if;
784
        end process;
785
end architecture;
786
----- VT100 Terminal Emulator -------------------------------------------------
787
 
788
----- VGA Top Level Component -------------------------------------------------
789
library ieee,work;
790
use ieee.std_logic_1164.all;
791
use ieee.numeric_std.all;
792
use work.vga_pkg.all;
793
use work.util.file_format;
794
use work.util.FILE_HEX;
795
use work.util.FILE_BINARY;
796
 
797
entity vga_top is
798
        port(
799
                clk:              in  std_ulogic;
800
                clk25MHz:         in  std_ulogic;
801
                rst:              in  std_ulogic;
802
 
803
                -- VGA Text buffer interface
804
                vga_we_ram:       in  std_ulogic; -- Write enable RAM
805
                vga_din:          in  std_ulogic_vector(15 downto 0);
806
                vga_addr:         in  std_ulogic_vector(12 downto 0);
807
                vga_dout:         out std_ulogic_vector(15 downto 0) := (others => '0');
808
 
809
                -- VGA control registers
810
                i_vga_control_we: in vga_control_registers_we_interface;
811
                i_vga_control:    in vga_control_registers_interface;
812
 
813
                o_vga:            out vga_physical_interface);
814
end;
815
 
816
architecture behav of vga_top is
817
 
818
        -- Setup for text buffer memory
819
        constant text_addr_length: positive    := 13;
820
        constant text_data_length: positive    := 16;
821
        constant text_file_name:   string      := "text.hex";
822
        constant text_file_type:   file_format := FILE_HEX;
823
 
824
        -- Setup for font buffer memory
825
        constant font_addr_length: positive    := 12;
826
        constant font_data_length: positive    := 8;
827
        constant font_file_name:   string      := "font.bin";
828
        constant font_file_type:   file_format := FILE_BINARY;
829
 
830
        -- Internal signals for mapping output <--> VGA module
831
        signal  foreground_draw_internal:      std_ulogic := '0';
832
 
833
        -- Text RAM signals, RAM <--> VGA module
834
        signal  text_dout:       std_ulogic_vector(15 downto 0) := (others => '0');
835
        signal  text_din:        std_ulogic_vector(15 downto 0) := (others => '0');
836
        signal  text_addr:       std_ulogic_vector(11 downto 0) := (others => '0');
837
        signal  text_addr_full:  std_ulogic_vector(12 downto 0) := (others => '0');
838
 
839
        -- Font ROM signals, ROM<-->VGA module
840
        signal  font_addr:       std_ulogic_vector(11 downto 0) := (others => '0');
841
        signal  font_dout:       std_ulogic_vector( 7 downto 0) := (others => '0');
842
 
843
        signal  control_c, control_n: vga_control_registers_interface := vga_control_registers_initialize;
844
 
845
        signal  foreground_draw: std_ulogic := '0';
846
        signal  background_draw: std_ulogic := '0';
847
begin
848
 
849
        color_block: block
850
                signal red_on:   std_ulogic := '0';
851
                signal green_on: std_ulogic := '0';
852
                signal blue_on:  std_ulogic := '0';
853
                signal bold:     std_ulogic := '0';
854
                signal reverse:  std_ulogic := '0';
855
                signal set:      std_ulogic_vector(2 downto 0) := "110";
856
                signal final:    std_ulogic_vector(2 downto 0) := "111";
857
        begin
858
                bold        <= text_dout(14);
859
                reverse     <= text_dout(15);
860
                set         <= "100" when bold = '0' else "111";
861
                final       <= set   when reverse = '0' else not set;
862
 
863
                red_on      <= text_dout(11) when foreground_draw = '1' else
864
                               text_dout(8)  when background_draw = '1' else '0';
865
                green_on    <= text_dout(12) when foreground_draw = '1' else
866
                               text_dout(9)  when background_draw = '1' else '0';
867
                blue_on     <= text_dout(13) when foreground_draw = '1' else
868
                               text_dout(10) when background_draw = '1' else '0';
869
 
870
                o_vga.red   <= final             when red_on    = '1' else "000";
871
                o_vga.green <= final             when green_on  = '1' else "000";
872
                o_vga.blue  <= final(2 downto 1) when blue_on   = '1' else "00";
873
        end block;
874
 
875
        -- Internal control registers
876
        -- Next state on clk edge rising
877
        vga_ns: process(clk, rst)
878
        begin
879
                if rst = '1' then
880
                        control_c   <= vga_control_registers_initialize;
881
                elsif rising_edge(clk) then
882
                        control_c   <= control_n;
883
                end if;
884
        end process;
885
 
886
        -- Internal control register
887
        -- We write into the registers here.
888
        vga_creg_we: process(
889
                control_c,
890
                i_vga_control,
891
                i_vga_control_we)
892
        begin
893
                control_n <= control_c;
894
 
895
                if i_vga_control_we.crx = '1' then control_n.crx <= i_vga_control.crx; end if;
896
                if i_vga_control_we.cry = '1' then control_n.cry <= i_vga_control.cry; end if;
897
                if i_vga_control_we.ctl = '1' then control_n.ctl <= i_vga_control.ctl; end if;
898
        end process;
899
 
900
        -- The actual VGA module
901
        u_vga: work.vga_pkg.vga_core port map (
902
                rst       => rst,
903
                clk25MHz  => clk25MHz,
904
 
905
                text_a    => text_addr,
906
                text_d    => text_dout(7 downto 0),
907
 
908
                font_a    => font_addr,
909
                font_d    => font_dout,
910
 
911
                ocrx      => control_c.crx,
912
                ocry      => control_c.cry,
913
                octl      => control_c.ctl(3 downto 0),
914
 
915
                foreground_draw => foreground_draw,
916
                background_draw => background_draw,
917
                hsync     => o_vga.hsync,
918
                vsync     => o_vga.vsync);
919
 
920
        text_addr_full <= control_c.ctl(4) & text_addr;
921
 
922
        --| @brief This RAM module holds the text we want to display on to the
923
        --| monitor. The text buffer holds at least 80*40 characters.
924
        u_text: entity work.dual_port_block_ram
925
        generic map(
926
            addr_length => text_addr_length,
927
            data_length => text_data_length,
928
            file_name   => text_file_name,
929
            file_type   => text_file_type)
930
        port map (
931
                a_clk   => clk,
932
                -- External interface
933
                a_dwe   => vga_we_ram,
934
                a_dre   => '1',
935
                a_addr  => vga_addr,
936
                a_din   => vga_din,
937
                a_dout  => vga_dout,
938
                -- Internal interface
939
                b_clk   => clk25MHz,
940
                b_dwe   => '0',
941
                b_dre   => '1',
942
                b_addr  => text_addr_full,
943
                b_din   => (others => '0'),
944
                b_dout  => text_dout);
945
 
946
        --| VGA Font memory
947
        u_font: entity work.single_port_block_ram
948
        generic map(
949
                addr_length => font_addr_length,
950
                data_length => font_data_length,
951
                file_name   => font_file_name,
952
                file_type   => font_file_type)
953
        port map (
954
                clk  => clk25MHz,
955
                dwe  => '0',
956
                dre  => '1',
957
                addr => font_addr,
958
                din  => (others => '0'),
959
                dout => font_dout);
960
 
961
end architecture;
962
 
963
----- VGA Top Level Component -------------------------------------------------
964
 
965
----- VGA Core ----------------------------------------------------------------
966
 
967
library ieee;
968
use ieee.std_logic_1164.all;
969
use ieee.numeric_std.all;
970
use work.vga_pkg.ctrm;
971
use work.vga_pkg.losr;
972
 
973
entity vga_core is
974
        port (
975
                rst:      in  std_ulogic;
976
                clk25MHz: in  std_ulogic;
977
                text_a:   out std_ulogic_vector(11 downto 0); -- text buffer
978
                text_d:   in  std_ulogic_vector( 7 downto 0);
979
                font_a:   out std_ulogic_vector(11 downto 0); -- font buffer
980
                font_d:   in  std_ulogic_vector( 7 downto 0);
981
                 --
982
                ocrx:     in  std_ulogic_vector(6 downto 0);
983
                ocry:     in  std_ulogic_vector(5 downto 0);
984
                octl:     in  std_ulogic_vector(3 downto 0);
985
                --
986
                foreground_draw: out std_ulogic; -- If '1', we should draw the character
987
                background_draw: out std_ulogic;
988
                hsync:     out std_ulogic;
989
                vsync:     out std_ulogic);
990
end entity;
991
 
992
architecture rtl of vga_core is
993
 
994
        signal foreground_draw_int, background_draw_int: std_ulogic := '0';
995
        signal hsync_int: std_ulogic := '1';
996
        signal vsync_int: std_ulogic := '1';
997
 
998
        signal blank: std_ulogic := '0';
999
        signal hctr:  integer range 793 downto 0 := 0;
1000
        signal vctr:  integer range 524 downto 0 := 0;
1001
 
1002
        -- character/pixel position on the screen
1003
        signal scry:  integer range 39 downto 0 := 0;  -- chr row   < 40 (6 bits)
1004
        signal scrx:  integer range 79 downto 0 := 0;  -- chr col   < 80 (7 bits)
1005
        signal chry:  integer range 11 downto 0 := 0;  -- chr high  < 12 (4 bits)
1006
        signal chrx:  integer range 7  downto 0 := 0;  -- chr width < 08 (3 bits)
1007
 
1008
        signal losr_ce: std_ulogic := '0';
1009
        signal losr_ld: std_ulogic := '0';
1010
        signal losr_do: std_ulogic := '0';
1011
        signal y:       std_ulogic := '0';  -- character luminance pixel value (0 or 1)
1012
 
1013
        -- control io register
1014
        signal ctl:       std_ulogic_vector(7 downto 0):= (others =>'0');
1015
        signal vga_en:    std_ulogic := '0';
1016
        signal cur_en:    std_ulogic := '0';
1017
        signal cur_mode:  std_ulogic := '0';
1018
        signal cur_blink: std_ulogic := '0';
1019
 
1020
begin
1021
 
1022
        -- hsync generator, initialized with '1'
1023
        process (rst, clk25MHz)
1024
        begin
1025
                if rst = '1' then
1026
                        hsync_int <= '1';
1027
                elsif rising_edge(clk25MHz) then
1028
                        if (hctr > 663) and (hctr < 757) then
1029
                                hsync_int <= '0';
1030
                        else
1031
                                hsync_int <= '1';
1032
                        end if;
1033
                end if;
1034
        end process;
1035
 
1036
        -- vsync generator, initialized with '1'
1037
        process (rst, clk25MHz)
1038
        begin
1039
                if rst = '1' then
1040
                        vsync_int <= '1';
1041
                elsif rising_edge(clk25MHz) then
1042
                        if (vctr > 499) and (vctr < 502) then
1043
                                vsync_int <= '0';
1044
                        else
1045
                                vsync_int <= '1';
1046
                        end if;
1047
                end if;
1048
        end process;
1049
 
1050
        -- Blank signal, 0 = no draw, 1 = visible/draw zone
1051
 
1052
        -- Proboscide99 31/08/08
1053
        blank <= '0' when (hctr < 8) or (hctr > 647) or (vctr > 479) else '1';
1054
 
1055
        -- flip-flips for sync of R, G y B signal, initialized with '0'
1056
        process (rst, clk25MHz)
1057
        begin
1058
                if rst = '1' then
1059
                        foreground_draw <= '0';
1060
                elsif rising_edge(clk25MHz) then
1061
                        foreground_draw <= foreground_draw_int;
1062
                        background_draw <= background_draw_int;
1063
                end if;
1064
        end process;
1065
 
1066
        -- Control register. Individual control signal
1067
 
1068
        vga_en    <= octl(3);
1069
        cur_en    <= octl(2);
1070
        cur_blink <= octl(1);
1071
        cur_mode  <= octl(0);
1072
 
1073
        -- counters, hctr, vctr, srcx, srcy, chrx, chry
1074
        counters: block
1075
 
1076
                signal hctr_ce: std_ulogic := '0';
1077
                signal hctr_rs: std_ulogic := '0';
1078
                signal vctr_ce: std_ulogic := '0';
1079
                signal vctr_rs: std_ulogic := '0';
1080
 
1081
                signal chrx_ce: std_ulogic := '0';
1082
                signal chrx_rs: std_ulogic := '0';
1083
                signal chry_ce: std_ulogic := '0';
1084
                signal chry_rs: std_ulogic := '0';
1085
                signal scrx_ce: std_ulogic := '0';
1086
                signal scrx_rs: std_ulogic := '0';
1087
                signal scry_ce: std_ulogic := '0';
1088
                signal scry_rs: std_ulogic := '0';
1089
 
1090
                signal hctr_639: std_ulogic := '0';
1091
                signal vctr_479: std_ulogic := '0';
1092
                signal chrx_007: std_ulogic := '0';
1093
                signal chry_011: std_ulogic := '0';
1094
 
1095
                -- RAM read, ROM read
1096
                signal ram_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3199 downto 0
1097
                signal mul:     unsigned(15 downto 0) := (others => '0');
1098
                signal rom_tmp: unsigned(11 downto 0) := (others => '0'); -- range 3071 downto 0;
1099
 
1100
                -- @todo Rename these signals to something more sensible
1101
        begin
1102
                u_hctr: work.vga_pkg.ctrm generic map (M => 794) port map (rst, clk25MHz, hctr_ce, hctr_rs, hctr);
1103
                u_vctr: work.vga_pkg.ctrm generic map (M => 525) port map (rst, clk25MHz, vctr_ce, vctr_rs, vctr);
1104
 
1105
                hctr_ce <= '1';
1106
                hctr_rs <= '1' when hctr = 793 else '0';
1107
                vctr_ce <= '1' when hctr = 663 else '0';
1108
                vctr_rs <= '1' when vctr = 524 else '0';
1109
 
1110
                u_chrx: work.vga_pkg.ctrm generic map (M => 8)  port map (rst, clk25MHz, chrx_ce, chrx_rs, chrx);
1111
                u_chry: work.vga_pkg.ctrm generic map (M => 12) port map (rst, clk25MHz, chry_ce, chry_rs, chry);
1112
                u_scrx: work.vga_pkg.ctrm generic map (M => 80) port map (rst, clk25MHz, scrx_ce, scrx_rs, scrx);
1113
                u_scry: work.vga_pkg.ctrm generic map (M => 40) port map (rst, clk25MHz, scry_ce, scry_rs, scry);
1114
 
1115
                hctr_639 <= '1' when hctr = 639 else '0';
1116
                vctr_479 <= '1' when vctr = 479 else '0';
1117
                chrx_007 <= '1' when chrx = 7 else '0';
1118
                chry_011 <= '1' when chry = 11 else '0';
1119
 
1120
                chrx_rs <= chrx_007 or hctr_639;
1121
                chry_rs <= chry_011 or vctr_479;
1122
                scrx_rs <= hctr_639;
1123
                scry_rs <= vctr_479;
1124
 
1125
                chrx_ce <= '1' and blank;
1126
                scrx_ce <= chrx_007;
1127
                chry_ce <= hctr_639 and blank;
1128
                scry_ce <= chry_011 and hctr_639;
1129
 
1130
                ram_tmp <=  (to_unsigned(scry,ram_tmp'length) sll 4) +
1131
                                (to_unsigned(scry,ram_tmp'length) sll 6) +
1132
                                to_unsigned(scrx,ram_tmp'length);
1133
 
1134
                text_a  <= std_ulogic_vector(ram_tmp);
1135
                mul     <= unsigned(text_d) * 12;
1136
                rom_tmp <= mul(rom_tmp'range) + chry;
1137
                font_a  <= std_ulogic_vector(rom_tmp);
1138
        end block;
1139
 
1140
        u_losr: work.vga_pkg.losr generic map (N => 8)
1141
        port map (rst, clk25MHz, losr_ld, losr_ce, losr_do, FONT_D);
1142
 
1143
        losr_ce <= blank;
1144
        losr_ld <= '1' when (chrx = 7) else '0';
1145
 
1146
        -- video out, vga_en control signal enable/disable vga signal
1147
        foreground_draw_int <=      y  and blank;
1148
        background_draw_int <= (not y) and blank;
1149
 
1150
        hsync <= hsync_int and vga_en;
1151
        vsync <= vsync_int and vga_en;
1152
 
1153
        -- Hardware Cursor
1154
        hw_cursor: block
1155
                signal small:   std_ulogic := '0';
1156
                signal curen2:  std_ulogic := '0';
1157
                signal slowclk: std_ulogic := '0';
1158
                signal curpos:  std_ulogic := '0';
1159
                signal yint:    std_ulogic := '0';
1160
                -- signal crx:     integer range 79 downto 0;
1161
                -- signal cry:     integer range 39 downto 0;
1162
                signal crx:     integer range 127 downto 0;
1163
                signal cry:     integer range 64 downto 0;
1164
                signal counter: unsigned(22 downto 0) := (others => '0');
1165
        begin
1166
 
1167
                -- slowclk for blink hardware cursor
1168
                counter <= counter + 1 when rising_edge(clk25MHz) else counter;
1169
                slowclk <= counter(22); --2.98Hz
1170
 
1171
                crx <= to_integer(unsigned(ocrx(6 downto 0)));
1172
                cry <= to_integer(unsigned(ocry(5 downto 0)));
1173
 
1174
                --
1175
                curpos <= '1' when scry = cry and scrx = crx else '0';
1176
                small  <= '1' when (chry > 8)                else '0';
1177
                curen2 <= (slowclk or (not cur_blink)) and cur_en;
1178
                yint   <= '1' when cur_mode = '0'            else small;
1179
                y      <= (yint and curpos and curen2) xor losr_do;
1180
        end block;
1181
end;
1182
----- VGA Core ----------------------------------------------------------------
1183
 
1184
-------------------------------------------------------------------------------
1185
--| @file ctrm.vhd
1186
--| @brief Counter, asynchronous *and* synchronous reset, up only.
1187
--|        (ctrm.vhd, original filename)
1188
--| @author         Javier Valcarce García
1189
--| @copyright      Copyright 2007 Javier Valcarce García
1190
--| @license        LGPL version 3
1191
--| @email          javier.valcarce@gmail.com
1192
-------------------------------------------------------------------------------
1193
library ieee;
1194
use ieee.std_logic_1164.all;
1195
use ieee.numeric_std.all;
1196
 
1197
entity ctrm is
1198
        generic (M: positive := 8);
1199
        port (
1200
                rst: in  std_ulogic; -- asynchronous rst
1201
                clk: in  std_ulogic;
1202
                ce:  in  std_ulogic; -- enable counting
1203
                rs:  in  std_ulogic; -- synchronous rst
1204
                do:  out integer range (M-1) downto 0 := 0);
1205
end ctrm;
1206
 
1207
architecture rtl of ctrm is
1208
        signal c: integer range (M-1) downto 0:= 0;
1209
begin
1210
        do <= c;
1211
        process(rst, clk)
1212
        begin
1213
                if rst = '1' then
1214
                        c <= 0;
1215
                elsif rising_edge(clk) then
1216
                        if ce = '1' then
1217
                                if rs = '1' then
1218
                                        c <= 0;
1219
                                else
1220
                                        c <= c + 1;
1221
                                end if;
1222
                        end if;
1223
                end if;
1224
        end process;
1225
end;
1226
 
1227
-------------------------------------------------------------------------------
1228
--| @file util.vhd
1229
--| @brief Shift register N-bit, asynchronous reset, synchronous load,
1230
--|        and enable
1231
--| @author         Javier Valcarce García
1232
--| @copyright      Copyright 2007 Javier Valcarce García
1233
--| @license        LGPL version 3
1234
--| @email          javier.valcarce@gmail.com
1235
-------------------------------------------------------------------------------
1236
library ieee;
1237
use ieee.std_logic_1164.all;
1238
use ieee.numeric_std.all;
1239
 
1240
entity losr is
1241
        generic (N: positive := 4);
1242
        port
1243
        (
1244
                rst:  in  std_ulogic;
1245
                clk:  in  std_ulogic;
1246
                load: in  std_ulogic;
1247
                ce:   in  std_ulogic;
1248
                do:   out std_ulogic := '0';
1249
                di:   in  std_ulogic_vector(N - 1 downto 0));
1250
end losr;
1251
 
1252
architecture rtl of losr is
1253
begin
1254
        process(rst, clk)
1255
                variable data : std_ulogic_vector(N - 1 downto 0) := (others => '0');
1256
        begin
1257
                if rst = '1' then
1258
                        data := (others => '0');
1259
                elsif rising_edge(clk) then
1260
                        if load = '1' then
1261
                                data := di;
1262
                        elsif ce = '1' then
1263
                                data := data(N-2 downto 0) & "0";
1264
                        end if;
1265
                end if;
1266
                do <= data(N-1);
1267
        end process;
1268
end;
1269
 

powered by: WebSVN 2.1.0

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