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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [pia_timer.vhd] - Blame information for rev 82

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

Line No. Rev Author Line
1 22 dilbert57
-- $Id: pia_timer.vhd,v 1.2 2008-03-14 15:52:46 dilbert57 Exp $
2 19 dilbert57
--===========================================================================--
3
--
4
--  S Y N T H E Z I A B L E    I/O Port   C O R E
5
--
6
--  www.OpenCores.Org - May 2004
7
--  This core adheres to the GNU public license  
8
--
9
-- File name      : pia_timer.vhd
10
--
11
-- Purpose        : Implements 2 x 8 bit parallel I/O ports
12
--                  with 8 bit presetable counter.
13
--                  port a = output connected to presettable counter input
14
--                  port b = input connected to counter output
15
--                  
16
-- Dependencies   : ieee.Std_Logic_1164
17
--                  ieee.std_logic_unsigned
18
--
19
-- Author         : John E. Kent      
20
--
21
--===========================================================================----
22
--
23
-- Revision History:
24
--
25
-- Date:          Revision         Author
26
-- 1 May 2004     0.0              John Kent
27
-- Initial version developed from ioport.vhd
28
--
29
-- 22 April 2006  1.0              John Kent
30
-- Removed I/O ports and hard wired a binary
31
-- down counter. Port A is the preset output.
32
-- Port B is the timer count input.
33
-- CA1 & CB1 are interrupt inputs
34
-- CA2 is the counter load (active low)
35
-- CB2 is the counter reset (active high)
36
-- It may be necessary to offset the counter
37
-- to compensate for differences in cpu cycle
38
-- times between FPGA and real 6809 systems.
39
--
40
-- 24 May 2006  1.1                                     John Kent
41
-- Modified counter to subtract one from preset
42
-- so FPGA version of the CMC_BUG monitor is
43
-- compatible with the reference design.
44
--
45
--===========================================================================----
46
--
47
-- Memory Map
48
--
49
-- IO + $00 - Port A Data & Direction register
50
-- IO + $01 - Port A Control register
51
-- IO + $02 - Port B Data & Direction Direction Register
52
-- IO + $03 - Port B Control Register
53
--
54
 
55
library ieee;
56
use ieee.std_logic_1164.all;
57
use ieee.std_logic_unsigned.all;
58
 
59
entity pia_timer is
60
        port (
61
         clk       : in    std_logic;
62
    rst       : in    std_logic;
63
    cs        : in    std_logic;
64
    rw        : in    std_logic;
65
    addr      : in    std_logic_vector(1 downto 0);
66
    data_in   : in    std_logic_vector(7 downto 0);
67
         data_out  : out   std_logic_vector(7 downto 0);
68
         irqa      : out   std_logic;
69
         irqb      : out   std_logic
70
         );
71
end;
72
 
73
architecture pia_arch of pia_timer is
74
 
75
signal pa          : std_logic_vector(7 downto 0);
76
signal porta_ddr   : std_logic_vector(7 downto 0);
77
signal porta_data  : std_logic_vector(7 downto 0);
78
signal porta_ctrl  : std_logic_vector(5 downto 0);
79
signal porta_read  : std_logic;
80
 
81
signal pb          : std_logic_vector(7 downto 0);
82
signal portb_ddr   : std_logic_vector(7 downto 0);
83
signal portb_data  : std_logic_vector(7 downto 0);
84
signal portb_ctrl  : std_logic_vector(5 downto 0);
85
signal portb_read  : std_logic;
86
signal portb_write : std_logic;
87
 
88
signal ca1         : std_logic;
89
signal ca1_del     : std_logic;
90
signal ca1_rise    : std_logic;
91
signal ca1_fall    : std_logic;
92
signal ca1_edge    : std_logic;
93
signal irqa1       : std_logic;
94
 
95
signal ca2         : std_logic;
96
signal ca2_del     : std_logic;
97
signal ca2_rise    : std_logic;
98
signal ca2_fall    : std_logic;
99
signal ca2_edge    : std_logic;
100
signal irqa2       : std_logic;
101
signal ca2_out     : std_logic;
102
 
103
signal cb1         : std_logic;
104
signal cb1_del     : std_logic;
105
signal cb1_rise    : std_logic;
106
signal cb1_fall    : std_logic;
107
signal cb1_edge    : std_logic;
108
signal irqb1       : std_logic;
109
 
110
signal cb2         : std_logic;
111
signal cb2_del     : std_logic;
112
signal cb2_rise    : std_logic;
113
signal cb2_fall    : std_logic;
114
signal cb2_edge    : std_logic;
115
signal irqb2       : std_logic;
116
signal cb2_out     : std_logic;
117
 
