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_transmitter is
11 cycle_cnt_width_g : natural := 12
16 reset_i : in std_logic;
18 clock_o : out std_logic;
19 mosi_o : out std_logic;
20 sync_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 cycle_reg_i : in std_logic_vector(cycle_cnt_width_g-1 downto 0);
27 cycle_reg_o : out std_logic_vector(cycle_cnt_width_g-1 downto 0);
28 cycle_reg_we_i : in std_logic;
30 wdog_i : in std_logic;
31 wdog_we_i : in std_logic;
33 mem_clk_i : in std_logic;
34 mem_en_i : in std_logic;
35 mem_we_i : in std_logic_vector(1 downto 0);
36 mem_addr_i : in std_logic_vector(8 downto 0);
37 mem_data_i : in std_logic_vector(15 downto 0);
38 mem_data_o : out std_logic_vector(15 downto 0)
40 end lxmaster_transmitter;
42 architecture Behavioral of lxmaster_transmitter is
45 type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
46 constant frame_length_c : positive := 2500; -- 50 MHz -> 20 kHz
47 constant wdog_length_c : positive := 2500000; -- 50 ms
48 constant msg_max_count_c : positive := 8;
50 signal ram_en_s : std_logic;
51 signal ram_rst_s : std_logic;
52 signal ram_addr_s : std_logic_vector(8 downto 0);
53 signal ram_addr_r : std_logic_vector(8 downto 0);
54 signal ram_data_o_s : std_logic_vector(15 downto 0);
56 signal lxmaster_state_s : state_t;
57 signal lxmaster_state_r : state_t;
58 signal lxmaster_last_word_s : std_logic;
59 signal lxmaster_last_word_r : std_logic;
61 signal lxmaster_num_data_s : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
62 signal lxmaster_num_data_r : std_logic_vector(7 downto 0);
63 signal lxmaster_loaded_data_s : std_logic_vector(15 downto 0);
64 signal lxmaster_loaded_data_r : std_logic_vector(15 downto 0);
65 signal lxmaster_data_counter_s : natural range 0 to 15;
66 signal lxmaster_data_counter_r : natural range 0 to 15;
68 signal lxmaster_sync_s : std_logic;
69 signal lxmaster_sync_r : std_logic;
70 signal lxmaster_sync_last_bit_s : std_logic;
71 signal lxmaster_sync_last_bit_r : std_logic;
73 signal lxmaster_wdog_counter_s : natural range 0 to (wdog_length_c-1);
74 signal lxmaster_frame_counter_s : natural range 0 to (2**cycle_cnt_width_g - 1);
75 signal lxmaster_cycle_limit_r : std_logic_vector(cycle_cnt_width_g-1 downto 0);
76 signal lxmaster_msg_counter_s : natural range 0 to (msg_max_count_c-1);
77 signal lxmaster_msg_counter_r : natural range 0 to (msg_max_count_c-1);
79 signal lxmaster_crc_data_s : std_logic;
80 signal lxmaster_crc_reset_s : std_logic;
81 signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
82 signal lxmaster_crc_reg_s : std_logic_vector(7 downto 0);
83 signal lxmaster_crc_reg_r : std_logic_vector(7 downto 0);
85 signal lxmaster_ram_reset_s : std_logic;
87 -- Bit 0: Transmitter - use first or second buffer (I/O)
88 -- Bit 1: Watchdog not kicked (O)
89 signal lxmaster_register_in_s : std_logic;
90 signal lxmaster_register_out_s : std_logic_vector(1 downto 0);
92 signal sync_s : std_logic;
93 signal sync_r : std_logic;
94 signal mosi_s : std_logic;
95 signal mosi_r : std_logic;
99 -- Directly route out some signals
100 clock_o <= clk_i; -- Cannot mix with logic
101 sync_s <= not lxmaster_sync_r; -- Active in log. 0
102 mosi_s <= '1' when lxmaster_sync_r = '0' and lxmaster_sync_last_bit_r = '0'
103 else lxmaster_crc_reg_r(0) when lxmaster_state_r = ST_CRC
104 else lxmaster_loaded_data_r(0);
109 lxmaster_crc_reg_s <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
110 lxmaster_crc_data_s <= '1' when lxmaster_state_r = ST_CRC else lxmaster_loaded_data_r(0);
111 lxmaster_crc_reset_s <= '1' when lxmaster_state_r /= ST_XFER or reset_i = '1' else '0';
114 register_o <= lxmaster_register_out_s;
115 cycle_reg_o <= lxmaster_cycle_limit_r;
117 ram: xilinx_dualport_bram
123 port_a_type => WRITE_FIRST,
124 port_b_type => READ_FIRST
132 wea => (others => '0'),
134 dina => (others => '0'),
135 douta => ram_data_o_s,
150 reset_i => lxmaster_crc_reset_s,
151 input_i => lxmaster_crc_data_s,
152 crc_o => lxmaster_crc_out_s
155 ram_rst_s <= reset_i or lxmaster_ram_reset_s;
158 -- TODO: Maybe some exception handling (overflows etc.)
160 process (ram_data_o_s, ram_addr_r, lxmaster_state_r, lxmaster_loaded_data_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
161 lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_counter_s, lxmaster_register_in_s, lxmaster_wdog_counter_s)
162 variable ram_addr_v : std_logic_vector(8 downto 0);
166 lxmaster_ram_reset_s <= '0';
167 lxmaster_sync_last_bit_s <= '0';
168 -- Defaults of state variables (no change)
169 ram_addr_s <= ram_addr_r;
170 lxmaster_state_s <= lxmaster_state_r;
171 lxmaster_loaded_data_s <= lxmaster_loaded_data_r;
172 lxmaster_data_counter_s <= lxmaster_data_counter_r;
173 lxmaster_num_data_s <= lxmaster_num_data_r;
174 lxmaster_msg_counter_s <= lxmaster_msg_counter_r;
175 lxmaster_last_word_s <= lxmaster_last_word_r;
177 if reset_i = '1' then
178 lxmaster_num_data_s <= x"00";
179 lxmaster_loaded_data_s <= x"0000";
180 lxmaster_state_s <= ST_END;
181 lxmaster_sync_s <= '0';
182 lxmaster_last_word_s <= '0';
184 ram_addr_s <= '0' & x"00";
187 lxmaster_ram_reset_s <= '1';
191 -- OK, we are enabled, default values
192 lxmaster_sync_s <= '0'; -- Not transferring
193 ram_en_s <= '0'; -- Not reading
195 case lxmaster_state_r is
198 -- We just read number of commands
199 if ram_data_o_s(7 downto 0) = x"00" then
200 lxmaster_state_s <= ST_END; --Nothing
202 lxmaster_state_s <= ST_READY; -- Make next read init the transfer
203 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
204 ram_addr_s <= ram_addr_v;
205 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
206 ram_en_s <= '1'; -- Read
209 -- Prepare message counter
210 lxmaster_msg_counter_s <= 0;
213 -- We are ready to begin transferring
214 lxmaster_loaded_data_s <= ram_data_o_s;
215 lxmaster_sync_s <= '1'; -- Transferring data next cycle
216 lxmaster_data_counter_s <= 0; -- Reset counter
217 lxmaster_state_s <= ST_XFER; --Go to transfer loop
220 lxmaster_loaded_data_s <= '0' & lxmaster_loaded_data_r(15 downto 1); -- Shift it
221 lxmaster_sync_s <= '1'; -- Transferring data next cycle
223 if lxmaster_data_counter_r = 14 then
224 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
226 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
227 -- At 14th bit, we need to read from RAM if more words are to come
228 ram_addr_s <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1); -- Update address
229 ram_en_s <= '1'; -- Read
230 lxmaster_last_word_s <= '0';
232 lxmaster_last_word_s <= '1';
235 elsif lxmaster_data_counter_r = 15 then
236 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
237 if lxmaster_last_word_r = '1' then
238 lxmaster_state_s <= ST_CRC;
239 lxmaster_data_counter_s <= 0;
241 lxmaster_loaded_data_s <= ram_data_o_s;
242 lxmaster_data_counter_s <= 0;
246 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1;
251 -- Check if this is last command, first read one more
252 if lxmaster_data_counter_r = 0 then
253 if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
254 lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 if we are on the last message
256 lxmaster_msg_counter_s <= lxmaster_msg_counter_r + 1;
259 ram_addr_s <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
260 ram_en_s <= '1'; -- Read
262 elsif lxmaster_data_counter_r = 1 then
264 if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
265 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
266 ram_addr_s <= ram_addr_v;
267 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
268 ram_en_s <= '1'; -- Read
270 lxmaster_num_data_s <= x"00"; -- Signalize termination
275 if lxmaster_data_counter_r = 7 then -- Ending
276 lxmaster_data_counter_s <= 0;
278 if lxmaster_num_data_r = x"00" then
279 lxmaster_state_s <= ST_END; -- Last command
281 -- Begin transmission of next data
282 lxmaster_loaded_data_s <= ram_data_o_s;
283 lxmaster_sync_s <= '1'; -- Transferring data next cycle
284 lxmaster_data_counter_s <= 0; -- Reset counter
285 lxmaster_state_s <= ST_XFER; --Go to transfer loop
289 -- Sync goes inactive to signalize termination if we're on last message
290 if lxmaster_data_counter_r /= 6 or lxmaster_num_data_r /= x"00" then
291 lxmaster_sync_s <= '1';
293 lxmaster_sync_last_bit_s <= '1';
296 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
300 if lxmaster_frame_counter_s < 2 then
301 -- Initialize first step
302 lxmaster_state_s <= ST_INIT;
303 ram_addr_s <= lxmaster_register_in_s & x"00";
305 -- Watchdog - make sure we read 0 if not kicked
306 if lxmaster_wdog_counter_s = (wdog_length_c - 1) then
307 lxmaster_ram_reset_s <= '1';
317 -- This function toggles outputs directly, make sure the outputs
318 -- are updated with clock to minimize phase.
323 wait until clk_i'event and clk_i = '1';
326 ram_addr_r <= ram_addr_s;
327 lxmaster_state_r <= lxmaster_state_s;
328 lxmaster_loaded_data_r <= lxmaster_loaded_data_s;
329 lxmaster_data_counter_r <= lxmaster_data_counter_s;
330 lxmaster_num_data_r <= lxmaster_num_data_s;
331 lxmaster_crc_reg_r <= lxmaster_crc_reg_s;
332 lxmaster_msg_counter_r <= lxmaster_msg_counter_s;
333 lxmaster_last_word_r <= lxmaster_last_word_s;
336 if reset_i = '1' then
338 lxmaster_frame_counter_s <= 1;
339 lxmaster_wdog_counter_s <= 0;
340 lxmaster_register_in_s <= '0';
341 lxmaster_register_out_s <= (others => '0');
342 lxmaster_last_word_r <= '1';
343 lxmaster_cycle_limit_r <= std_logic_vector(to_unsigned(frame_length_c,
344 lxmaster_cycle_limit_r'length));
348 if register_we_i = '1' then
349 lxmaster_register_in_s <= register_i;
352 if lxmaster_frame_counter_s < 2 then
353 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
354 lxmaster_frame_counter_s <= to_integer(unsigned(lxmaster_cycle_limit_r));
356 lxmaster_frame_counter_s <= lxmaster_frame_counter_s - 1;
359 if wdog_we_i = '1' and wdog_i = '1' then
360 lxmaster_wdog_counter_s <= 0;
361 lxmaster_register_out_s(1) <= '0';
362 elsif lxmaster_wdog_counter_s /= (wdog_length_c - 1) then
363 lxmaster_wdog_counter_s <= lxmaster_wdog_counter_s + 1;
364 lxmaster_register_out_s(1) <= '0';
366 lxmaster_register_out_s(1) <= '1';
369 if cycle_reg_we_i = '1' then
370 lxmaster_cycle_limit_r <= cycle_reg_i;
375 lxmaster_sync_r <= lxmaster_sync_s;
376 lxmaster_sync_last_bit_r <= lxmaster_sync_last_bit_s;
383 wait until clk_i'event and clk_i = '0';