1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : Initialization module
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : DM9kA_init_module.vhd
|
6 |
|
|
-- Author : Jussi Nieminen
|
7 |
|
|
-- Company :
|
8 |
|
|
-- Last update: 2012-04-04
|
9 |
|
|
-- Platform :
|
10 |
|
|
-------------------------------------------------------------------------------
|
11 |
|
|
-- Description: Initializes DM9kA. Includes two state machines.
|
12 |
|
|
-------------------------------------------------------------------------------
|
13 |
|
|
-- Revisions :
|
14 |
|
|
-- Date Version Author Description
|
15 |
|
|
-- 2009/08/24 1.0 niemin95 Created
|
16 |
|
|
-------------------------------------------------------------------------------
|
17 |
|
|
|
18 |
|
|
library ieee;
|
19 |
|
|
use ieee.std_logic_1164.all;
|
20 |
|
|
use ieee.numeric_std.all;
|
21 |
|
|
|
22 |
|
|
-- constants
|
23 |
|
|
use work.DM9kA_ctrl_pkg.all;
|
24 |
|
|
|
25 |
|
|
|
26 |
|
|
entity DM9kA_init_module is
|
27 |
|
|
|
28 |
|
|
port (
|
29 |
|
|
clk : in std_logic;
|
30 |
|
|
rst_n : in std_logic;
|
31 |
|
|
ready_out : out std_logic;
|
32 |
|
|
sleep_time_out : out std_logic_vector(sleep_time_w_c-1 downto 0);
|
33 |
|
|
reg_addr_out : out std_logic_vector(7 downto 0);
|
34 |
|
|
config_data_out : out std_logic_vector(7 downto 0);
|
35 |
|
|
read_not_write_out : out std_logic;
|
36 |
|
|
config_valid_out : out std_logic;
|
37 |
|
|
data_from_comm_in : in std_logic_vector(data_width_c-1 downto 0);
|
38 |
|
|
data_from_comm_valid_in : in std_logic;
|
39 |
|
|
comm_busy_in : in std_logic
|
40 |
|
|
);
|
41 |
|
|
|
42 |
|
|
end DM9kA_init_module;
|
43 |
|
|
|
44 |
|
|
|
45 |
|
|
architecture rtl of DM9kA_init_module is
|
46 |
|
|
|
47 |
|
|
type init_table_type is record
|
48 |
|
|
addr : std_logic_vector(7 downto 0);
|
49 |
|
|
value : std_logic_vector(7 downto 0);
|
50 |
|
|
writing : std_logic;
|
51 |
|
|
sleep_time : integer;
|
52 |
|
|
end record;
|
53 |
|
|
|
54 |
|
|
constant init_values_c : integer := 24;
|
55 |
|
|
type init_table_array is array (0 to init_values_c-1) of init_table_type;
|
56 |
|
|
|
57 |
|
|
constant init_table_c : init_table_array := (
|
58 |
|
|
(GPCR_c, x"01", '1', 0), -- 1
|
59 |
|
|
(GPR_c, x"00", '1', power_up_sleep_c), -- power up PHY
|
60 |
|
|
(NCR_c, x"03", '1', 500), -- software reset
|
61 |
|
|
(NCR_c, x"00", '1', 0),
|
62 |
|
|
(GPR_c, x"01", '1', 0), -- shut down PHY, and start it once again
|
63 |
|
|
(GPR_c, x"00", '1', 2*power_up_sleep_c), -- don't know why, but it must be done
|
64 |
|
|
(ISR_c, x"3F", '1', 0), -- 16bit mode + reseting status
|
65 |
|
|
(NSR_c, x"2C", '1', 0), -- 10 reset NSR
|
66 |
|
|
(NCR_c, x"00", '1', 0),
|
67 |
|
|
|
68 |
|
|
(MAC1_c, MAC_addr_c(47 downto 40), '1', 0), -- write MAC address
|
69 |
|
|
(MAC2_c, MAC_addr_c(39 downto 32), '1', 0),
|
70 |
|
|
(MAC3_c, MAC_addr_c(31 downto 24), '1', 0),
|
71 |
|
|
(MAC4_c, MAC_addr_c(23 downto 16), '1', 0),
|
72 |
|
|
(MAC5_c, MAC_addr_c(15 downto 8), '1', 0),
|
73 |
|
|
(MAC6_c, MAC_addr_c(7 downto 0), '1', 0),
|
74 |
|
|
|
75 |
|
|
(BPTR_c, x"3F", '1', 0), -- send 600 us jam pattern when 3k left in RxRAM
|
76 |
|
|
(FCTR_c, x"5A", '1', 0), -- High/low water overflow thresholds
|
77 |
|
|
(FCR_c, x"29", '1', 0), -- 20 flow cntrl
|
78 |
|
|
(WUCR_r, x"00", '1', 0), -- wake up control (all wake up stuff disabled)
|
79 |
|
|
(TCR2_c, x"80", '1', 0), -- led mode 1
|
80 |
|
|
(ETXCSR_c, x"83", '1', 0), -- early transmit OFF.
|
81 |
|
|
(IMR_c, x"83", '1', 0), -- interrupt masks, allow rx and tx interrupts
|
82 |
|
|
(RCR_c, x"39", '1', 0), -- discard error/too long packets, enable rx
|
83 |
|
|
(NSR_c, x"00", '0', 0)); -- 26 test read, bit 6 is link status
|
84 |
|
|
|
85 |
|
|
signal init_cnt_r : integer range 0 to init_values_c - 1;
|
86 |
|
|
signal ready_r : std_logic;
|
87 |
|
|
signal data_from_comm_r : std_logic_vector(data_width_c-1 downto 0);
|
88 |
|
|
|
89 |
|
|
type init_state_type is (start, read_data, wait_busy, wait_link_up);
|
90 |
|
|
signal state_r : init_state_type;
|
91 |
|
|
|
92 |
|
|
signal reset_sleep_cnt_r : integer range 0 to reset_sleep_c;
|
93 |
|
|
|
94 |
|
|
-- 1 second with 25MHz (yes, it's really necessary)
|
95 |
|
|
constant link_wait_time_c : integer := 25_000_000;
|
96 |
|
|
--constant link_wait_time_c : integer := 250; -- ES simulation only!!!
|
97 |
|
|
|
98 |
|
|
type wait_link_type is (send_query, wait_reply, idle);
|
99 |
|
|
signal wait_link_state_r : wait_link_type;
|
100 |
|
|
signal wait_link_cnt_r : integer range 0 to link_wait_time_c;
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
-- how many seconds we wait until we are ready
|
104 |
|
|
-- **************************************************************************
|
105 |
|
|
-- * Okay, this might seem a bit weird thing to do (wait n seconds even after
|
106 |
|
|
-- * the DM9kA tells us that it's link is up), but there's a reason to it.
|
107 |
|
|
-- * When testing this block I noticed, that the PC on the other end needed
|
108 |
|
|
-- * some time too to figure out that there is someone who might want to send
|
109 |
|
|
-- * something. So if we start sending right after the DM9kA is ready, the PC
|
110 |
|
|
-- * might not be ready to receive it.
|
111 |
|
|
-- **************************************************************************
|
112 |
|
|
constant continue_times_c : integer := 5;
|
113 |
|
|
signal continue_r : integer range 0 to continue_times_c;
|
114 |
|
|
|
115 |
|
|
|
116 |
|
|
-------------------------------------------------------------------------------
|
117 |
|
|
begin -- rtl
|
118 |
|
|
-------------------------------------------------------------------------------
|
119 |
|
|
|
120 |
|
|
ready_out <= ready_r;
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
--
|
124 |
|
|
-- Sequential process for state machine
|
125 |
|
|
--
|
126 |
|
|
init : process (clk, rst_n)
|
127 |
|
|
begin -- process init
|
128 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
129 |
|
|
|
130 |
|
|
ready_r <= '0';
|
131 |
|
|
init_cnt_r <= 0;
|
132 |
|
|
data_from_comm_r <= (others => '0');
|
133 |
|
|
reset_sleep_cnt_r <= 0;
|
134 |
|
|
wait_link_cnt_r <= 0;
|
135 |
|
|
continue_r <= 0;
|
136 |
|
|
sleep_time_out <= (others => '0');
|
137 |
|
|
reg_addr_out <= (others => '0');
|
138 |
|
|
config_data_out <= (others => '0');
|
139 |
|
|
read_not_write_out <= '0';
|
140 |
|
|
config_valid_out <= '0';
|
141 |
|
|
state_r <= start;
|
142 |
|
|
wait_link_state_r <= send_query;
|
143 |
|
|
|
144 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
145 |
|
|
|
146 |
|
|
if reset_sleep_cnt_r /= reset_sleep_c then
|
147 |
|
|
-- sleep for a while after reset release
|
148 |
|
|
reset_sleep_cnt_r <= reset_sleep_cnt_r + 1;
|
149 |
|
|
|
150 |
|
|
elsif ready_r = '0' then
|
151 |
|
|
|
152 |
|
|
case state_r is
|
153 |
|
|
when start =>
|
154 |
|
|
|
155 |
|
|
reg_addr_out <= init_table_c(init_cnt_r).addr;
|
156 |
|
|
config_data_out <= init_table_c(init_cnt_r).value;
|
157 |
|
|
read_not_write_out <= not init_table_c(init_cnt_r).writing;
|
158 |
|
|
sleep_time_out <= std_logic_vector(to_unsigned(init_table_c(init_cnt_r).sleep_time, sleep_time_w_c));
|
159 |
|
|
config_valid_out <= '1';
|
160 |
|
|
|
161 |
|
|
-- change state once busy is up (comm is working)
|
162 |
|
|
if comm_busy_in = '1' then
|
163 |
|
|
if init_table_c(init_cnt_r).writing = '0' then
|
164 |
|
|
state_r <= read_data;
|
165 |
|
|
else
|
166 |
|
|
state_r <= wait_busy;
|
167 |
|
|
end if;
|
168 |
|
|
end if;
|
169 |
|
|
|
170 |
|
|
when read_data =>
|
171 |
|
|
|
172 |
|
|
-- reading is quite useless at the moment, but for example some
|
173 |
|
|
-- registers can be cleared by reading if necessary
|
174 |
|
|
if data_from_comm_valid_in = '1' then
|
175 |
|
|
data_from_comm_r <= data_from_comm_in;
|
176 |
|
|
state_r <= wait_busy;
|
177 |
|
|
end if;
|
178 |
|
|
|
179 |
|
|
when wait_busy =>
|
180 |
|
|
|
181 |
|
|
if comm_busy_in = '0' then
|
182 |
|
|
config_valid_out <= '0';
|
183 |
|
|
|
184 |
|
|
if init_cnt_r = init_values_c-1 then
|
185 |
|
|
state_r <= wait_link_up;
|
186 |
|
|
else
|
187 |
|
|
init_cnt_r <= init_cnt_r + 1;
|
188 |
|
|
state_r <= start;
|
189 |
|
|
end if;
|
190 |
|
|
end if;
|
191 |
|
|
|
192 |
|
|
|
193 |
|
|
when wait_link_up =>
|
194 |
|
|
|
195 |
|
|
-- wait until link is up, before raising ready signal
|
196 |
|
|
case wait_link_state_r is
|
197 |
|
|
when send_query =>
|
198 |
|
|
|
199 |
|
|
reg_addr_out <= NSR_c;
|
200 |
|
|
config_data_out <= (others => '0');
|
201 |
|
|
read_not_write_out <= '1';
|
202 |
|
|
config_valid_out <= '1';
|
203 |
|
|
wait_link_state_r <= wait_reply;
|
204 |
|
|
|
205 |
|
|
when wait_reply =>
|
206 |
|
|
|
207 |
|
|
if data_from_comm_valid_in = '1' then
|
208 |
|
|
if data_from_comm_in(6) = '1' then
|
209 |
|
|
-- if bit 6 from NSR - the link up bit - is up, wait continue_times_c
|
210 |
|
|
-- more and then continue
|
211 |
|
|
continue_r <= continue_r + 1;
|
212 |
|
|
end if;
|
213 |
|
|
wait_link_state_r <= idle;
|
214 |
|
|
config_valid_out <= '0';
|
215 |
|
|
end if;
|
216 |
|
|
|
217 |
|
|
when idle =>
|
218 |
|
|
|
219 |
|
|
if wait_link_cnt_r = link_wait_time_c then
|
220 |
|
|
|
221 |
|
|
wait_link_cnt_r <= 0;
|
222 |
|
|
-- check if link is up, and raise ready if so
|
223 |
|
|
if continue_r = continue_times_c then
|
224 |
|
|
ready_r <= '1';
|
225 |
|
|
state_r <= start;
|
226 |
|
|
end if;
|
227 |
|
|
wait_link_state_r <= send_query;
|
228 |
|
|
|
229 |
|
|
else
|
230 |
|
|
wait_link_cnt_r <= wait_link_cnt_r + 1;
|
231 |
|
|
end if;
|
232 |
|
|
when others => null;
|
233 |
|
|
end case;
|
234 |
|
|
when others => null;
|
235 |
|
|
end case;
|
236 |
|
|
|
237 |
|
|
else
|
238 |
|
|
-- ready_r = '1'
|
239 |
|
|
|
240 |
|
|
reg_addr_out <= (others => '0');
|
241 |
|
|
config_data_out <= (others => '0');
|
242 |
|
|
read_not_write_out <= '0';
|
243 |
|
|
config_valid_out <= '0';
|
244 |
|
|
|
245 |
|
|
end if;
|
246 |
|
|
end if;
|
247 |
|
|
end process init;
|
248 |
|
|
|
249 |
|
|
|
250 |
|
|
end rtl;
|