-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathMicrocomputerZ80Basic.vhd
322 lines (271 loc) · 8.92 KB
/
MicrocomputerZ80Basic.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
320
321
322
-- This file is copyright by Grant Searle 2014
-- You are free to use this file in your own projects but must never charge for it nor use it without
-- acknowledgement.
-- Please ask permission from Grant Searle before republishing elsewhere.
-- If you use this file or any part of it, please add an acknowledgement to myself and
-- a link back to my main web site http://searle.hostei.com/grant/
-- and to the "multicomp" page at http://searle.hostei.com/grant/Multicomp/index.html
--
-- Please check on the above web pages to see if there are any updates before using this file.
-- If for some reason the page is no longer available, please search for "Grant Searle"
-- on the internet to see if I have moved to another web hosting service.
--
-- Grant Searle
-- eMail address available on my main web page link above.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity MicrocomputerZ80Basic is
port(
N_RESET : in std_logic;
clk : in std_logic;
baud_increment : in std_logic_vector(15 downto 0);
sramData : inout std_logic_vector(7 downto 0);
sramAddress : out std_logic_vector(15 downto 0);
n_sRamWE : out std_logic;
n_sRamCS : out std_logic;
n_sRamOE : out std_logic;
n_sRamLB : out std_logic;
n_sRamUB : out std_logic;
rxd1 : in std_logic;
txd1 : out std_logic;
rts1 : out std_logic;
cts1 : in std_logic; -- Added CTS input
rxd2 : in std_logic;
txd2 : out std_logic;
rts2 : out std_logic;
videoSync : out std_logic;
video : out std_logic;
R : out std_logic_vector(1 downto 0);
G : out std_logic_vector(1 downto 0);
B : out std_logic_vector(1 downto 0);
HS : out std_logic;
VS : out std_logic;
hBlank : out std_logic;
vBlank : out std_logic;
cepix : out std_logic;
ps2Clk : in std_logic;
ps2Data : in std_logic;
sdCS : out std_logic;
sdMOSI : out std_logic;
sdMISO : in std_logic;
sdSCLK : out std_logic;
driveLED : out std_logic :='1'
);
end MicrocomputerZ80Basic;
architecture struct of MicrocomputerZ80Basic is
signal reset_counter : unsigned(15 downto 0) := (others => '0');
signal reset_n_internal : std_logic := '0'; -- Active low internal reset
signal n_WR : std_logic;
signal n_RD : std_logic;
signal cpuAddress : std_logic_vector(15 downto 0);
signal cpuDataOut : std_logic_vector(7 downto 0);
signal cpuDataIn : std_logic_vector(7 downto 0);
signal basRomData : std_logic_vector(7 downto 0);
signal internalRam1DataOut : std_logic_vector(7 downto 0);
signal internalRam2DataOut : std_logic_vector(7 downto 0);
signal interface1DataOut : std_logic_vector(7 downto 0);
signal interface2DataOut : std_logic_vector(7 downto 0);
signal sdCardDataOut : std_logic_vector(7 downto 0);
signal n_memWR : std_logic :='1';
signal n_memRD : std_logic :='1';
signal n_ioWR : std_logic :='1';
signal n_ioRD : std_logic :='1';
signal n_MREQ : std_logic :='1';
signal n_IORQ : std_logic :='1';
signal n_int1 : std_logic :='1';
signal n_int2 : std_logic :='1';
signal n_externalRamCS : std_logic :='1';
signal n_internalRam1CS : std_logic :='1';
signal n_internalRam2CS : std_logic :='1';
signal n_basRomCS : std_logic :='1';
signal n_interface1CS : std_logic :='1';
signal n_interface2CS : std_logic :='1';
signal n_sdCardCS : std_logic :='1';
signal serialClkCount : unsigned(15 downto 0);
signal cpuClkCount : std_logic_vector(5 downto 0);
signal sdClkCount : std_logic_vector(5 downto 0);
signal cpuClock : std_logic;
signal serialClock : std_logic;
signal sdClock : std_logic;
begin
process(clk)
begin
if rising_edge(clk) then
if N_RESET = '0' then
reset_counter <= (others => '0');
reset_n_internal <= '0';
else
if reset_counter /= unsigned'(X"FFFF") then
reset_counter <= reset_counter + 1;
reset_n_internal <= '0';
else
reset_n_internal <= '1';
end if;
end if;
end if;
end process;
-- ____________________________________________________________________________________
-- CPU CHOICE GOES HERE
cpu1 : entity work.t80s
generic map(mode => 1, t2write => 1, iowait => 0)
port map(
reset_n => reset_n_internal,
clk_n => cpuClock,
wait_n => '1',
int_n => '1',
nmi_n => '1',
busrq_n => '1',
mreq_n => n_MREQ,
iorq_n => n_IORQ,
rd_n => n_RD,
wr_n => n_WR,
a => cpuAddress,
di => cpuDataIn,
do => cpuDataOut
);
-- ____________________________________________________________________________________
-- ROM GOES HERE
rom1 : entity work.Z80_BASIC_ROM -- 8KB BASIC
port map(
address => cpuAddress(12 downto 0),
clock => clk,
q => basRomData
);
-- ____________________________________________________________________________________
-- RAM GOES HERE
ram1: entity work.InternalRam64K
port map
(
address => cpuAddress(15 downto 0),
clock => clk,
data => cpuDataOut,
wren => not(n_memWR or n_internalRam1CS),
q => internalRam1DataOut
);
-- ____________________________________________________________________________________
-- INPUT/OUTPUT DEVICES GO HERE
io1 : entity work.SBCTextDisplayRGB
port map (
n_reset => N_RESET,
clk => clk,
-- RGB video signals
hSync => HS,
vSync => VS,
videoR0 => R(1),
videoR1 => R(0),
videoG0 => G(1),
videoG1 => G(0),
videoB0 => B(1),
videoB1 => B(0),
hBlank => hBlank,
vBlank => vBlank,
cepix => cepix,
-- Monochrome video signals (when using TV timings only)
sync => videoSync,
video => video,
n_wr => n_interface1CS or n_ioWR,
n_rd => n_interface1CS or n_ioRD,
n_int => n_int1,
regSel => cpuAddress(0),
dataIn => cpuDataOut,
dataOut => interface1DataOut,
ps2Clk => ps2Clk,
ps2Data => ps2Data
);
io2 : entity work.bufferedUART
port map(
clk => clk,
n_wr => n_interface2CS or n_ioWR,
n_rd => n_interface2CS or n_ioRD,
n_int => n_int2,
regSel => cpuAddress(0),
dataIn => cpuDataOut,
dataOut => interface2DataOut,
rxClock => serialClock,
txClock => serialClock,
rxd => rxd1,
txd => txd1,
n_cts => cts1, -- Connect CTS signal
n_dcd => '0',
n_rts => rts1
);
sd1 : entity work.sd_controller
port map(
sdCS => sdCS,
sdMOSI => sdMOSI,
sdMISO => sdMISO,
sdSCLK => sdSCLK,
n_wr => n_sdCardCS or n_ioWR,
n_rd => n_sdCardCS or n_ioRD,
n_reset => N_RESET,
dataIn => cpuDataOut,
dataOut => sdCardDataOut,
regAddr => cpuAddress(2 downto 0),
driveLED => driveLED,
clk => sdClock -- twice the spi clk
);
-- ____________________________________________________________________________________
-- MEMORY READ/WRITE LOGIC GOES HERE
n_ioWR <= n_WR or n_IORQ;
n_memWR <= n_WR or n_MREQ;
n_ioRD <= n_RD or n_IORQ;
n_memRD <= n_RD or n_MREQ;
-- ____________________________________________________________________________________
-- CHIP SELECTS GO HERE
n_basRomCS <= '0' when cpuAddress(15 downto 13) = "000" else '1'; --8K at bottom of memory
n_interface1CS <= '0' when cpuAddress(7 downto 1) = "1000000" and (n_ioWR='0' or n_ioRD = '0') else '1'; -- 2 Bytes $80-$81
n_interface2CS <= '0' when cpuAddress(7 downto 1) = "1000001" and (n_ioWR='0' or n_ioRD = '0') else '1'; -- 2 Bytes $82-$83
n_sdCardCS <= '0' when cpuAddress(7 downto 3) = "10001" and (n_ioWR='0' or n_ioRD = '0') else '1'; -- 8 Bytes $88-$8F
n_internalRam1CS <= not n_basRomCS; -- Full Internal RAM - 64 K
-- ____________________________________________________________________________________
-- BUS ISOLATION GOES HERE
cpuDataIn <=
interface1DataOut when n_interface1CS = '0' else
interface2DataOut when n_interface2CS = '0' else
sdCardDataOut when n_sdCardCS = '0' else
basRomData when n_basRomCS = '0' else
internalRam1DataOut when n_internalRam1CS= '0' else
sramData when n_externalRamCS= '0' else
x"FF";
-- ____________________________________________________________________________________
-- SYSTEM CLOCKS GO HERE
-- SUB-CIRCUIT CLOCK SIGNALS
serialClock <= serialClkCount(15);
process (clk)
begin
if rising_edge(clk) then
if cpuClkCount < 4 then -- 4 = 10MHz, 3 = 12.5MHz, 2=16.6MHz, 1=25MHz
cpuClkCount <= cpuClkCount + 1;
else
cpuClkCount <= (others=>'0');
end if;
if cpuClkCount < 2 then -- 2 when 10MHz, 2 when 12.5MHz, 2 when 16.6MHz, 1 when 25MHz
cpuClock <= '0';
else
cpuClock <= '1';
end if;
if sdClkCount < 49 then -- 1MHz
sdClkCount <= sdClkCount + 1;
else
sdClkCount <= (others=>'0');
end if;
if sdClkCount < 25 then
sdClock <= '0';
else
sdClock <= '1';
end if;
-- Serial clock DDS
-- 50MHz master input clock:
-- Baud Increment
-- 115200 2416
-- 38400 805
-- 19200 403
-- 9600 201
-- 4800 101
-- 2400 50
serialClkCount <= serialClkCount + unsigned(baud_increment);
end if;
end process;
end;