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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [pia6821.vhd] - Blame information for rev 99

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

Line No. Rev Author Line
1 99 davidgb
--===========================================================================--
2
--                                                                           --
3
--        Synthesizable 6821 Compatible Parallel Interface Adapter           --
4
--                                                                           --
5
--===========================================================================--
6
--
7
--  File name      : pia6821.vhd
8
--
9
--  Entity name    : pia6821
10
--
11
--  Purpose        : Implements a 6821 like PIA with
12
--                   2 x 8 bit parallel I/O ports with
13
--                   programmable data direction registers and
14
--                   2 x 2 bit control signals.
15
--                  
16
--  Dependencies   : ieee.std_logic_1164
17
--                   ieee.std_logic_unsigned
18
--                   unisim.vcomponents
19
--
20
--  Author         : John E. Kent
21
--
22
--  Email          : dilbert57@opencores.org      
23
--
24
--  Web            : http://opencores.org/project,system09
25
--
26
--  Description    : Register Memory Map
27
--
28
--                   Base + $00 - Port A Data & Direction register
29
--                   Base + $01 - Port A Control register
30
--                   Base + $02 - Port B Data & Direction Direction Register
31
--                   Base + $03 - Port B Control Register
32
--
33
--  Copyright (C) 2004 - 2010 John Kent
34
--
35
--  This program is free software: you can redistribute it and/or modify
36
--  it under the terms of the GNU General Public License as published by
37
--  the Free Software Foundation, either version 3 of the License, or
38
--  (at your option) any later version.
39
--
40
--  This program is distributed in the hope that it will be useful,
41
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
42
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43
--  GNU General Public License for more details.
44
--
45
--  You should have received a copy of the GNU General Public License
46
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
47
--
48
--===========================================================================--
49
--                                                                           --
50
--                              Revision  History                            --
51
--                                                                           --
52
--===========================================================================--
53
--
54
-- Version  Author     Date          Description
55
-- 0.0      John Kent  2004-05-01    Initial version developed from ioport.vhd
56
-- 0.1      John Kent  2010-05-30    Updated header & GPL information
57
-- 0.2      John Kent  2010-08-09    Made reset synchronous for wishbone compliance          
58
--
59
--===========================================================================--
60
 
61
library ieee;
62
   use ieee.std_logic_1164.all;
63
   use ieee.std_logic_unsigned.all;
64
library unisim;
65
   use unisim.vcomponents.all;
66
 
67
entity pia6821 is
68
  port (
69
    clk       : in    std_logic;
70
    rst       : in    std_logic;
71
    cs        : in    std_logic;
72
    rw        : in    std_logic;
73
    addr      : in    std_logic_vector(1 downto 0);
74
    data_in   : in    std_logic_vector(7 downto 0);
75
    data_out  : out   std_logic_vector(7 downto 0);
76
    irqa      : out   std_logic;
77
    irqb      : out   std_logic;
78
    pa        : inout std_logic_vector(7 downto 0);
79
    ca1       : in    std_logic;
80
    ca2       : inout std_logic;
81
    pb        : inout std_logic_vector(7 downto 0);
82
    cb1       : in    std_logic;
83
    cb2       : inout std_logic
84
  );
85
end;
86
 
87
architecture pia_arch of pia6821 is
88
 
89
signal porta_ddr   : std_logic_vector(7 downto 0);
90
signal porta_data  : std_logic_vector(7 downto 0);
91
signal porta_ctrl  : std_logic_vector(5 downto 0);
92
signal porta_read  : std_logic;
93
 
94
signal portb_ddr   : std_logic_vector(7 downto 0);
95
signal portb_data  : std_logic_vector(7 downto 0);
96
signal portb_ctrl  : std_logic_vector(5 downto 0);
97
signal portb_read  : std_logic;
98
signal portb_write : std_logic;
99
 
100
signal ca1_del     : std_logic;
101
signal ca1_rise    : std_logic;
102
signal ca1_fall    : std_logic;
103
signal ca1_edge    : std_logic;
104
signal irqa1       : std_logic;
105
 
106
signal ca2_del     : std_logic;
107
signal ca2_rise    : std_logic;
108
signal ca2_fall    : std_logic;
109
signal ca2_edge    : std_logic;
110
signal irqa2       : std_logic;
111
signal ca2_out     : std_logic;
112
 