118
-- 74193 down counter
119
signal timer       : std_logic_vector(7 downto 0);
120
 
121
begin
122
 
123
--------------------------------
124
--
125
-- read I/O port
126
--
127
--------------------------------
128
 
129
pia_read : process(  addr,      cs,
130
                     irqa1, irqa2, irqb1, irqb2,
131
                     porta_ddr,  portb_ddr,
132
                                                        porta_data, portb_data,
133
                                                        porta_ctrl, portb_ctrl,
134
                                                   pa,         pb )
135
variable count : integer;
136
begin
137
      case addr is
138
             when "00" =>
139
                    for count in 0 to 7 loop
140
                           if porta_ctrl(2) = '0' then
141
                                  data_out(count) <= porta_ddr(count);
142
                             porta_read <= '0';
143
            else
144
                                  if porta_ddr(count) = '1' then
145
                data_out(count) <= porta_data(count);
146
              else
147
                data_out(count) <= pa(count);
148
              end if;
149
                             porta_read <= cs;
150
            end if;
151
                         end loop;
152
                         portb_read <= '0';
153
 
154
             when "01" =>
155
                    data_out <= irqa1 & irqa2 & porta_ctrl;
156
                         porta_read <= '0';
157
                         portb_read <= '0';
158
 
159
                  when "10" =>
160
                    for count in 0 to 7 loop
161
                           if portb_ctrl(2) = '0' then
162
                                  data_out(count) <= portb_ddr(count);
163
                                  portb_read <= '0';
164
            else
165
                                  if portb_ddr(count) = '1' then
166
                data_out(count) <= portb_data(count);
167
              else
168
                data_out(count) <= pb(count);
169
                                  end if;
170
                                  portb_read <= cs;
171
            end if;
172
                         end loop;
173
                         porta_read <= '0';
174
 
175
                  when "11" =>
176
                    data_out <= irqb1 & irqb2 & portb_ctrl;
177
                         porta_read <= '0';
178
                         portb_read <= '0';
179
 
180
                  when others =>
181
                    data_out <= "00000000";
182
                         porta_read <= '0';
183
                         portb_read <= '0';
184
 
185
                end case;
186
end process;
187
 
188
---------------------------------
189
--
190
-- Write I/O ports
191
--
192
---------------------------------
193
 
194
pia_write : process( clk, rst, addr, cs, rw, data_in,
195
                        porta_ctrl, portb_ctrl,
196
                        porta_data, portb_data,
197
                                                                porta_ctrl, portb_ctrl,
198
                                                                porta_ddr, portb_ddr )
199
begin
200
  if rst = '1' then
201
      porta_ddr   <= "00000000";
202
      porta_data  <= "00000000";
203
      porta_ctrl  <= "000000";
204
      portb_ddr   <= "00000000";
205
      portb_data  <= "00000000";
206
                portb_ctrl  <= "000000";
207
                portb_write <= '0';
208
  elsif clk'event and clk = '1' then
209
    if cs = '1' and rw = '0' then
210
      case addr is
211
             when "00" =>
212
                    if porta_ctrl(2) = '0' then
213
                       porta_ddr  <= data_in;
214
                       porta_data <= porta_data;
215
                         else
216
                       porta_ddr  <= porta_ddr;
217
                       porta_data <= data_in;
218
                         end if;
219
                         porta_ctrl  <= porta_ctrl;
220
                    portb_ddr   <= portb_ddr;
221
                    portb_data  <= portb_data;
222
                         portb_ctrl  <= portb_ctrl;
223
                         portb_write <= '0';
224
                  when "01" =>
225
                    porta_ddr   <= porta_ddr;
226
                    porta_data  <= porta_data;
227
                         porta_ctrl  <= data_in(5 downto 0);
228
                    portb_ddr   <= portb_ddr;
229
                    portb_data  <= portb_data;
230
                         portb_ctrl  <= portb_ctrl;
231
                         portb_write <= '0';
232
             when "10" =>
233
                    porta_ddr   <= porta_ddr;
234
                    porta_data  <= porta_data;
235
                         porta_ctrl  <= porta_ctrl;
236
                    if portb_ctrl(2) = '0' then
237
                       portb_ddr   <= data_in;
238
                       portb_data  <= portb_data;
239
                            portb_write <= '0';
240
                         else
241
                       portb_ddr   <= portb_ddr;
242
                       portb_data  <= data_in;
243
                            portb_write <= '1';
244
                         end if;
245
                         portb_ctrl  <= portb_ctrl;
246
                  when "11" =>
247
                    porta_ddr   <= porta_ddr;
248
                    porta_data  <= porta_data;
249
                         porta_ctrl  <= porta_ctrl;
250
                    portb_ddr   <= portb_ddr;
251
                    portb_data  <= portb_data;
