-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvt100.vhd
320 lines (269 loc) · 8.08 KB
/
vt100.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
library ieee;
use ieee.std_logic_1164.all;
-- use IEEE.STD_LOGIC_ARITH.all;
-- use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.NUMERIC_STD.all;
entity vt100 is
port(
Reset_n : in std_logic;
clk : in std_logic;
junkBuzzer : out std_logic;
videoR : out std_logic_vector(3 downto 0);
videoG : out std_logic_vector(3 downto 0);
videoB : out std_logic_vector(3 downto 0);
hSync : out std_logic;
vSync : out std_logic;
blinkenlight : out std_logic_vector(5 downto 0);
NMI_n : in std_logic;
RXD0 : in std_logic;
CTS0 : in std_logic;
DSR0 : in std_logic;
RI0 : in std_logic;
DCD0 : in std_logic;
TXD0 : out std_logic;
RTS0 : out std_logic;
DTR0 : out std_logic;
ps2Clk : inout std_logic;
ps2Data : inout std_logic
);
end vt100;
architecture struct of vt100 is
signal pixelClk : std_logic;
signal row : unsigned(9 downto 0);
signal col : unsigned(9 downto 0);
signal display_enable : std_logic;
signal frame_start : std_logic;
signal row_start : std_logic;
signal dispram_addr_b : std_logic_vector(11 downto 0) := "000000000000";
signal dispram_output_b : std_logic_vector(7 downto 0);
signal serialClkCount : unsigned(15 downto 0);
signal cpuClkCount : unsigned(7 downto 0);
signal cpuClock : std_logic;
signal serialClock : std_logic;
signal kbdClock : std_logic;
signal kbdClkCount : unsigned(11 downto 0);
signal M1_n : std_logic;
signal MREQ_n : std_logic;
signal IORQ_n : std_logic;
signal RD_n : std_logic;
signal WR_n : std_logic;
signal RFSH_n : std_logic;
signal HALT_n : std_logic;
signal WAIT_n : std_logic;
signal INT_n : std_logic;
signal RESET_s : std_logic;
signal BUSRQ_n : std_logic;
signal BUSAK_n : std_logic;
signal A : std_logic_vector(15 downto 0);
signal D : std_logic_vector(7 downto 0);
signal ROM_D : std_logic_vector(7 downto 0);
signal SRAM_D : std_logic_vector(7 downto 0);
signal UART0_D : std_logic_vector(7 downto 0);
signal UART1_D : std_logic_vector(7 downto 0);
signal CPU_D : std_logic_vector(7 downto 0);
signal DISPRAM_D : std_logic_vector(7 downto 0);
signal BLINKEN_D : std_logic_vector(7 downto 0);
signal Mirror : std_logic;
signal IOWR_n : std_logic;
signal RAMCS_n : std_logic;
signal ROMCS_n : std_logic;
signal DISPRAMCS_n : std_logic;
signal UART0CS_n : std_logic;
signal UART1CS_n : std_logic;
signal BLINKCS_n : std_logic;
signal BaudOut0 : std_logic;
signal BaudOut1 : std_logic;
signal PS2NewDataFlag : std_logic;
signal PS2Character : std_logic_vector(7 downto 0);
begin
pixelClk <= clk;
Wait_n <= '1';
BusRq_n <= '1';
INT_n <= '1';
process (Reset_n, cpuClock)
begin
if Reset_n = '0' then
Reset_s <= '0';
--Mirror <= '0';
elsif cpuClock'event and cpuClock = '1' then
Reset_s <= '1';
--if IORQ_n = '0' and A(7 downto 4) = "1111" then
-- Mirror <= D(0);
--end if;
end if;
end process;
process (Clk)
begin
if(rising_edge(Clk)) then
if cpuClkCount < 20 then
cpuClkCount <= cpuClkCount + 1;
else
cpuClkCount <= (others => '0');
end if;
if cpuClkCount < 10 then
cpuClock <= '1';
else
cpuClock <= '0';
end if;
-- 1.8432 MHz clock (ish) from 50 MHz
if (serialClkCount < 271) then
serialClkCount <= serialClkCount + 1;
else
serialClkCount <= (others => '0');
end if;
if (serialClkCount < 135) then
serialClock <= '1';
else
serialClock <= '0';
end if;
end if;
end process;
-- Memory decoding
IOWR_n <= WR_n or IORQ_n;
-- 1K RAM at 8000-83FF
RAMCS_n <= '0' when A(15 downto 10) = "100000" and MREQ_n = '0' else '1';
-- 4K display ram at F000-FFFF
DISPRAMCS_n <= '0' when A(15 downto 12) = "1111" and MREQ_n = '0' else '1';
-- 4K ROM at anywhere else (but mainly 0000-0fff)
ROMCS_n <= '0' when RAMCS_n = '1' and DISPRAMCS_n = '1' and MREQ_n = '0' else '1';
-- I/O Decoding - port 00-07 and 08-15 are UARTS, port 255 is the blinkenlights
BLINKCS_n <= '0' when IORQ_n = '0' and A(7 downto 0) = "11111111" else '1';
UART0CS_n <= '0' when IORQ_n = '0' and A(7 downto 3) = "00000" else '1';
UART1CS_n <= '0' when IORQ_n = '0' and A(7 downto 3) = "00001" else '1';
-- data bus selection
CPU_D <=
SRAM_D when RAMCS_n = '0' else
DISPRAM_D when DISPRAMCS_n = '0' else
UART0_D when UART0CS_n = '0' else
UART1_D when UART1CS_n = '0' else
BLINKEN_D when BLINKCS_n = '0' else
ROM_D;
ps2kbd: entity work.ps2_keyboard
port map(
clk => clk,
ps2_clk => PS2Clk,
ps2_data => PS2Data,
ps2_code_new => PS2NewDataFlag,
ps2_code => PS2Character
);
vgactrl1 : entity work.vga_controller
port map(
n_reset => Reset_n,
pixelClk => pixelClk,
hSync => hSync,
vSync => vSync,
frame_start => frame_start,
row_start => row_start,
disp_enable => display_enable,
row => row,
column => col
);
vgagfx1 : entity work.vga_textmode
port map(
n_reset => Reset_n,
pixelClk => pixelClk,
row => std_logic_vector(row),
column => std_logic_vector(col),
disp_enable => display_enable,
frame_start => frame_start,
row_start => row_start,
display_mem_addr => dispram_addr_b,
display_mem_data => dispram_output_b,
videoR => videoR,
videoG => videoG,
videoB => videoB
);
displaymem : entity work.displayram
port map (
-- clock_a => cpuClock,
-- address_a => A(11 downto 0),
clock_a => cpuClock,
address_a => A(11 downto 0),
q_a => DISPRAM_D,
data_a => D,
enable_a => not DISPRAMCS_n,
wren_a => not (WR_n or DISPRAMCS_n),
enable_b => '1',
clock_b => pixelClk,
address_b => dispram_addr_b,
q_b => dispram_output_b,
data_b => "00000000"
);
cpu0 : entity work.T80s
generic map(Mode => 1, T2Write => 1, IOWait => 0)
port map(
RESET_n => RESET_s,
CLK_n => cpuClock,
WAIT_n => WAIT_n,
INT_n => INT_n,
NMI_n => NMI_n,
BUSRQ_n => BUSRQ_n,
M1_n => M1_n,
MREQ_n => MREQ_n,
IORQ_n => IORQ_n,
RD_n => RD_n,
WR_n => WR_n,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
BUSAK_n => BUSAK_n,
A => A,
DI => CPU_D,
DO => D);
uart0 : entity work.T16450
port map(
MR_n => Reset_s,
XIn => Clk,
RClk => BaudOut0,
CS_n => UART0CS_n,
Rd_n => RD_n,
Wr_n => IOWR_n,
A => A(2 downto 0),
D_In => D,
D_Out => UART0_D,
SIn => RXD0,
CTS_n => CTS0,
DSR_n => DSR0,
RI_n => RI0,
DCD_n => DCD0,
SOut => TXD0,
RTS_n => RTS0,
DTR_n => DTR0,
OUT1_n => open,
OUT2_n => open,
BaudOut => BaudOut0,
Intr => open);
rom0 : entity work.bootrom
port map (
address => A(11 downto 0),
clock => cpuClock,
q => ROM_D
);
sram0 : entity work.sram
port map (
-- missing RAMCS_n
-- clken => not RAMCS_n,
address => A(9 downto 0),
clock => cpuClock,
data => D,
q => SRAM_D,
wren => not (WR_n or RAMCS_n)
);
-- Allow Z80 to update LED states - only 6 of the 8 bits are wired to LEDs though
process(cpuClkCount, reset_n)
begin
if (reset_n = '0') then
BLINKEN_D <= "00000000";
elsif (rising_edge(cpuClock)) then
if BLINKCS_n = '0' and WR_n = '0' then
BLINKEN_D <= D;
end if;
end if;
end process;
junkBuzzer <= '1';
blinkenlight(0) <= not BLINKEN_D(0);
blinkenlight(1) <= not BLINKEN_D(1);
blinkenlight(2) <= not BLINKEN_D(2);
blinkenlight(3) <= not BLINKEN_D(3);
blinkenlight(4) <= not BLINKEN_D(4);
blinkenlight(5) <= not BLINKEN_D(5);
end;