113
signal cb1_del     : std_logic;
114
signal cb1_rise    : std_logic;
115
signal cb1_fall    : std_logic;
116
signal cb1_edge    : std_logic;
117
signal irqb1       : std_logic;
118
 
119
signal cb2_del     : std_logic;
120
signal cb2_rise    : std_logic;
121
signal cb2_fall    : std_logic;
122
signal cb2_edge    : std_logic;
123
signal irqb2       : std_logic;
124
signal cb2_out     : std_logic;
125
 
126
begin
127
 
128
--------------------------------
129
--
130
-- read I/O port
131
--
132
--------------------------------
133
 
134
pia_read : process(  addr,      cs,
135
                     irqa1, irqa2, irqb1, irqb2,
136
                     porta_ddr,  portb_ddr,
137
                     porta_data, portb_data,
138
                     porta_ctrl, portb_ctrl,
139
                     pa,         pb )
140
variable count : integer;
141
begin
142
  case addr is
143
  when "00" =>
144
    for count in 0 to 7 loop
145
      if porta_ctrl(2) = '0' then
146
        data_out(count) <= porta_ddr(count);
147
        porta_read <= '0';
148
      else
149
        if porta_ddr(count) = '1' then
150
          data_out(count) <= porta_data(count);
151
        else
152
          data_out(count) <= pa(count);
153
        end if;
154
        porta_read <= cs;
155
      end if;
156
    end loop;
157
    portb_read <= '0';
158
 
159
  when "01" =>
160
    data_out <= irqa1 & irqa2 & porta_ctrl;
161
    porta_read <= '0';
162
    portb_read <= '0';
163
 
164
  when "10" =>
165
    for count in 0 to 7 loop
166
      if portb_ctrl(2) = '0' then
167
        data_out(count) <= portb_ddr(count);
168
        portb_read <= '0';
169
      else
170
        if portb_ddr(count) = '1' then
171
          data_out(count) <= portb_data(count);
172
        else
173
          data_out(count) <= pb(count);
174
        end if;
175
        portb_read <= cs;
176
      end if;
177
    end loop;
178
    porta_read <= '0';
179
 
180
  when "11" =>
181
    data_out <= irqb1 & irqb2 & portb_ctrl;
182
    porta_read <= '0';
183
    portb_read <= '0';
184
 
185
  when others =>
186
    data_out <= "00000000";
187
    porta_read <= '0';
188
    portb_read <= '0';
189
 
190
  end case;
191
 
192
end process;
193
 
194
---------------------------------
195
--
196
-- Write I/O ports
197
--
198
---------------------------------
199
 
200
pia_write : process( clk, rst, addr, cs, rw, data_in,
201
                     porta_ctrl, portb_ctrl,
202
                     porta_data, portb_data,
203
                     porta_ctrl, portb_ctrl,
204
                     porta_ddr, portb_ddr )
205
begin
206
  if clk'event and clk = '1' then
207
    portb_write <= '0';
208
    if rst = '1' then
209
      porta_ddr   <= (others=>'0');
210
      porta_data  <= (others=>'0');
211
      porta_ctrl  <= (others=>'0');
212
      portb_ddr   <= (others=>'0');
213
      portb_data  <= (others=>'0');
214
      portb_ctrl  <= (others=>'0');
215
    elsif cs = '1' and rw = '0' then
216
      case addr is
217
        when "00" =>
218
        if porta_ctrl(2) = '0' then
219
          porta_ddr  <= data_in;
220
        else
221
          porta_data <= data_in;
222
        end if;
223
      when "01" =>
224
        porta_ctrl  <= data_in(5 downto 0);
225
      when "10" =>
226
        if portb_ctrl(2) = '0' then
227
          portb_ddr   <= data_in;
228
        else
229
          portb_data  <= data_in;
230
          portb_write <= '1';
231
        end if;
232
      when "11" =>
233
        portb_ctrl  <= data_in(5 downto 0);
234
      when others =>
235
        null;
236
      end case;
237
    end if;
238
  end if;
239
end process;
240
 
241
---------------------------------
242
--
243
-- direction control port a
244
--
245
---------------------------------
246
porta_direction : process ( porta_data, porta_ddr )
247
variable count : integer;
248
begin
249
  for count in 0 to 7 loop