252
                         portb_ctrl  <= data_in(5 downto 0);
253
                         portb_write <= '0';
254
                  when others =>
255
                    porta_ddr   <= porta_ddr;
256
                    porta_data  <= porta_data;
257
                         porta_ctrl  <= porta_ctrl;
258
                    portb_ddr   <= portb_ddr;
259
                    portb_data  <= portb_data;
260
                         portb_ctrl  <= portb_ctrl;
261
                         portb_write <= '0';
262
                end case;
263
         else
264
                    porta_ddr   <= porta_ddr;
265
                    porta_data  <= porta_data;
266
                         porta_ctrl  <= porta_ctrl;
267
                    portb_data  <= portb_data;
268
                    portb_ddr   <= portb_ddr;
269
                         portb_ctrl  <= portb_ctrl;
270
                         portb_write <= '0';
271
         end if;
272
  end if;
273
end process;
274
 
275
---------------------------------
276
--
277
-- CA1 Edge detect
278
--
279
---------------------------------
280
ca1_input : process( clk, rst, ca1, ca1_del,
281
                     ca1_rise, ca1_fall, ca1_edge,
282
                                                        irqa1, porta_ctrl, porta_read )
283
begin
284
  if rst = '1' then
285
    ca1_del  <= '0';
286
         ca1_rise <= '0';
287
    ca1_fall <= '0';
288
         ca1_edge <= '0';
289
         irqa1    <= '0';
290
  elsif clk'event and clk = '0' then
291
    ca1_del  <= ca1;
292
    ca1_rise <= (not ca1_del) and ca1;
293
    ca1_fall <= ca1_del and (not ca1);
294
         if ca1_edge = '1' then
295
            irqa1 <= '1';
296
         elsif porta_read = '1' then
297
            irqa1 <= '0';
298
    else
299
            irqa1 <= irqa1;
300
    end if;
301
  end if;
302
 
303
  if porta_ctrl(1) = '0' then
304
         ca1_edge <= ca1_fall;
305
  else
306
         ca1_edge <= ca1_rise;
307
  end if;
308
end process;
309
 
310
---------------------------------
311
--
312
-- CA2 Edge detect
313
--
314
---------------------------------
315
ca2_input : process( clk, rst, ca2, ca2_del,
316
                     ca2_rise, ca2_fall, ca2_edge,
317
                                                        irqa2, porta_ctrl, porta_read )
318
begin
319
  if rst = '1' then
320
    ca2_del  <= '0';
321
         ca2_rise <= '0';
322
    ca2_fall <= '0';
323
         ca2_edge <= '0';
324
         irqa2    <= '0';
325
  elsif clk'event and clk = '0' then
326
    ca2_del  <= ca2;
327
    ca2_rise <= (not ca2_del) and ca2;
328
    ca2_fall <= ca2_del and (not ca2);
329
         if porta_ctrl(5) = '0' and ca2_edge = '1' then
330
            irqa2 <= '1';
331
         elsif porta_read = '1' then
332
            irqa2 <= '0';
333
    else
334
            irqa2 <= irqa2;
335
    end if;
336
  end if;
337
 
338
  if porta_ctrl(4) = '0' then
339
         ca2_edge <= ca2_fall;
340
  else
341
         ca2_edge <= ca2_rise;
342
  end if;
343
end process;
344
 
345
---------------------------------
346
--
347
-- CA2 output control
348
--
349
---------------------------------
350
ca2_output : process( clk, rst, porta_ctrl, porta_read, ca1_edge, ca2_out )
351
begin
352
  if rst='1' then
353
    ca2_out <= '0';
354
  elsif clk'event and clk='0' then
355
    case porta_ctrl(5 downto 3) is
356
    when "100" => -- read PA clears, CA1 edge sets
357
      if porta_read = '1' then
358
             ca2_out <= '0';
359
      elsif ca1_edge = '1' then
360
             ca2_out <= '1';
361
      else
362
             ca2_out <= ca2_out;
363
      end if;
364
    when "101" => -- read PA clears, E sets
365
      ca2_out <= not porta_read;
366
    when "110" =>       -- set low
367
           ca2_out <= '0';
368
    when "111" =>       -- set high
369
           ca2_out <= '1';
370
    when others => -- no change
371
           ca2_out <= ca2_out;
372
    end case;
373
  end if;
374
end process;
375
 
376
 
377
---------------------------------
378
--
379
-- CB1 Edge detect
380
--
381
---------------------------------
382
cb1_input : process( clk, rst, cb1, cb1_del,
383
                     cb1_rise, cb1_fall, cb1_edge,
384
                                                        irqb1, portb_ctrl, portb_read )
385
begin
386
  if rst = '1' then
