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
|
------------------------------------------------------------------------------
---- ----
---- 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.all;
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)
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?
-- "001" 0x04 Unused
-- "010" 0x08 Unused
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
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 addr_i=CNT_1 or 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);
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_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 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;
|