250
    if porta_ddr(count) = '1' then
251
      pa(count) <= porta_data(count);
252
    else
253
      pa(count) <= 'Z';
254
    end if;
255
  end loop;
256
end process;
257
 
258
---------------------------------
259
--
260
-- CA1 Edge detect
261
--
262
---------------------------------
263
ca1_input : process( clk, rst, ca1, ca1_del,
264
                     ca1_rise, ca1_fall, ca1_edge,
265
                     irqa1, porta_ctrl, porta_read )
266
begin
267
  if clk'event and clk = '0' then
268
    if rst = '1' then
269
      ca1_del  <= '0';
270
      ca1_rise <= '0';
271
      ca1_fall <= '0';
272
      irqa1    <= '0';
273
    else
274
      ca1_del  <= ca1;
275
      ca1_rise <= (not ca1_del) and ca1;
276
      ca1_fall <= ca1_del and (not ca1);
277
      if ca1_edge = '1' then
278
        irqa1 <= '1';
279
      elsif porta_read = '1' then
280
        irqa1 <= '0';
281
      end if;
282
    end if;
283
  end if;
284
 
285
  if porta_ctrl(1) = '0' then
286
    ca1_edge <= ca1_fall;
287
  else
288
    ca1_edge <= ca1_rise;
289
  end if;
290
 
291
end process;
292
 
293
---------------------------------
294
--
295
-- CA2 Edge detect
296
--
297
---------------------------------
298
ca2_input : process( clk, rst, ca2, ca2_del,
299
                     ca2_rise, ca2_fall, ca2_edge,
300
                     irqa2, porta_ctrl, porta_read )
301
begin
302
  if clk'event and clk = '0' then
303
    if rst = '1' then
304
      ca2_del  <= '0';
305
      ca2_rise <= '0';
306
      ca2_fall <= '0';
307
      irqa2    <= '0';
308
    else
309
      ca2_del  <= ca2;
310
      ca2_rise <= (not ca2_del) and ca2;
311
      ca2_fall <= ca2_del and (not ca2);
312
      if porta_ctrl(5) = '0' and ca2_edge = '1' then
313
        irqa2 <= '1';
314
      elsif porta_read = '1' then
315
        irqa2 <= '0';
316
      else
317
        irqa2 <= irqa2;
318
      end if;
319
    end if;
320
  end if;
321
 
322
  if porta_ctrl(4) = '0' then
323
    ca2_edge <= ca2_fall;
324
  else
325
    ca2_edge <= ca2_rise;
326
  end if;
327
end process;
328
 
329
---------------------------------
330
--
331
-- CA2 output control
332
--
333
---------------------------------
334
ca2_output : process( clk, rst, porta_ctrl, porta_read, ca1_edge, ca2_out )
335
begin
336
  if clk'event and clk='0' then
337
    if rst='1' then
338
      ca2_out <= '0';
339
    else
340
      case porta_ctrl(5 downto 3) is
341
      when "100" => -- read PA clears, CA1 edge sets
342
        if porta_read = '1' then
343
          ca2_out <= '0';
344
        elsif ca1_edge = '1' then
345
          ca2_out <= '1';
346
        else
347
          ca2_out <= ca2_out;
348
        end if;
349
      when "101" => -- read PA clears, E sets
350
        ca2_out <= not porta_read;
351
      when "110" =>     -- set low
352
        ca2_out <= '0';
353
      when "111" =>     -- set high
354
        ca2_out <= '1';
355
      when others => -- no change
356
        ca2_out <= ca2_out;
357
      end case;
358
    end if;
359
  end if;
360
end process;
361
 
362
---------------------------------
363
--
364
-- CA2 direction control
365
--
366
---------------------------------
367
ca2_direction : process( porta_ctrl, ca2, ca2_out )
368
begin
369
  if porta_ctrl(5) = '0' then
370
    ca2 <= 'Z';
371
  else
372
    ca2 <= ca2_out;
373
  end if;
374
end process;
375
 
376
---------------------------------
377
--
378
-- direction control port b
379
--
380
---------------------------------
381
portb_direction : process ( portb_data, portb_ddr )
382
variable count : integer;
383
begin
384
  for count in 0 to 7 loop
385
    if portb_ddr(count) = '1' then
386
      pb(count) <= portb_data(count);
387
    else
