summaryrefslogtreecommitdiffstats
path: root/zpu/hdl/zealot/devices/phi_io.vhdl
blob: 6e40d1d49519d0f258710c363d01a228e663b592 (plain)
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
------------------------------------------------------------------------------
----                                                                      ----
----  ZPU Phi I/O                                                         ----
----                                                                      ----
----  http://www.opencores.org/                                           ----
----                                                                      ----
----  Description:                                                        ----
----  ZPU is a 32 bits small stack cpu. This is the minimum I/O devices   ----
----  assumed by the libc. They are a timer and an UART.@p                ----
----  Important! this is currently a simulation only model, no UART       ----
----  provided and it unconditionally generates a log.                    ----
----  Important! not all peripherals implemented!                         ----
----  Important! The enable signals assumes this is mapped @ 0x80A00xx.   ----
----                                                                      ----
----  To Do:                                                              ----
----  -                                                                   ----
----                                                                      ----
----  Author:                                                             ----
----    - ōyvind Harboe, oyvind.harboe zylin.com                          ----
----    - Salvador E. Tropea, salvador inti.gob.ar                        ----
----                                                                      ----
------------------------------------------------------------------------------
----                                                                      ----
---- Copyright (c) 2008 ōyvind Harboe <oyvind.harboe zylin.com>           ----
---- Copyright (c) 2008 Salvador E. Tropea <salvador inti.gob.ar>         ----
---- Copyright (c) 2008 Instituto Nacional de TecnologŪa Industrial       ----
----                                                                      ----
---- Distributed under the BSD license                                    ----
----                                                                      ----
------------------------------------------------------------------------------
----                                                                      ----
---- Design unit:      ZPUPhiIO(Behave) (Entity and architecture)         ----
---- File name:        phi_io.vhdl                                        ----
---- Note:             None                                               ----
---- Limitations:      Only for simulation.                               ----
---- Errors:           None known                                         ----
---- Library:          zpu                                                ----
---- Dependencies:     IEEE.std_logic_1164                                ----
----                   IEEE.numeric_std                                   ----
----                   std.textio                                         ----
----                   zpu.zpupkg                                         ----
----                   zpu.txt_util                                       ----
---- Target FPGA:      Spartan 3 (XC3S1500-4-FG456)                       ----
---- Language:         VHDL                                               ----
---- Wishbone:         No                                                 ----
---- Synthesis tools:  N/A                                                ----
---- Simulation tools: GHDL [Sokcho edition] (0.2x)                       ----
---- Text editor:      SETEdit 0.5.x                                      ----
----                                                                      ----
------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

use std.textio.all;

library zpu;
use zpu.zpupkg.timer;
use zpu.zpupkg.gpio;
use zpu.UART.all;
use zpu.txt_util.all;
 
entity ZPUPhiIO is
   generic(
      BRDIVISOR : positive:=1;   -- Baud rate divisor i.e. br_clk/9600/4
      ENA_LOG   : boolean:=true; -- Enable log
      LOG_FILE  : string:="log.txt"); -- Name for the log file
   port(
      clk_i      : in  std_logic; -- System Clock
      reset_i    : in  std_logic; -- Synchronous Reset
      busy_o     : out std_logic; -- I/O is busy
      we_i       : in  std_logic; -- Write Enable
      re_i       : in  std_logic; -- Read Enable
      data_i     : in  unsigned(31 downto 0);
      data_o     : out unsigned(31 downto 0);
      addr_i     : in  unsigned(2  downto 0); -- Address bits 4-2
      --
      rs232_rx_i : in  std_logic;  -- UART Rx input
      rs232_tx_o : out std_logic;  -- UART Tx output
      br_clk_i   : in  std_logic;  -- UART base clock (enable)
      --
      gpio_in    : in  std_logic_vector(31 downto 0);
      gpio_out   : out std_logic_vector(31 downto 0);
      gpio_dir   : out std_logic_vector(31 downto 0)  -- 1 = in, 0 = out
      );
end entity ZPUPhiIO;
   
   
architecture Behave of ZPUPhiIO is
   constant LOW_BITS  : unsigned(1 downto 0):=(others=>'0');
   constant TX_FULL   : std_logic:='0';
   constant RX_EMPTY  : std_logic:='1';

   -- "000" 0x00 is CPU enable ... useful?
   constant IO_DATA   : unsigned(2 downto 0):="001"; -- 0x04
   constant IO_DIR    : unsigned(2 downto 0):="010"; -- 0x08
   constant UART_TX   : unsigned(2 downto 0):="011"; -- 0x0C
   constant UART_RX   : unsigned(2 downto 0):="100"; -- 0x10
   constant CNT_1     : unsigned(2 downto 0):="101"; -- 0x14
   constant CNT_2     : unsigned(2 downto 0):="110"; -- 0x18
   -- "111" 0x1C Unused
   -- Unimplemented: Interrupt control and timer (not counter ...?)

   signal timer_read : unsigned(31 downto 0);
   signal timer_we   : std_logic;
   signal is_timer   : std_logic;

   -- UART
   -- Rx
   signal rx_br      : std_logic; -- Rx timing
   signal uart_read  : std_logic; -- ZPU read the value
   signal rx_avail   : std_logic; -- Rx data available
   signal rx_data    : std_logic_vector(7 downto 0); -- Rx data
   -- Tx
   signal tx_br      : std_logic; -- Tx timing
   signal uart_write : std_logic; -- ZPU is writing
   signal tx_busy    : std_logic; -- Tx can't get a new value

   -- GPIO
   signal gpio_we    : std_logic;
   signal is_gpio    : std_logic;
   signal gpio_read  : unsigned(31 downto 0);

   file l_file       : text open write_mode is LOG_FILE;

