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

Subversion Repositories System09

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

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

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

powered by: WebSVN 2.1.0

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