388
      pb(count) <= 'Z';
389
    end if;
390
  end loop;
391
end process;
392
 
393
---------------------------------
394
--
395
-- CB1 Edge detect
396
--
397
---------------------------------
398
cb1_input : process( clk, rst, cb1, cb1_del,
399
                     cb1_rise, cb1_fall, cb1_edge,
400
                     irqb1, portb_ctrl, portb_read )
401
begin
402
  if clk'event and clk = '0' then
403
    if rst = '1' then
404
      cb1_del  <= '0';
405
      cb1_rise <= '0';
406
      cb1_fall <= '0';
407
      irqb1    <= '0';
408
    else
409
      cb1_del  <= cb1;
410
      cb1_rise <= (not cb1_del) and cb1;
411
      cb1_fall <= cb1_del and (not cb1);
412
 
413
      if cb1_edge = '1' then
414
        irqb1 <= '1';
415
      elsif portb_read = '1' then
416
        irqb1 <= '0';
417
      end if;
418
 
419
    end if;
420
  end if;
421
 
422
  if portb_ctrl(1) = '0' then
423
    cb1_edge <= cb1_fall;
424
  else
425
    cb1_edge <= cb1_rise;
426
  end if;
427
 
428
end process;
429
 
430
---------------------------------
431
--
432
-- CB2 Edge detect
433
--
434
---------------------------------
435
cb2_input : process( clk, rst, cb2, cb2_del,
436
                     cb2_rise, cb2_fall, cb2_edge,
437
                     irqb2, portb_ctrl, portb_read )
438
begin
439
  if clk'event and clk = '0' then
440
    if rst = '1' then
441
      cb2_del  <= '0';
442
      cb2_rise <= '0';
443
      cb2_fall <= '0';
444
      irqb2    <= '0';
445
    else
446
      cb2_del  <= cb2;
447
      cb2_rise <= (not cb2_del) and cb2;
448
      cb2_fall <= cb2_del and (not cb2);
449
 
450
      if portb_ctrl(5) = '0' and cb2_edge = '1' then
451
        irqb2 <= '1';
452
      elsif portb_read = '1' then
453
        irqb2 <= '0';
454
      end if;
455
 
456
    end if;
457
  end if;
458
 
459
  if portb_ctrl(4) = '0' then
460
    cb2_edge <= cb2_fall;
461
  else
462
    cb2_edge <= cb2_rise;
463
  end if;
464
end process;
465
 
466
---------------------------------
467
--
468
-- CB2 output control
469
--
470
---------------------------------
471
cb2_output : process( clk, rst, portb_ctrl, portb_write, cb1_edge, cb2_out )
472
begin
473
  if clk'event and clk='0' then
474
    if rst='1' then
475
      cb2_out <= '0';
476
    else
477
      case portb_ctrl(5 downto 3) is
478
      when "100" => -- write PB clears, CA1 edge sets
479
        if portb_write = '1' then
480
          cb2_out <= '0';
481
        elsif cb1_edge = '1' then
482
          cb2_out <= '1';
483
        end if;
484
      when "101" => -- write PB clears, E sets
485
        cb2_out <= not portb_write;
486
      when "110" =>     -- set low
487
        cb2_out <= '0';
488
      when "111" =>     -- set high
489
        cb2_out <= '1';
490
      when others => -- no change
491
        null;
492
      end case;
493
    end if;
494
  end if;
495
end process;
496
 
497
---------------------------------
498
--
499
-- CB2 direction control
500
--
501
---------------------------------
502
cb2_direction : process( portb_ctrl, cb2, cb2_out )
503
begin
504
  if portb_ctrl(5) = '0' then
505
    cb2 <= 'Z';
506
  else
507
    cb2 <= cb2_out;
508
  end if;
509
end process;
510
 
511
---------------------------------
512
--
513
-- IRQ control
514
--
515
---------------------------------
516
pia_irq : process( irqa1, irqa2, irqb1, irqb2, porta_ctrl, portb_ctrl )
517
begin
518
  irqa <= (irqa1 and porta_ctrl(0)) or (irqa2 and porta_ctrl(3));
519
  irqb <= (irqb1 and portb_ctrl(0)) or (irqb2 and portb_ctrl(3));
520
end process;
521
 
522
end pia_arch;
523
 

powered by: WebSVN 2.1.0

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