-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchar_address_unit.vhd
133 lines (110 loc) · 3.7 KB
/
char_address_unit.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vga_util.all;
entity char_address_unit is
generic (
MEM_BYTES: positive := 2 ** 12;
MEM_BANKS: positive := 2
);
port (
clk, en, reset: in std_logic;
hstate: in vga_hstate;
vstate: in vga_vstate;
incr_frame: in boolean;
incr_char_y: in boolean;
incr_pixel_y: in boolean;
incr_char_x: in boolean;
addr_offset: in natural range 0 to MEM_BYTES - 1;
bank_offset: in natural range 0 to MEM_BANKS - 1;
offset_reg_ce: in std_logic;
mem_addr: out natural range 0 to MEM_BYTES - 1 := 0;
mem_bank: out natural range 0 to MEM_BANKS - 1 := 0
);
end entity;
architecture rtl of char_address_unit is
signal int_mem_addr: natural range 0 to MEM_BYTES - 1 := 0;
signal int_mem_bank: natural range 0 to MEM_BANKS - 1 := 0;
signal start_line_mem_addr: natural range 0 to MEM_BYTES - 1 := 0;
signal start_line_mem_bank: natural range 0 to MEM_BANKS - 1 := 0;
signal int_mem_addr_offset: natural range 0 to MEM_BYTES - 1 := 0;
signal int_mem_bank_offset: natural range 0 to MEM_BANKS - 1 := 0;
begin
mem_addr <= int_mem_addr;
mem_bank <= int_mem_bank;
resolve_mem_loc: process (clk, en, reset, hstate, vstate,
int_mem_addr, int_mem_bank,
start_line_mem_addr, start_line_mem_bank,
int_mem_addr_offset, int_mem_bank_offset,
addr_offset, bank_offset, offset_reg_ce,
incr_frame, incr_char_y, incr_pixel_y, incr_char_x
) is
begin
if rising_edge(clk) then
if reset = '1' then
int_mem_addr <= 0;
int_mem_bank <= 0;
start_line_mem_addr <= 0;
start_line_mem_bank <= 0;
int_mem_addr_offset <= 0;
int_mem_bank_offset <= 0;
elsif en = '1' then
if not (hstate = HActiveVideo and vstate = VActiveVideo) then
if offset_reg_ce = '1' then
int_mem_addr <= addr_offset;
int_mem_bank <= bank_offset;
start_line_mem_addr <= addr_offset;
start_line_mem_bank <= bank_offset;
int_mem_addr_offset <= addr_offset;
int_mem_bank_offset <= bank_offset;
end if;
elsif hstate = HActiveVideo and vstate = VActiveVideo then
if incr_frame then
-- Reset the pointer position
int_mem_addr <= int_mem_addr_offset;
int_mem_bank <= int_mem_bank_offset;
-- Reset the start line too
start_line_mem_addr <= int_mem_addr_offset;
start_line_mem_bank <= int_mem_bank_offset;
elsif incr_char_y then
-- Increment as usual, but also set the
-- start line variables so we know where to jump
-- back to when we get to the end of this line.
if int_mem_addr = MEM_BYTES - 1 then
int_mem_addr <= 0;
start_line_mem_addr <= 0;
if int_mem_bank = MEM_BANKS - 1 then
int_mem_bank <= 0;
start_line_mem_bank <= 0;
else
int_mem_bank <= int_mem_bank + 1;
start_line_mem_bank <= int_mem_bank + 1;
end if;
else
int_mem_addr <= int_mem_addr + 1;
start_line_mem_addr <= int_mem_addr + 1;
-- line below is important
start_line_mem_bank <= int_mem_bank;
end if;
elsif incr_pixel_y then
-- Jump back to the start of the line
int_mem_addr <= start_line_mem_addr;
int_mem_bank <= start_line_mem_bank;
elsif incr_char_x then
-- Increment normally
if int_mem_addr = MEM_BYTES - 1 then
int_mem_addr <= 0;
if int_mem_bank = MEM_BANKS - 1 then
int_mem_bank <= 0;
else
int_mem_bank <= int_mem_bank + 1;
end if;
else
int_mem_addr <= int_mem_addr + 1;
end if;
end if;
end if; -- active_video = true
end if; -- en = '1'
end if; -- rising_edge(clk)
end process;
end architecture;