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;
21 register_we_i : in std_logic;
23 mem_clk_i : in std_logic;
24 mem_en_i : in std_logic;
25 mem_we_i : in std_logic_vector(1 downto 0);
26 mem_addr_i : in std_logic_vector(8 downto 0);
27 mem_data_i : in std_logic_vector(15 downto 0);
28 mem_data_o : out std_logic_vector(15 downto 0)
30 end lxmaster_transmitter;
32 architecture Behavioral of lxmaster_transmitter is
35 type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
36 constant frame_length_c : positive := 2500; -- 50 MHz -> 20 kHz
37 -- RAM Access (both ARM and Tumbl)
38 signal ram_en_s : std_logic;
39 signal ram_rst_s : std_logic;
41 signal ram_addr_s : std_logic_vector(8 downto 0);
42 signal ram_addr_r : std_logic_vector(8 downto 0);
43 signal ram_data_o_s : std_logic_vector(15 downto 0);
45 signal lxmaster_state_s : state_t;
46 signal lxmaster_state_r : state_t;
47 signal lxmaster_not_last_word_s : std_logic;
48 signal lxmaster_not_last_word_r : std_logic;
50 signal lxmaster_num_data_s : std_logic_vector(7 downto 0); -- If 0 then the peripheral is not active this cycle
51 signal lxmaster_num_data_r : std_logic_vector(7 downto 0);
52 signal lxmaster_loaded_data_s : std_logic_vector(15 downto 0);
53 signal lxmaster_loaded_data_r : std_logic_vector(15 downto 0);
54 signal lxmaster_data_counter_s : std_logic_vector(3 downto 0); -- Shift: 0 - 15
55 signal lxmaster_data_counter_r : std_logic_vector(3 downto 0);
57 signal lxmaster_sync_s : std_logic;
58 signal lxmaster_sync_r : std_logic;
59 signal lxmaster_sync_last_bit_s : std_logic;
60 signal lxmaster_sync_last_bit_r : std_logic;
62 signal lxmaster_frame_counter_s : natural range 0 to (frame_length_c-1);
64 signal lxmaster_crc_data_s : std_logic;
65 signal lxmaster_crc_reset_s : std_logic;
66 signal lxmaster_crc_out_s : std_logic_vector(7 downto 0);
67 signal lxmaster_crc_reg_s : std_logic_vector(7 downto 0);
68 signal lxmaster_crc_reg_r : std_logic_vector(7 downto 0);
70 signal lxmaster_ram_reset_s : std_logic;
72 -- Bit 0: Transmitter - use first or second buffer
73 signal lxmaster_register_in_s : std_logic;
74 signal lxmaster_register_out_s : std_logic;
78 -- Directly route out some signals
79 clock_o <= clk_i; -- Cannot mix with logic
80 sync_o <= not lxmaster_sync_r; -- Active in log. 0
81 mosi_o <= '1' when lxmaster_sync_r = '0' and lxmaster_sync_last_bit_r = '0'
82 else lxmaster_crc_reg_r(0) when lxmaster_state_r = ST_CRC
83 else lxmaster_loaded_data_r(0);
85 lxmaster_crc_reg_s <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
86 lxmaster_crc_data_s <= '1' when lxmaster_state_r = ST_CRC else lxmaster_loaded_data_r(0);
87 lxmaster_crc_reset_s <= '1' when lxmaster_state_r = ST_READY or reset_i = '1' else '0';
90 register_o <= lxmaster_register_out_s;
92 ram: xilinx_dualport_bram_write_first
105 wea => (others => '0'),
107 dina => (others => '0'),
108 douta => ram_data_o_s,
123 reset_i => lxmaster_crc_reset_s,
124 input_i => lxmaster_crc_data_s,
125 crc_o => lxmaster_crc_out_s
128 ram_rst_s <= reset_i or lxmaster_ram_reset_s;
131 -- TODO: Maybe some exception handling (overflows etc.)
133 process (ram_data_o_s, ram_addr_r, lxmaster_state_r, lxmaster_loaded_data_r, lxmaster_num_data_r, lxmaster_not_last_word_r,
134 lxmaster_data_counter_r, reset_i, lxmaster_frame_counter_s, lxmaster_register_in_s)
135 variable ram_addr_v : std_logic_vector(8 downto 0);
139 lxmaster_ram_reset_s <= '0';
140 lxmaster_sync_last_bit_s <= '0';
141 -- Defaults of state variables (no change)
142 ram_addr_s <= ram_addr_r;
143 lxmaster_state_s <= lxmaster_state_r;
144 lxmaster_loaded_data_s <= lxmaster_loaded_data_r;
145 lxmaster_data_counter_s <= lxmaster_data_counter_r;
146 lxmaster_num_data_s <= lxmaster_num_data_r;
147 lxmaster_not_last_word_s <= lxmaster_not_last_word_r;
149 if reset_i = '1' then
150 lxmaster_num_data_s <= x"00";
151 lxmaster_loaded_data_s <= x"0000";
152 lxmaster_state_s <= ST_END;
153 lxmaster_sync_s <= '0';
155 ram_addr_s <= '0' & x"00";
158 lxmaster_ram_reset_s <= '1';
162 -- OK, we are enabled, default values
163 lxmaster_sync_s <= '0'; -- Not transferring
164 ram_en_s <= '0'; -- Not reading
166 case lxmaster_state_r is
169 -- We just read number of commands
170 if ram_data_o_s(7 downto 0) = x"00" then
171 lxmaster_state_s <= ST_END; --Nothing
173 lxmaster_state_s <= ST_READY; -- Make next read init the transfer
176 -- Regardless, write the number of data
177 lxmaster_num_data_s <= ram_data_o_s(7 downto 0);
179 -- And schedule reading
180 ram_addr_s <= ram_addr_r + 1; -- Update address
181 ram_en_s <= '1'; -- Read
184 -- We are ready to begin transferring
185 lxmaster_loaded_data_s <= ram_data_o_s;
186 lxmaster_sync_s <= '1'; -- Transferring data next cycle
187 lxmaster_data_counter_s <= x"0"; -- Reset counter
188 lxmaster_state_s <= ST_XFER; --Go to transfer loop
189 lxmaster_not_last_word_s <= '0'; -- Not last word
192 lxmaster_loaded_data_s <= '0' & lxmaster_loaded_data_r(15 downto 1); -- Shift it
193 lxmaster_sync_s <= '1'; -- Transferring data next cycle
195 if lxmaster_data_counter_r = x"E" and ram_addr_r(7 downto 0) /= lxmaster_num_data_r then
196 -- At 14th bit, we need to read from RAM if more words are to come
197 ram_addr_s <= ram_addr_r + 1; -- Update address
198 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
199 ram_en_s <= '1'; -- Read
200 lxmaster_not_last_word_s <= '1';
201 elsif lxmaster_data_counter_r = x"F" then
202 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r (wasn't updated so it would not overflow)
203 if ram_addr_r(7 downto 0) = lxmaster_num_data_r and lxmaster_not_last_word_r = '0' then
204 lxmaster_state_s <= ST_CRC;
205 lxmaster_data_counter_s <= x"0";
207 lxmaster_loaded_data_s <= ram_data_o_s;
208 lxmaster_data_counter_s <= x"0";
209 lxmaster_not_last_word_s <= '0';
213 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1;
218 -- Check if this is last command, first read one more
219 if lxmaster_data_counter_r = x"0" then
220 if (ram_addr_r(7 downto 0) = x"FF") then
221 lxmaster_ram_reset_s <= '1'; -- Make sure we read 0 in this case
224 ram_addr_s <= ram_addr_r + 1; -- Update address
225 ram_en_s <= '1'; -- Read
227 elsif lxmaster_data_counter_r = x"1" then
229 if ram_data_o_s(7 downto 0) /= x"00" then -- Need to read first command
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
235 lxmaster_num_data_s <= x"00"; -- Signalize termination
240 if lxmaster_data_counter_r = x"7" then -- Ending
241 lxmaster_data_counter_s <= x"0";
243 if lxmaster_num_data_r(7 downto 0) = x"00" then
244 lxmaster_state_s <= ST_END; -- Last command
246 -- Begin transmission of next data
247 lxmaster_loaded_data_s <= ram_data_o_s;
248 lxmaster_sync_s <= '1'; -- Transferring data next cycle
249 lxmaster_data_counter_s <= x"0"; -- Reset counter
250 lxmaster_state_s <= ST_XFER; --Go to transfer loop
251 lxmaster_not_last_word_s <= '0'; -- Not last word
255 if lxmaster_data_counter_r /= x"6" then
256 lxmaster_sync_s <= '1'; -- Sync goes inactive to signalize termination
258 lxmaster_sync_last_bit_s <= '1';
261 lxmaster_data_counter_s <= lxmaster_data_counter_r + 1; -- Increment
265 if lxmaster_frame_counter_s = (frame_length_c - 1) then
266 -- Initialize first step
267 lxmaster_state_s <= ST_INIT;
268 ram_addr_s <= lxmaster_register_in_s & x"00";
278 -- This function toggles outputs directly, make sure the outputs
279 -- are updated with clock to minimize phase.
284 wait until clk_i'event and clk_i = '1';
287 ram_addr_r <= ram_addr_s;
288 lxmaster_state_r <= lxmaster_state_s;
289 lxmaster_loaded_data_r <= lxmaster_loaded_data_s;
290 lxmaster_data_counter_r <= lxmaster_data_counter_s;
291 lxmaster_num_data_r <= lxmaster_num_data_s;
292 lxmaster_not_last_word_r <= lxmaster_not_last_word_s;
293 lxmaster_crc_reg_r <= lxmaster_crc_reg_s;
296 if reset_i = '1' then
297 lxmaster_frame_counter_s <= (frame_length_c - 1);
298 lxmaster_register_in_s <= '0';
299 lxmaster_register_out_s <= '0';
302 if register_we_i = '1' then
303 lxmaster_register_in_s <= register_i;
306 if lxmaster_frame_counter_s = (frame_length_c - 1) then
307 lxmaster_register_out_s <= lxmaster_register_in_s;
308 lxmaster_frame_counter_s <= 0;
310 lxmaster_frame_counter_s <= lxmaster_frame_counter_s + 1;
315 lxmaster_sync_r <= lxmaster_sync_s;
316 lxmaster_sync_last_bit_r <= lxmaster_sync_last_bit_s;