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;
20 rx_crc_error_o : out std_logic;
22 register_i : in std_logic;
23 register_o : out std_logic_vector(1 downto 0);
24 register_we_i : in std_logic;
26 mem_clk_i : in std_logic;
27 mem_en_i : in std_logic;
28 mem_we_i : in std_logic_vector(1 downto 0);
29 mem_addr_i : in std_logic_vector(8 downto 0);
30 mem_data_i : in std_logic_vector(15 downto 0);
31 mem_data_o : out std_logic_vector(15 downto 0)
33 end lxmaster_receiver;
35 architecture Behavioral of lxmaster_receiver is
38 type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
39 constant msg_max_count_c : positive := 8;
41 signal ram_en_s : std_logic;
42 signal ram_we_s : std_logic_vector(1 downto 0);
43 signal ram_rst_s : std_logic;
44 signal ram_addr_s : std_logic_vector(8 downto 0);
45 signal ram_addr_r : std_logic_vector(8 downto 0);
46 signal ram_data_o_s : std_logic_vector(15 downto 0);
47 signal ram_data_i_s : std_logic_vector(15 downto 0);
48 signal inc_ram_addr_s : std_logic;
49 signal inc_ram_addr_r : std_logic;
51 signal lxmaster_state_s : state_t;
52 signal lxmaster_state_r : state_t;
53 signal lxmaster_last_word_s : std_logic;
54 signal lxmaster_last_word_r : std_logic;
56 signal lxmaster_num_data_s : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
57 signal lxmaster_num_data_r : std_logic_vector(7 downto 0);
58 signal lxmaster_data_counter_s : natural range 0 to 15;
59 signal lxmaster_data_counter_r : natural range 0 to 15;
61 signal lxmaster_frame_start_s : std_logic;
62 signal lxmaster_sync_s : std_logic;
63 signal lxmaster_sync_r : std_logic;
64 signal lxmaster_sync_last_bit_s : std_logic;
65 signal lxmaster_sync_last_bit_r : std_logic;
66 signal miso_s : std_logic;
67 signal sync_s : std_logic;
68 signal prev_sync_s : std_logic;
69 signal prev_sync_r : std_logic;
70 signal data_ready_s : std_logic;
71 signal received_data_s : std_logic_vector(15 downto 0);
72 signal received_data_r : std_logic_vector(15 downto 0);
74 signal lxmaster_msg_counter_s : natural range 0 to (msg_max_count_c-1);
75 signal lxmaster_msg_counter_r : natural range 0 to (msg_max_count_c-1);
77 signal lxmaster_crc_data_s : std_logic;
78 signal lxmaster_crc_reset_s : std_logic;
79 signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
80 signal lxmaster_crc_reg_s : std_logic_vector(7 downto 0);
81 signal lxmaster_crc_reg_r : std_logic_vector(7 downto 0);
83 signal lxmaster_crc_error_int_s : std_logic;
84 signal lxmaster_crc_error_int_r : std_logic;
85 signal lxmaster_crc_error_s : std_logic;
86 signal lxmaster_crc_error_r : std_logic;
88 signal rx_done_s : std_logic;
91 signal lxmaster_ram_reset_s : std_logic;
93 -- Bit 0: Transmitter - use first or second buffer (I/O)
94 signal lxmaster_register_in_s : std_logic;
95 signal lxmaster_register_out_s : std_logic_vector(1 downto 0);
99 -- Directly route out some signals
100 lxmaster_frame_start_s <= '1' when (sync_s = '1') and (prev_sync_r = '0') else '0';
103 lxmaster_crc_reg_s <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
104 lxmaster_crc_data_s <= received_data_r(received_data_r'length - 1);
105 lxmaster_crc_reset_s <= '1' when lxmaster_state_r /= ST_XFER or reset_i = '1' else '0';
106 rx_crc_error_o <= lxmaster_crc_error_r;
109 register_o <= lxmaster_register_out_s;
111 ram: xilinx_dualport_bram
117 port_a_type => WRITE_FIRST,
118 port_b_type => READ_FIRST
128 dina => ram_data_i_s,
129 douta => ram_data_o_s,
144 reset_i => lxmaster_crc_reset_s,
145 input_i => lxmaster_crc_data_s,
146 crc_o => lxmaster_crc_out_s
149 ram_rst_s <= reset_i or lxmaster_ram_reset_s;
151 crosdom_ser_fifo: lx_crosdom_ser_fifo
158 -- Asynchronous clock domain interface
159 acd_clock_i => clock_i,
160 acd_miso_i => miso_i,
161 acd_sync_i => sync_i,
165 -- Output synchronous with clk_i
168 data_ready_o => data_ready_s -- Not used for now
172 -- TODO: Maybe some exception handling (overflows etc.)
174 process (ram_data_o_s, ram_addr_r, inc_ram_addr_r, lxmaster_state_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
175 lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_start_s, lxmaster_register_in_s,
176 sync_s, miso_s, prev_sync_r, received_data_r, lxmaster_crc_reg_r, lxmaster_crc_error_int_r,
177 lxmaster_crc_error_r)
178 variable ram_addr_v : std_logic_vector(8 downto 0);
179 variable crc_bit_mismatch_v : std_logic;
183 lxmaster_ram_reset_s <= '0';
184 lxmaster_sync_last_bit_s <= '0';
186 -- Defaults of state variables (no change)
187 ram_addr_s <= ram_addr_r;
188 inc_ram_addr_s <= '0';
189 lxmaster_state_s <= lxmaster_state_r;
190 lxmaster_data_counter_s <= lxmaster_data_counter_r;
191 lxmaster_num_data_s <= lxmaster_num_data_r;
192 lxmaster_msg_counter_s <= lxmaster_msg_counter_r;
193 lxmaster_last_word_s <= lxmaster_last_word_r;
194 lxmaster_crc_error_int_s <= lxmaster_crc_error_int_r;
195 lxmaster_crc_error_s <= lxmaster_crc_error_r;
197 prev_sync_s <= sync_s;
200 ram_data_i_s <= received_data_r;
201 received_data_s <= miso_s & received_data_r(received_data_r'length - 1 downto 1);
203 if reset_i = '1' then
204 lxmaster_num_data_s <= x"00";
205 lxmaster_state_s <= ST_END;
206 lxmaster_sync_s <= '0';
207 lxmaster_last_word_s <= '0';
209 ram_addr_s <= '0' & x"00";
212 lxmaster_ram_reset_s <= '1';
213 lxmaster_crc_error_s <= '0';
217 -- OK, we are enabled, default values
218 lxmaster_sync_s <= '0'; -- Not transferring
219 ram_en_s <= '0'; -- Not reading
221 case lxmaster_state_r is
224 -- We just read number of commands
225 if ram_data_o_s(7 downto 0) = x"00" then
226 lxmaster_state_s <= ST_END; --Nothing
229 lxmaster_state_s <= ST_READY; -- Make next read init the transfer
230 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
231 ram_addr_s <= ram_addr_v;
232 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
233 ram_en_s <= '1'; -- Read
236 -- Prepare message counter
237 lxmaster_msg_counter_s <= 0;
239 lxmaster_crc_error_int_s <= '0';
242 -- We are ready to begin transferring
243 lxmaster_sync_s <= '1'; -- Transferring data next cycle
244 lxmaster_data_counter_s <= 0; -- Reset counter
245 lxmaster_state_s <= ST_XFER; --Go to transfer loop
248 lxmaster_sync_s <= '1'; -- Transferring data next cycle
250 if inc_ram_addr_r = '1' then
251 -- Update address if second and other loop
252 ram_addr_s <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1);
255 if lxmaster_data_counter_r = 14 then
256 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
258 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
259 lxmaster_last_word_s <= '0';
261 lxmaster_last_word_s <= '1';
264 elsif lxmaster_data_counter_r = 15 then
265 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
266 if lxmaster_last_word_r = '1' then
267 lxmaster_state_s <= ST_CRC;
268 lxmaster_data_counter_s <= 0;
270 lxmaster_data_counter_s <= 0;
275 inc_ram_addr_s <= '1';
278 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1;
283 if received_data_r(received_data_r'length - 1) /= lxmaster_crc_reg_r(0) then
284 crc_bit_mismatch_v := '1';
286 crc_bit_mismatch_v := '0';
289 if crc_bit_mismatch_v = '1' then
290 lxmaster_crc_error_int_s <= '1';
293 -- Check if this is last command, first read one more
294 if lxmaster_data_counter_r = 0 then
295 if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
296 lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 if we are on the last message
298 lxmaster_msg_counter_s <= lxmaster_msg_counter_r + 1;
301 ram_addr_s <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
302 ram_en_s <= '1'; -- Read
304 elsif lxmaster_data_counter_r = 1 then
306 if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
307 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
308 ram_addr_s <= ram_addr_v;
309 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
310 ram_en_s <= '1'; -- Read
312 lxmaster_num_data_s <= x"00"; -- Signalize termination
317 if lxmaster_data_counter_r = 7 then -- Ending
318 lxmaster_data_counter_s <= 0;
320 if lxmaster_num_data_r = x"00" then
321 lxmaster_state_s <= ST_END; -- Last command
323 lxmaster_crc_error_s <= lxmaster_crc_error_int_r or crc_bit_mismatch_v;
325 -- Begin transmission of next data
326 lxmaster_sync_s <= '1'; -- Transferring data next cycle
327 lxmaster_data_counter_s <= 0; -- Reset counter
328 lxmaster_state_s <= ST_XFER; --Go to transfer loop
332 -- Sync goes inactive to signalize termination if we're on last message
333 if lxmaster_data_counter_r /= 6 or lxmaster_num_data_r /= x"00" then
334 lxmaster_sync_s <= '1';
336 lxmaster_sync_last_bit_s <= '1';
339 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
343 if lxmaster_frame_start_s = '1' then
344 -- Initialize first step
345 lxmaster_state_s <= ST_INIT;
346 ram_addr_s <= lxmaster_register_in_s & x"00";
356 -- This function toggles outputs directly, make sure the outputs
357 -- are updated with clock to minimize phase.
362 wait until clk_i'event and clk_i = '1';
365 ram_addr_r <= ram_addr_s;
366 inc_ram_addr_r <= inc_ram_addr_s;
367 lxmaster_state_r <= lxmaster_state_s;
368 lxmaster_data_counter_r <= lxmaster_data_counter_s;
369 lxmaster_num_data_r <= lxmaster_num_data_s;
370 lxmaster_crc_reg_r <= lxmaster_crc_reg_s;
371 lxmaster_msg_counter_r <= lxmaster_msg_counter_s;
372 lxmaster_last_word_r <= lxmaster_last_word_s;
373 lxmaster_crc_error_int_r <= lxmaster_crc_error_int_s;
374 lxmaster_crc_error_r <= lxmaster_crc_error_s;
376 rx_done_o <= rx_done_s;
379 if reset_i = '1' then
381 lxmaster_register_in_s <= '0';
382 lxmaster_register_out_s <= (others => '0');
383 lxmaster_last_word_r <= '1';
387 if register_we_i = '1' then
388 lxmaster_register_in_s <= register_i;
391 if lxmaster_frame_start_s = '1' then
392 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
395 if lxmaster_state_s = ST_END then
396 lxmaster_register_out_s(1) <= '0';
398 lxmaster_register_out_s(1) <= '1';
402 lxmaster_sync_r <= lxmaster_sync_s;
403 lxmaster_sync_last_bit_r <= lxmaster_sync_last_bit_s;
405 prev_sync_r <= prev_sync_s;
406 received_data_r <= received_data_s;