387
    cb1_del  <= '0';
388
         cb1_rise <= '0';
389
    cb1_fall <= '0';
390
         cb1_edge <= '0';
391
         irqb1    <= '0';
392
  elsif clk'event and clk = '0' then
393
    cb1_del  <= cb1;
394
    cb1_rise <= (not cb1_del) and cb1;
395
    cb1_fall <= cb1_del and (not cb1);
396
         if cb1_edge = '1' then
397
            irqb1 <= '1';
398
         elsif portb_read = '1' then
399
            irqb1 <= '0';
400
    else
401
            irqb1 <= irqb1;
402
    end if;
403
  end if;
404
 
405
  if portb_ctrl(1) = '0' then
406
         cb1_edge <= cb1_fall;
407
  else
408
         cb1_edge <= cb1_rise;
409
  end if;
410
end process;
411
 
412
---------------------------------
413
--
414
-- CB2 Edge detect
415
--
416
---------------------------------
417
cb2_input : process( clk, rst, cb2, cb2_del,
418
                     cb2_rise, cb2_fall, cb2_edge,
419
                                                        irqb2, portb_ctrl, portb_read )
420
begin
421
  if rst = '1' then
422
    cb2_del  <= '0';
423
         cb2_rise <= '0';
424
    cb2_fall <= '0';
425
         cb2_edge <= '0';
426
         irqb2    <= '0';
427
  elsif clk'event and clk = '0' then
428
    cb2_del  <= cb2;
429
    cb2_rise <= (not cb2_del) and cb2;
430
    cb2_fall <= cb2_del and (not cb2);
431
         if portb_ctrl(5) = '0' and cb2_edge = '1' then
432
            irqb2 <= '1';
433
         elsif portb_read = '1' then
434
            irqb2 <= '0';
435
    else
436
            irqb2 <= irqb2;
437
    end if;
438
  end if;
439
 
440
  if portb_ctrl(4) = '0' then
441
         cb2_edge <= cb2_fall;
442
  else
443
         cb2_edge <= cb2_rise;
444
  end if;
445
 
446
end process;
447
 
448
---------------------------------
449
--
450
-- CB2 output control
451
--
452
---------------------------------
453
cb2_output : process( clk, rst, portb_ctrl, portb_write, cb1_edge, cb2_out )
454
begin
455
  if rst='1' then
456
    cb2_out <= '0';
457
  elsif clk'event and clk='0' then
458
    case portb_ctrl(5 downto 3) is
459
    when "100" => -- write PB clears, CA1 edge sets
460
      if portb_write = '1' then
461
             cb2_out <= '0';
462
      elsif cb1_edge = '1' then
463
             cb2_out <= '1';
464
      else
465
             cb2_out <= cb2_out;
466
      end if;
467
    when "101" => -- write PB clears, E sets
468
      cb2_out <= not portb_write;
469
    when "110" =>       -- set low
470
           cb2_out <= '0';
471
    when "111" =>       -- set high
472
           cb2_out <= '1';
473
    when others => -- no change
474
           cb2_out <= cb2_out;
475
    end case;
476
  end if;
477
end process;
478
 
479
---------------------------------
480
--
481
-- IRQ control
482
--
483
---------------------------------
484
pia_irq : process( irqa1, irqa2, irqb1, irqb2, porta_ctrl, portb_ctrl )
485
begin
486
  irqa <= (irqa1 and porta_ctrl(0)) or (irqa2 and porta_ctrl(3));
487
  irqb <= (irqb1 and portb_ctrl(0)) or (irqb2 and portb_ctrl(3));
488
end process;
489
 
490
---------------------------------
491
--
492
-- 2 x 74193 binary down counter
493
--
494
---------------------------------
495
--
496
-- On the reference 6809 board, 
497
-- RTI takes one more clock cycle than System09
498
-- So subtract 1 from the porta_data preset value.
499
-- 11th July 2006 John Kent
500
-- RTI in CPU09 has been extended by one bus cycle
501
-- so remove the subtract by one offset on porta_data
502
--
503
pia_counter : process( clk, timer, porta_data, ca2_out, cb2_out)
504
begin
505
  if cb2_out = '1' then
506
    timer <= "00000000";
507
  elsif ca2_out = '0' then
508
--    timer <= porta_data - "00000001";
509
    timer <= porta_data;
510
  elsif clk'event and clk='1' then
511
    timer <= timer - "00000001";
512
  end if;
513
  pa  <= "00000000";
514
  pb  <= timer;
515
  ca1 <= timer(7);
516
  cb1 <= timer(7);
517
  ca2 <= '0';
518
  cb2 <= '0';
519
end process;
520
 
521
end pia_arch;
522
 

powered by: WebSVN 2.1.0

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