2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_unsigned.all;
4 use ieee.numeric_std.all;
6 use work.lx_rocon_pkg.all;
8 -- LX Master (Transmitter)
9 entity lxmaster_receiver is
13 reset_i : in std_logic;
15 clock_i : in std_logic;
16 miso_i : in std_logic;
17 sync_i : in std_logic;
19 rx_done_o : out std_logic;
21 register_i : in std_logic;
22 register_o : out std_logic_vector(1 downto 0);
23 register_we_i : in std_logic;
25 mem_clk_i : in std_logic;
26 mem_en_i : in std_logic;
27 mem_we_i : in std_logic_vector(1 downto 0);
28 mem_addr_i : in std_logic_vector(8 downto 0);
29 mem_data_i : in std_logic_vector(15 downto 0);
30 mem_data_o : out std_logic_vector(15 downto 0)
32 end lxmaster_receiver;
34 architecture Behavioral of lxmaster_receiver is
37 type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
38 constant msg_max_count_c : positive := 8;
40 signal ram_en_s : std_logic;
41 signal ram_we_s : std_logic_vector(1 downto 0);
42 signal ram_rst_s : std_logic;
43 signal ram_addr_s : std_logic_vector(8 downto 0);
44 signal ram_addr_r : std_logic_vector(8 downto 0);
45 signal ram_data_o_s : std_logic_vector(15 downto 0);
46 signal ram_data_i_s : std_logic_vector(15 downto 0);
47 signal inc_ram_addr_s : std_logic;
48 signal inc_ram_addr_r : std_logic;
50 signal lxmaster_state_s : state_t;
51 signal lxmaster_state_r : state_t;
52 signal lxmaster_last_word_s : std_logic;
53 signal lxmaster_last_word_r : std_logic;
55 signal lxmaster_num_data_s : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
56 signal lxmaster_num_data_r : std_logic_vector(7 downto 0);
57 signal lxmaster_data_counter_s : natural range 0 to 15;
58 signal lxmaster_data_counter_r : natural range 0 to 15;
60 signal lxmaster_frame_start_s : std_logic;
61 signal lxmaster_sync_s : std_logic;
62 signal lxmaster_sync_r : std_logic;
63 signal lxmaster_sync_last_bit_s : std_logic;
64 signal lxmaster_sync_last_bit_r : std_logic;
65 signal miso_s : std_logic;
66 signal sync_s : std_logic;
67 signal prev_sync_s : std_logic;
68 signal prev_sync_r : std_logic;
69 signal data_ready_s : std_logic;
70 signal received_data_s : std_logic_vector(15 downto 0);
71 signal received_data_r : std_logic_vector(15 downto 0);
73 signal lxmaster_msg_counter_s : natural range 0 to (msg_max_count_c-1);
74 signal lxmaster_msg_counter_r : natural range 0 to (msg_max_count_c-1);
76 signal lxmaster_crc_data_s : std_logic;
77 signal lxmaster_crc_reset_s : std_logic;
78 signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
79 signal lxmaster_crc_reg_s : std_logic_vector(7 downto 0);
80 signal lxmaster_crc_reg_r : std_logic_vector(7 downto 0);
82 signal lxmaster_ram_reset_s : std_logic;
84 -- Bit 0: Transmitter - use first or second buffer (I/O)
85 signal lxmaster_register_in_s : std_logic;
86 signal lxmaster_register_out_s : std_logic_vector(1 downto 0);
90 -- Directly route out some signals
91 lxmaster_frame_start_s <= '1' when (sync_s = '1') and (prev_sync_r = '0') else '0';
94 lxmaster_crc_reg_s <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
95 lxmaster_crc_data_s <= '1' when lxmaster_state_r = ST_CRC else received_data_r(0);
96 lxmaster_crc_reset_s <= '1' when lxmaster_state_r /= ST_XFER or reset_i = '1' else '0';
99 register_o <= lxmaster_register_out_s;
101 ram: xilinx_dualport_bram
107 port_a_type => WRITE_FIRST,
108 port_b_type => READ_FIRST
118 dina => ram_data_i_s,
119 douta => ram_data_o_s,
134 reset_i => lxmaster_crc_reset_s,
135 input_i => lxmaster_crc_data_s,
136 crc_o => lxmaster_crc_out_s
139 ram_rst_s <= reset_i or lxmaster_ram_reset_s;
141 crosdom_ser_fifo: lx_crosdom_ser_fifo
148 -- Asynchronous clock domain interface
149 acd_clock_i => clock_i,
150 acd_miso_i => miso_i,
151 acd_sync_i => sync_i,
155 -- Output synchronous with clk_i
158 data_ready_o => data_ready_s -- Not used for now
162 -- TODO: Maybe some exception handling (overflows etc.)
164 process (ram_data_o_s, ram_addr_r, inc_ram_addr_r, lxmaster_state_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
165 lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_start_s, lxmaster_register_in_s,
166 sync_s, miso_s, prev_sync_r, received_data_r)
167 variable ram_addr_v : std_logic_vector(8 downto 0);
171 lxmaster_ram_reset_s <= '0';
172 lxmaster_sync_last_bit_s <= '0';
174 -- Defaults of state variables (no change)
175 ram_addr_s <= ram_addr_r;
176 inc_ram_addr_s <= '0';
177 lxmaster_state_s <= lxmaster_state_r;
178 lxmaster_data_counter_s <= lxmaster_data_counter_r;
179 lxmaster_num_data_s <= lxmaster_num_data_r;
180 lxmaster_msg_counter_s <= lxmaster_msg_counter_r;
181 lxmaster_last_word_s <= lxmaster_last_word_r;
183 prev_sync_s <= sync_s;
186 ram_data_i_s <= received_data_r;
187 received_data_s <= miso_s & received_data_r(received_data_r'length - 1 downto 1);
189 if reset_i = '1' then
190 lxmaster_num_data_s <= x"00";
191 lxmaster_state_s <= ST_END;
192 lxmaster_sync_s <= '0';
193 lxmaster_last_word_s <= '0';
195 ram_addr_s <= '0' & x"00";
198 lxmaster_ram_reset_s <= '1';
202 -- OK, we are enabled, default values
203 lxmaster_sync_s <= '0'; -- Not transferring
204 ram_en_s <= '0'; -- Not reading
206 case lxmaster_state_r is
209 -- We just read number of commands
210 if ram_data_o_s(7 downto 0) = x"00" then
211 lxmaster_state_s <= ST_END; --Nothing
214 lxmaster_state_s <= ST_READY; -- Make next read init the transfer
215 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
216 ram_addr_s <= ram_addr_v;
217 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
218 ram_en_s <= '1'; -- Read
221 -- Prepare message counter
222 lxmaster_msg_counter_s <= 0;
225 -- We are ready to begin transferring
226 lxmaster_sync_s <= '1'; -- Transferring data next cycle
227 lxmaster_data_counter_s <= 0; -- Reset counter
228 lxmaster_state_s <= ST_XFER; --Go to transfer loop
231 lxmaster_sync_s <= '1'; -- Transferring data next cycle
233 if inc_ram_addr_r = '1' then
234 -- Update address if second and other loop
235 ram_addr_s <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1);
238 if lxmaster_data_counter_r = 14 then
239 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
241 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
242 lxmaster_last_word_s <= '0';
244 lxmaster_last_word_s <= '1';
247 elsif lxmaster_data_counter_r = 15 then
248 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
249 if lxmaster_last_word_r = '1' then
250 lxmaster_state_s <= ST_CRC;
251 lxmaster_data_counter_s <= 0;
253 lxmaster_data_counter_s <= 0;
258 inc_ram_addr_s <= '1';
261 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1;
266 -- Check if this is last command, first read one more
267 if lxmaster_data_counter_r = 0 then
268 if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
269 lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 if we are on the last message
271 lxmaster_msg_counter_s <= lxmaster_msg_counter_r + 1;
274 ram_addr_s <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
275 ram_en_s <= '1'; -- Read
277 elsif lxmaster_data_counter_r = 1 then
279 if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
280 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
281 ram_addr_s <= ram_addr_v;
282 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
283 ram_en_s <= '1'; -- Read
285 lxmaster_num_data_s <= x"00"; -- Signalize termination
290 if lxmaster_data_counter_r = 7 then -- Ending
291 lxmaster_data_counter_s <= 0;
293 if lxmaster_num_data_r = x"00" then
294 lxmaster_state_s <= ST_END; -- Last command
297 -- Begin transmission of next data
298 lxmaster_sync_s <= '1'; -- Transferring data next cycle
299 lxmaster_data_counter_s <= 0; -- Reset counter
300 lxmaster_state_s <= ST_XFER; --Go to transfer loop
304 -- Sync goes inactive to signalize termination if we're on last message
305 if lxmaster_data_counter_r /= 6 or lxmaster_num_data_r /= x"00" then
306 lxmaster_sync_s <= '1';
308 lxmaster_sync_last_bit_s <= '1';
311 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
315 if lxmaster_frame_start_s = '1' then
316 -- Initialize first step
317 lxmaster_state_s <= ST_INIT;
318 ram_addr_s <= lxmaster_register_in_s & x"00";
328 -- This function toggles outputs directly, make sure the outputs
329 -- are updated with clock to minimize phase.
334 wait until clk_i'event and clk_i = '1';
337 ram_addr_r <= ram_addr_s;
338 inc_ram_addr_r <= inc_ram_addr_s;
339 lxmaster_state_r <= lxmaster_state_s;
340 lxmaster_data_counter_r <= lxmaster_data_counter_s;
341 lxmaster_num_data_r <= lxmaster_num_data_s;
342 lxmaster_crc_reg_r <= lxmaster_crc_reg_s;
343 lxmaster_msg_counter_r <= lxmaster_msg_counter_s;
344 lxmaster_last_word_r <= lxmaster_last_word_s;
347 if reset_i = '1' then
349 lxmaster_register_in_s <= '0';
350 lxmaster_register_out_s <= (others => '0');
351 lxmaster_last_word_r <= '1';
355 if register_we_i = '1' then
356 lxmaster_register_in_s <= register_i;
359 if lxmaster_frame_start_s = '1' then
360 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
363 if lxmaster_state_s = ST_END then
364 lxmaster_register_out_s(1) <= '0';
366 lxmaster_register_out_s(1) <= '1';
370 lxmaster_sync_r <= lxmaster_sync_s;
371 lxmaster_sync_last_bit_r <= lxmaster_sync_last_bit_s;
373 prev_sync_r <= prev_sync_s;
374 received_data_r <= received_data_s;