summaryrefslogtreecommitdiffstats
path: root/misc/arm7/src/arm7wb.vhd
blob: 33663527f76904a334c50f845609c61048533691 (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
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library work;
use work.phi_config.all;
use work.wishbone_pkg.all;

entity arm7wb is
	generic(
			simulate_io_time	: boolean := false);
	port (	areset			: in std_logic;
			cpu_clk			: in std_logic;
			cpu_clk_2x		: in std_logic;
			cpu_a_p			: in std_logic_vector(23 downto 1);
			cpu_wr_n_p		: in std_logic_vector(1 downto 0);
			cpu_cs_n_p		: in std_logic_vector(3 downto 1);
			cpu_oe_n_p		: in std_logic;
			cpu_d_p			: inout std_logic_vector(15 downto 0);
			cpu_wait_n_p	: out std_logic;

			arm7_debug		: out std_logic;
			arm7_debug2		: out std_logic;

			wb_o			: out wishbone_bus_in;
			wb_i            : in wishbone_bus_out);			
end arm7wb;
			
architecture behave of arm7wb is

type	cpu_state_type		is (cpu_idle, cpu_cs, cpu_end);

-- Input simulated delay
signal	cpu_wr_n_p_del		: std_logic_vector(1 downto 0);
signal 	cpu_a_p_del			: std_logic_vector(23 downto 1);
signal	cpu_d_p_del			: std_logic_vector(15 downto 0);
signal	cpu_cs_n_p_del		: std_logic_vector(3 downto 1);
signal	cpu_oe_n_p_del		: std_logic;

-- Clock phase detect signals
signal	cpu_clk_toggle		: std_logic;
signal	cpu_clk_smp1		: std_logic;
signal	cpu_clk_smp2		: std_logic;
signal	cpu_clk_phase		: std_logic;

-- Internal version of control signal (for feedback)
signal	arm7_din_int		: std_logic_vector(15 downto 0);
signal	arm7_dout_int		: std_logic_vector(15 downto 0);
signal	arm7_a_int			: std_logic_vector(23 downto 1);
signal	arm7_we_int			: std_logic_vector(1 downto 0);
signal  cyc_int             : std_logic;
signal	we_int				: std_logic;
signal  adr_reg             : std_logic_vector(25 downto 24);

-- Input sampled
signal	cpu_a_smp			: std_logic_vector(23 downto 1);
signal	cpu_d_smp			: std_logic_vector(15 downto 0);
signal	cpu_cs_n 			: std_logic_vector(3 downto 1);
signal	cpu_oe_n			: std_logic;
signal	cpu_wr_n 			: std_logic_vector(1 downto 0);

-- Main FSM
signal	cpu_state			: cpu_state_type;

constant	Clock_2_Out	: time := 5.5 ns;
constant	Input_Setup	: time := 2.5 ns;

begin

	arm7_dout_int <= wb_i.dat(15 downto 0) when (arm7_a_int(1) = '0') else wb_i.dat(31 downto 16);
	arm7_debug <= cpu_oe_n;
	arm7_debug2 <= cpu_wr_n(0);

	-- Generate 64 MBytes address based on 3 CS_N signals from CPU
	-- Memory map FPGA internal
	--  0x00000000 DDR 32 MBytes (CS_N2 and CS_N3)
	--  0x00200000 FPGA/Ethernet (CS_N1)
	wb_o.adr(31 downto 26) <= "000000";
	wb_o.adr(25 downto 24) <= adr_reg;
	wb_o.adr(23 downto 1) <= arm7_a_int(23 downto 1);
	wb_o.adr(0) <= '0';
	
	wb_o.dat <= (x"0000" & arm7_din_int) when (arm7_a_int(1) = '0') else (arm7_din_int & x"0000");
	wb_o.sel <= ("00" & arm7_we_int) when (arm7_a_int(1) = '0') else (arm7_we_int & "00");	
	
	wb_o.cyc <= cyc_int;
	wb_o.stb <= cyc_int;
	wb_o.we <= cpu_oe_n;

	iotimingon:
	if simulate_io_time generate
	begin
		cpu_wr_n_p_del <= transport "XX" after 0 ns, cpu_wr_n_p after Input_Setup;
		cpu_a_p_del <= transport "XXXXXXXXXXXXXXXXXXXXXXX" after 0 ns, cpu_a_p after Input_Setup;
		cpu_d_p_del <= transport "XXXXXXXXXXXXXXXX" after 0 ns, cpu_d_p after Input_Setup;
		cpu_cs_n_p_del <= transport "XXX" after 0 ns, cpu_cs_n_p after Input_Setup;
		cpu_oe_n_p_del <= transport 'X' after 0 ns, cpu_oe_n_p after Input_Setup;
	end generate;
	
	iotimingoff:
	if not simulate_io_time generate
	begin
		cpu_wr_n_p_del <= cpu_wr_n_p;
		cpu_a_p_del <=  cpu_a_p;
		cpu_d_p_del <= cpu_d_p;
		cpu_cs_n_p_del <= cpu_cs_n_p;
		cpu_oe_n_p_del <= cpu_oe_n_p;
	end generate;
	
	process(cpu_clk, areset)	-- Toggle FF with 1x clock to find phase
	begin
		if areset = '1' then
			cpu_clk_toggle <= '0';
		elsif (cpu_clk'event and cpu_clk = '1') then
			cpu_clk_toggle <= not(cpu_clk_toggle);
		end if;
	end process;
	
	process(cpu_clk_2x, areset)	-- Find phase relationsship between 1x and 2x clock
	begin
		if areset = '1' then
			cpu_clk_smp1 <= '0';
			cpu_clk_smp2 <= '1';
			cpu_clk_phase <= '0';
		elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
			cpu_clk_smp1 <= cpu_clk_toggle;
			cpu_clk_smp2 <= cpu_clk_smp1;
			if cpu_clk_smp1 = '1' and cpu_clk_smp2 = '0' then
				cpu_clk_phase <= '0';
			else
				cpu_clk_phase <= not(cpu_clk_phase);
			end if;
		end if;
	end process;
	
	process(cpu_clk_2x, areset)	-- Sample input signals on 2x clock
	begin
		if areset = '1' then
			cpu_d_smp <= "0000000000000000";
			cpu_cs_n <= "111";
		elsif (cpu_clk_2x = '1' and cpu_clk_2x'event) then
			cpu_d_smp <= cpu_d_p_del;
			cpu_cs_n <= cpu_cs_n_p_del;
		end if;
	end process;

	process(cpu_clk, areset)	-- Sample input signals on 1x clock
	begin
		if areset = '1' then
			cpu_a_smp <= "00000000000000000000000";
			cpu_oe_n <= '1';
			cpu_wr_n <= "11";
		elsif (cpu_clk = '1' and cpu_clk'event) then
			cpu_a_smp <= cpu_a_p_del;
			cpu_oe_n <= cpu_oe_n_p_del;
			cpu_wr_n <= cpu_wr_n_p_del;
		end if;
	end process;

	arm7_din_int <= cpu_d_smp;
	arm7_a_int <= cpu_a_smp;
	arm7_we_int <= not(cpu_wr_n);
	
	process(cpu_clk, areset)
	begin
		if areset = '1' then
			cpu_state <= cpu_idle;
			cyc_int <= '0';
			we_int <= '0';
			adr_reg <= "00";
			cpu_d_p	<= (others => 'Z');
		elsif (cpu_clk'event and cpu_clk = '1') then
			
			cyc_int <= '0';
			we_int <= '0';
			cpu_d_p	<= (others => 'Z') after Clock_2_Out;
			
			
			case cpu_state is
			
				when cpu_idle =>
					if cpu_oe_n = '1' then
						we_int <= '1';
					end if;
					if cpu_cs_n(1) = '0' then
						cyc_int <= '1';
						adr_reg <= "10";
						cpu_state <= cpu_cs;
					end if;
					if cpu_cs_n(2) = '0' then
						cyc_int <= '1';
						adr_reg <= "00";
						cpu_state <= cpu_cs;
					end if;
					if cpu_cs_n(3) = '0' then
						cyc_int <= '1';
						adr_reg <= "01";
						cpu_state <= cpu_cs;
					end if;
					
				when cpu_cs =>
					if cpu_oe_n = '0' then
						cpu_d_p <= arm7_dout_int after Clock_2_Out;
						if wb_i.ack = '1' then
							cpu_state <= cpu_end;
						else
							cyc_int <= '1';
						end if;
					else
						if wb_i.ack = '0' then
							cyc_int <= '1';
							we_int <= '1';
						else
							cpu_state <= cpu_end;
						end if;
					end if;
						
				when others =>
					cpu_state <= cpu_idle;

			end case;
		end if;
	end process;
	
	process(cpu_clk_2x, areset)
	begin
		if areset = '1' then
			cpu_wait_n_p <= '1';
		elsif (cpu_clk_2x'event and cpu_clk_2x = '1') then
			cpu_wait_n_p <= '1' after Clock_2_Out;
			if (cpu_state = cpu_cs and wb_i.ack = '0') then
			   	cpu_wait_n_p <= '0' after Clock_2_Out;
			end if;
		end if;
	end process;
	
end behave;			
OpenPOWER on IntegriCloud