begin
   -----------
   -- Timer --
   -----------
   timerinst: Timer
      port map(
         clk_i => clk_i, reset_i => reset_i, we_i => timer_we,
         data_i => data_i, addr_i => addr_i(1 downto 1),
         data_o => timer_read);
   
   busy_o   <= we_i or re_i;
   is_timer <= '1' when to_01(addr_i)=CNT_1 or to_01(addr_i)=CNT_2 else '0'; -- 0x80A0014/8
   timer_we <= we_i and is_timer;

   ----------
   -- UART --
   ----------
   -- Rx section
   rx_core : RxUnit
      port map(
         clk_i => clk_i, reset_i => reset_i, enable_i => rx_br,
         read_i => uart_read, rxd_i => rs232_rx_i, rxav_o => rx_avail,
         datao_o => rx_data);
   uart_read <= '1' when re_i='1' and addr_i=UART_RX else '0';

   -- Tx section
   tx_core : TxUnit
      port map(
         clk_i => clk_i, reset_i => reset_i, enable_i => tx_br,
         load_i => uart_write, txd_o => rs232_tx_o, busy_o => tx_busy,
         datai_i => std_logic_vector(data_i(7 downto 0)));
   uart_write <= '1' when we_i='1' and addr_i=UART_TX else '0';

   -- Rx timing
   rx_timer : BRGen
      generic map(COUNT => BRDIVISOR)
      port map(
         clk_i => clk_i, reset_i => reset_i, ce_i => br_clk_i, o_o => rx_br);

   -- Tx timing
   tx_timer : BRGen -- 4 Divider for Tx
      generic map(COUNT => 4)  
      port map(
         clk_i => clk_i, reset_i => reset_i, ce_i => rx_br, o_o => tx_br);
   
   ----------
   -- GPIO --
   ----------
   gpio_i0: gpio
      port map(
          clk_i    => clk_i,              -- : in  std_logic;
          reset_i  => reset_i,            -- : in  std_logic;
          --                              
          we_i     => gpio_we,            -- : in  std_logic;
          data_i   => data_i,             -- : in  unsigned(31 downto 0);
          addr_i   => addr_i(1 downto 1), -- : in  unsigned( 0 downto 0);
          data_o   => gpio_read,          -- : out unsigned(31 downto 0);
          --                              
          port_in  => gpio_in,            -- : std_logic_vector(31 downto 0);
          port_out => gpio_out,           -- : std_logic_vector(31 downto 0);
          port_dir => gpio_dir            -- : std_logic_vector(31 downto 0);
          );
   is_gpio <= '1' when to_01(addr_i) = IO_DATA or to_01(addr_i) = IO_DIR else '0'; -- 0x80A0004/8
   gpio_we <= we_i and is_gpio;


   do_io:
   process(clk_i)
        --synopsys translate off
        variable line_out : line := new string'("");
        variable char     : character;
        --synopsys translate on
   begin
      if rising_edge(clk_i) then
         if reset_i/='1' then
            --synopsys translate off
            if we_i='1' then
               if addr_i=UART_TX and ENA_LOG then -- 0x80a000c
                  -- Write to UART
                  print("- Write to UART Tx: 0x" &hstr(data_i)&" ("&
                        character'val(to_integer(data_i) mod 256)&")");
                    char := character'val(to_integer(data_i));
                    if char = lf then
                        std.textio.writeline(l_file, line_out);
                    else
                        std.textio.write(line_out, char);
                    end if;
               elsif is_gpio = '1' and ENA_LOG then
                  print("- Write GPIO: 0x" & hstr(data_i));
               elsif is_timer='1' and ENA_LOG then
                  print("- Write to TIMER: 0x" & hstr(data_i));
               else
                  --print(l_file,character'val(to_integer(data_i)));
                  report "Illegal IO data_i=0x"&hstr(data_i)&" @0x"&
                     hstr(x"80a00"&"000"&addr_i&"00") severity warning;
               end if;
            end if;
            --synopsys translate on
            data_o <= (others => '0');
            if re_i='1' then
               if is_gpio = '1' then
                  if ENA_LOG then
                     print("- Read  GPIO: 0x" & hstr(gpio_read));
                  end if;
                  data_o <= gpio_read;
               elsif addr_i=UART_TX then
                  if ENA_LOG then
                     print("- Read UART Tx");
                  end if;
                  data_o(8) <= not(tx_busy); -- output fifo not full
               elsif addr_i=UART_RX then
                  if ENA_LOG then
                     print("- Read UART Rx");
                  end if;
                  data_o(8) <= rx_avail; -- receiver not empty
                  data_o(7 downto 0) <= unsigned(rx_data);
               elsif is_timer='1' then
                  if ENA_LOG then
                     print("- Read TIMER: 0x" & hstr(timer_read));
                  end if;
                  data_o <= timer_read;
               else
                  report "Illegal IO data_o @0x"&
                     hstr(x"80a00"&"000"&addr_i&"00") severity warning;
               end if;
            end if; -- re_i='1'
         end if; -- reset_i/='1'
      end if; -- rising_edge(clk_i)
   end process do_io;
end Behave;
 
OpenPOWER on IntegriCloud