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
13 reset_i : in std_logic;
15 clock_o : out std_logic;
16 mosi_o : out std_logic;
17 sync_o : out std_logic;
19 register_i : in std_logic;
20 register_o : out std_logic_vector(1 downto 0);
21 register_we_i : in std_logic;
23 wdog_i : in std_logic;
24 wdog_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_transmitter;
35 architecture Behavioral of lxmaster_transmitter is
38 type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
39 constant frame_length_c : positive := 2500; -- 50 MHz -> 20 kHz
40 constant wdog_length_c : positive := 2500000; -- 50 ms
41 constant msg_max_count_c : positive := 8;
42 -- RAM Access (both ARM and Tumbl)
43 signal ram_en_s : std_logic;
44 signal ram_rst_s : std_logic;
46 signal ram_addr_s : std_logic_vector(8 downto 0);
47 signal ram_addr_r : std_logic_vector(8 downto 0);
48 signal ram_data_o_s : std_logic_vector(15 downto 0);
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_loaded_data_s : std_logic_vector(15 downto 0);
58 signal lxmaster_loaded_data_r : std_logic_vector(15 downto 0);
59 signal lxmaster_data_counter_s : std_logic_vector(3 downto 0); -- Shift: 0 - 15
60 signal lxmaster_data_counter_r : std_logic_vector(3 downto 0);
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;
67 signal lxmaster_wdog_counter_s : natural range 0 to (wdog_length_c-1);
68 signal lxmaster_frame_counter_s : natural range 0 to (frame_length_c-1);
69 signal lxmaster_msg_counter_s : natural range 0 to (msg_max_count_c-1);
70 signal lxmaster_msg_counter_r : natural range 0 to (msg_max_count_c-1);
72 signal lxmaster_crc_data_s : std_logic;
73 signal lxmaster_crc_reset_s : std_logic;
74 signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
75 signal lxmaster_crc_reg_s : std_logic_vector(7 downto 0);
76 signal lxmaster_crc_reg_r : std_logic_vector(7 downto 0);
78 signal lxmaster_ram_reset_s : std_logic;
80 -- Bit 0: Transmitter - use first or second buffer (I/O)
81 -- Bit 1: Watchdog not kicked (O)
82 signal lxmaster_register_in_s : std_logic;
83 signal lxmaster_register_out_s : std_logic_vector(1 downto 0);
87 -- Directly route out some signals
88 clock_o <= clk_i; -- Cannot mix with logic
89 sync_o <= not lxmaster_sync_r; -- Active in log. 0
90 mosi_o <= '1' when lxmaster_sync_r = '0' and lxmaster_sync_last_bit_r = '0'
91 else lxmaster_crc_reg_r(0) when lxmaster_state_r = ST_CRC
92 else lxmaster_loaded_data_r(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 lxmaster_loaded_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_write_first
114 wea => (others => '0'),
116 dina => (others => '0'),
117 douta => ram_data_o_s,
132 reset_i => lxmaster_crc_reset_s,
133 input_i => lxmaster_crc_data_s,
134 crc_o => lxmaster_crc_out_s
137 ram_rst_s <= reset_i or lxmaster_ram_reset_s;
140 -- TODO: Maybe some exception handling (overflows etc.)
142 process (ram_data_o_s, ram_addr_r, lxmaster_state_r, lxmaster_loaded_data_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
143 lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_counter_s, lxmaster_register_in_s, lxmaster_wdog_counter_s)
144 variable ram_addr_v : std_logic_vector(8 downto 0);
148 lxmaster_ram_reset_s <= '0';
149 lxmaster_sync_last_bit_s <= '0';
150 -- Defaults of state variables (no change)
151 ram_addr_s <= ram_addr_r;
152 lxmaster_state_s <= lxmaster_state_r;
153 lxmaster_loaded_data_s <= lxmaster_loaded_data_r;
154 lxmaster_data_counter_s <= lxmaster_data_counter_r;
155 lxmaster_num_data_s <= lxmaster_num_data_r;
156 lxmaster_msg_counter_s <= lxmaster_msg_counter_r;
157 lxmaster_last_word_s <= lxmaster_last_word_r;
159 if reset_i = '1' then
160 lxmaster_num_data_s <= x"00";
161 lxmaster_loaded_data_s <= x"0000";
162 lxmaster_state_s <= ST_END;
163 lxmaster_sync_s <= '0';
164 lxmaster_last_word_s <= '0';
166 ram_addr_s <= '0' & x"00";
169 lxmaster_ram_reset_s <= '1';
173 -- OK, we are enabled, default values
174 lxmaster_sync_s <= '0'; -- Not transferring
175 ram_en_s <= '0'; -- Not reading
177 case lxmaster_state_r is
180 -- We just read number of commands
181 if ram_data_o_s(7 downto 0) = x"00" then
182 lxmaster_state_s <= ST_END; --Nothing
184 lxmaster_state_s <= ST_READY; -- Make next read init the transfer
185 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
186 ram_addr_s <= ram_addr_v;
187 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
188 ram_en_s <= '1'; -- Read
191 -- Prepare message counter
192 lxmaster_msg_counter_s <= 0;
195 -- We are ready to begin transferring
196 lxmaster_loaded_data_s <= ram_data_o_s;
197 lxmaster_sync_s <= '1'; -- Transferring data next cycle
198 lxmaster_data_counter_s <= x"0"; -- Reset counter
199 lxmaster_state_s <= ST_XFER; --Go to transfer loop
202 lxmaster_loaded_data_s <= '0' & lxmaster_loaded_data_r(15 downto 1); -- Shift it
203 lxmaster_sync_s <= '1'; -- Transferring data next cycle
205 if lxmaster_data_counter_r = x"E" then
206 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
208 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
209 -- At 14th bit, we need to read from RAM if more words are to come
210 ram_addr_s <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1); -- Update address
211 ram_en_s <= '1'; -- Read
212 lxmaster_last_word_s <= '0';
214 lxmaster_last_word_s <= '1';
217 elsif lxmaster_data_counter_r = x"F" then
218 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
219 if lxmaster_last_word_r = '1' then
220 lxmaster_state_s <= ST_CRC;
221 lxmaster_data_counter_s <= x"0";
223 lxmaster_loaded_data_s <= ram_data_o_s;
224 lxmaster_data_counter_s <= x"0";
228 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1;
233 -- Check if this is last command, first read one more
234 if lxmaster_data_counter_r = x"0" then
235 if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
236 lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 if we are on the last message
238 lxmaster_msg_counter_s <= lxmaster_msg_counter_r + 1;
241 ram_addr_s <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
242 ram_en_s <= '1'; -- Read
244 elsif lxmaster_data_counter_r = x"1" then
246 if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
247 ram_addr_v := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
248 ram_addr_s <= ram_addr_v;
249 lxmaster_num_data_s <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
250 ram_en_s <= '1'; -- Read
252 lxmaster_num_data_s <= x"00"; -- Signalize termination
257 if lxmaster_data_counter_r = x"7" then -- Ending
258 lxmaster_data_counter_s <= x"0";
260 if lxmaster_num_data_r(7 downto 0) = x"00" then
261 lxmaster_state_s <= ST_END; -- Last command
263 -- Begin transmission of next data
264 lxmaster_loaded_data_s <= ram_data_o_s;
265 lxmaster_sync_s <= '1'; -- Transferring data next cycle
266 lxmaster_data_counter_s <= x"0"; -- Reset counter
267 lxmaster_state_s <= ST_XFER; --Go to transfer loop
271 if lxmaster_data_counter_r /= x"6" then
272 lxmaster_sync_s <= '1'; -- Sync goes inactive to signalize termination
274 lxmaster_sync_last_bit_s <= '1';
277 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
281 if lxmaster_frame_counter_s = (frame_length_c - 1) then
282 -- Initialize first step
283 lxmaster_state_s <= ST_INIT;
284 ram_addr_s <= lxmaster_register_in_s & x"00";
286 -- Watchdog - make sure we read 0 if not kicked
287 if lxmaster_wdog_counter_s = (wdog_length_c - 1) then
288 lxmaster_ram_reset_s <= '1';
298 -- This function toggles outputs directly, make sure the outputs
299 -- are updated with clock to minimize phase.
304 wait until clk_i'event and clk_i = '1';
307 ram_addr_r <= ram_addr_s;
308 lxmaster_state_r <= lxmaster_state_s;
309 lxmaster_loaded_data_r <= lxmaster_loaded_data_s;
310 lxmaster_data_counter_r <= lxmaster_data_counter_s;
311 lxmaster_num_data_r <= lxmaster_num_data_s;
312 lxmaster_crc_reg_r <= lxmaster_crc_reg_s;
313 lxmaster_msg_counter_r <= lxmaster_msg_counter_s;
314 lxmaster_last_word_r <= lxmaster_last_word_s;
317 if reset_i = '1' then
318 lxmaster_frame_counter_s <= (frame_length_c - 1);
319 lxmaster_wdog_counter_s <= 0;
320 lxmaster_register_in_s <= '0';
321 lxmaster_register_out_s <= (others => '0');
322 lxmaster_last_word_r <= '1';
325 if register_we_i = '1' then
326 lxmaster_register_in_s <= register_i;
329 if lxmaster_frame_counter_s = (frame_length_c - 1) then
330 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
331 lxmaster_frame_counter_s <= 0;
333 lxmaster_frame_counter_s <= lxmaster_frame_counter_s + 1;
336 if wdog_we_i = '1' and wdog_i = '1' then
337 lxmaster_wdog_counter_s <= 0;
338 lxmaster_register_out_s(1) <= '0';
339 elsif lxmaster_wdog_counter_s /= (wdog_length_c - 1) then
340 lxmaster_wdog_counter_s <= lxmaster_wdog_counter_s + 1;
341 lxmaster_register_out_s(1) <= '0';
343 lxmaster_register_out_s(1) <= '1';
348 lxmaster_sync_r <= lxmaster_sync_s;
349 lxmaster_sync_last_bit_r <= lxmaster_sync_last_bit_s;