1 |
2 |
tarookumic |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
----------------------------------------------------------------------------
|
6 |
|
|
-- This file is a part of the LEON VHDL model
|
7 |
|
|
-- Copyright (C) 1999 European Space Agency (ESA)
|
8 |
|
|
--
|
9 |
|
|
-- This library is free software; you can redistribute it and/or
|
10 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
11 |
|
|
-- License as published by the Free Software Foundation; either
|
12 |
|
|
-- version 2 of the License, or (at your option) any later version.
|
13 |
|
|
--
|
14 |
|
|
-- See the file COPYING.LGPL for the full details of the license.
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
-----------------------------------------------------------------------------
|
18 |
|
|
-- Entity: ioport
|
19 |
|
|
-- File: ioport.vhd
|
20 |
|
|
-- Author: Jiri Gaisler - Gaisler Research
|
21 |
|
|
-- Description: Parallel I/O port. On reset, all port are programmed as
|
22 |
|
|
-- inputs and remaning registers are unknown. This means
|
23 |
|
|
-- that the interrupt configuration registers must be
|
24 |
|
|
-- written before I/O port interrputs are unmasked in the
|
25 |
|
|
-- interrupt controller.
|
26 |
|
|
------------------------------------------------------------------------------
|
27 |
|
|
|
28 |
|
|
library IEEE;
|
29 |
|
|
use IEEE.std_logic_1164.all;
|
30 |
|
|
use IEEE.std_logic_signed."-";
|
31 |
|
|
use work.leon_config.all;
|
32 |
|
|
use work.peri_serial_comp.all;
|
33 |
|
|
use work.peri_io_comp.all;
|
34 |
|
|
use work.macro.genmux;
|
35 |
|
|
use work.amba.all;
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
entity ioport is
|
39 |
|
|
port (
|
40 |
|
|
rst : in std_logic;
|
41 |
|
|
clk : in std_logic;
|
42 |
|
|
apbi : in apb_slv_in_type;
|
43 |
|
|
apbo : out apb_slv_out_type;
|
44 |
|
|
uart1o : in uart_out_type;
|
45 |
|
|
uart2o : in uart_out_type;
|
46 |
|
|
mctrlo_pioh : in std_logic_vector(15 downto 0);
|
47 |
|
|
ioi : in io_in_type;
|
48 |
|
|
pioo : out pio_out_type
|
49 |
|
|
);
|
50 |
|
|
end;
|
51 |
|
|
|
52 |
|
|
architecture rtl of ioport is
|
53 |
|
|
|
54 |
|
|
constant ISELLEN : integer := 5;
|
55 |
|
|
type irq_ctrl_type is record
|
56 |
|
|
isel : std_logic_vector(ISELLEN-1 downto 0);
|
57 |
|
|
pol : std_logic;
|
58 |
|
|
edge : std_logic;
|
59 |
|
|
enable : std_logic;
|
60 |
|
|
end record;
|
61 |
|
|
|
62 |
|
|
type irq_conf_type is array (3 downto 0) of irq_ctrl_type;
|
63 |
|
|
|
64 |
|
|
type pioregs is record
|
65 |
|
|
irqout : std_logic_vector(3 downto 0);
|
66 |
|
|
irqlat : std_logic_vector(3 downto 0);
|
67 |
|
|
pin1 : std_logic_vector(15 downto 0);
|
68 |
|
|
pin2 : std_logic_vector(31 downto 0);
|
69 |
|
|
pdir : std_logic_vector(17 downto 0);
|
70 |
|
|
pout : std_logic_vector(15 downto 0);
|
71 |
|
|
iconf : irq_conf_type;
|
72 |
|
|
end record;
|
73 |
|
|
|
74 |
|
|
signal r, rin : pioregs;
|
75 |
|
|
|
76 |
|
|
begin
|
77 |
|
|
|
78 |
|
|
pioop : process(rst, r, apbi, mctrlo_pioh, ioi, uart1o, uart2o)
|
79 |
|
|
variable rdata : std_logic_vector(31 downto 0);
|
80 |
|
|
variable v : pioregs;
|
81 |
|
|
variable wrio : std_logic;
|
82 |
|
|
begin
|
83 |
|
|
|
84 |
|
|
v := r; wrio := '0';
|
85 |
|
|
|
86 |
|
|
-- synchronise port inputs. Low 16 bits are latched twice while high 16 bits
|
87 |
|
|
-- are allready latched once in the memory controller and therefore only
|
88 |
|
|
-- latched once here.
|
89 |
|
|
|
90 |
|
|
v.pin1 := ioi.piol; v.pin2 := mctrlo_pioh & r.pin1;
|
91 |
|
|
|
92 |
|
|
-- read/write registers
|
93 |
|
|
|
94 |
|
|
rdata := (others => '0');
|
95 |
|
|
case apbi.paddr(3 downto 2) is
|
96 |
|
|
when "00" => rdata(31 downto 0) := r.pin2;
|
97 |
|
|
when "01" => rdata(17 downto 0) := not r.pdir;
|
98 |
|
|
when "10" => rdata(31 downto 0) :=
|
99 |
|
|
r.iconf(3).enable & r.iconf(3).edge & r.iconf(3).pol & r.iconf(3).isel &
|
100 |
|
|
r.iconf(2).enable & r.iconf(2).edge & r.iconf(2).pol & r.iconf(2).isel &
|
101 |
|
|
r.iconf(1).enable & r.iconf(1).edge & r.iconf(1).pol & r.iconf(1).isel &
|
102 |
|
|
r.iconf(0).enable & r.iconf(0).edge & r.iconf(0).pol & r.iconf(0).isel;
|
103 |
|
|
when others => rdata := (others => '-');
|
104 |
|
|
end case;
|
105 |
|
|
|
106 |
|
|
if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then
|
107 |
|
|
case apbi.paddr(3 downto 2) is
|
108 |
|
|
when "00" => v.pout := apbi.pwdata(15 downto 0); wrio := '1';
|
109 |
|
|
when "01" => v.pdir := not apbi.pwdata(17 downto 0);
|
110 |
|
|
when "10" =>
|
111 |
|
|
v.iconf(3).enable := apbi.pwdata(31); v.iconf(3).edge := apbi.pwdata(30);
|
112 |
|
|
v.iconf(3).pol := apbi.pwdata(29); v.iconf(3).isel := apbi.pwdata(28 downto 24);
|
113 |
|
|
v.iconf(2).enable := apbi.pwdata(23); v.iconf(2).edge := apbi.pwdata(22);
|
114 |
|
|
v.iconf(2).pol := apbi.pwdata(21); v.iconf(2).isel := apbi.pwdata(20 downto 16);
|
115 |
|
|
v.iconf(1).enable := apbi.pwdata(15); v.iconf(1).edge := apbi.pwdata(14);
|
116 |
|
|
v.iconf(1).pol := apbi.pwdata(13); v.iconf(1).isel := apbi.pwdata(12 downto 8);
|
117 |
|
|
v.iconf(0).enable := apbi.pwdata(7); v.iconf(0).edge := apbi.pwdata(6);
|
118 |
|
|
v.iconf(0).pol := apbi.pwdata(5); v.iconf(0).isel := apbi.pwdata(4 downto 0);
|
119 |
|
|
when others => null;
|
120 |
|
|
end case;
|
121 |
|
|
end if;
|
122 |
|
|
|
123 |
|
|
-- override I/O port settings if UARTs are enabled
|
124 |
|
|
if uart1o.txen = '1' then v.pout(15) := uart1o.txd; end if;
|
125 |
|
|
if uart1o.flow = '1' then v.pout(13) := uart1o.rtsn; end if;
|
126 |
|
|
if uart2o.txen = '1' then v.pout(11) := uart2o.txd; end if;
|
127 |
|
|
if uart2o.flow = '1' then v.pout(9) := uart2o.rtsn; end if;
|
128 |
|
|
|
129 |
|
|
-- interrupt generation
|
130 |
|
|
|
131 |
|
|
for i in 0 to 3 loop -- select and latch interrupt source
|
132 |
|
|
v.irqlat(i) := genmux(r.iconf(i).isel, r.pin2);
|
133 |
|
|
|
134 |
|
|
if r.iconf(i).enable = '1' then
|
135 |
|
|
if r.iconf(i).edge = '1' then
|
136 |
|
|
v.irqout(i) := (v.irqlat(i) xor r.irqlat(i)) and
|
137 |
|
|
(v.irqlat(i) xor not r.iconf(i).pol);
|
138 |
|
|
else
|
139 |
|
|
v.irqout(i) := (v.irqlat(i) xor not r.iconf(i).pol);
|
140 |
|
|
end if;
|
141 |
|
|
else
|
142 |
|
|
v.irqout(i) := '0';
|
143 |
|
|
end if;
|
144 |
|
|
end loop;
|
145 |
|
|
|
146 |
|
|
-- reset operation
|
147 |
|
|
|
148 |
|
|
if rst = '0' then
|
149 |
|
|
v.pdir := (others => '1');
|
150 |
|
|
v.iconf(0).enable := '0'; v.iconf(1).enable := '0';
|
151 |
|
|
v.iconf(2).enable := '0'; v.iconf(3).enable := '0';
|
152 |
|
|
end if;
|
153 |
|
|
|
154 |
|
|
-- drive signals
|
155 |
|
|
|
156 |
|
|
rin <= v; -- update registers
|
157 |
|
|
apbo.prdata <= rdata; -- drive data bus
|
158 |
|
|
pioo.irq <= r.irqout;
|
159 |
|
|
pioo.piodir <= r.pdir;
|
160 |
|
|
pioo.io8lsb <= r.pin2(7 downto 0);
|
161 |
|
|
pioo.rxd(0) <= r.pin2(14);
|
162 |
|
|
pioo.ctsn(0) <= r.pin2(12);
|
163 |
|
|
pioo.rxd(1) <= r.pin2(10);
|
164 |
|
|
pioo.ctsn(1) <= r.pin2(8);
|
165 |
|
|
pioo.piol <= apbi.pwdata(31 downto 16) & r.pout(15 downto 0);
|
166 |
|
|
pioo.wrio <= wrio;
|
167 |
|
|
|
168 |
|
|
end process;
|
169 |
|
|
|
170 |
|
|
-- registers
|
171 |
|
|
|
172 |
|
|
regs : process(clk,rst)
|
173 |
|
|
begin
|
174 |
|
|
if rising_edge(clk) then r <= rin; end if;
|
175 |
|
|
if rst = '0' then r.pdir <= (others => '1'); end if;
|
176 |
|
|
end process;
|
177 |
|
|
|
178 |
|
|
|
179 |
|
|
end;
|