]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/lxmaster_transmitter.vhd
LX Master watchdog implemented
[fpga/lx-cpu1/lx-rocon.git] / hw / lxmaster_transmitter.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_unsigned.all;
4 use ieee.numeric_std.all;
5 use work.util_pkg.all;
6 use work.lx_rocon_pkg.all;
7
8 -- LX Master (Transmitter)
9 entity lxmaster_transmitter is
10         port
11         (
12                 clk_i             : in std_logic;
13                 reset_i           : in std_logic;
14                 -- Transmision
15                 clock_o           : out std_logic;
16                 mosi_o            : out std_logic;
17                 sync_o            : out std_logic;
18                 -- Register
19                 register_i        : in std_logic;
20                 register_o        : out std_logic_vector(1 downto 0);
21                 register_we_i     : in std_logic;
22                 -- Watchdog
23                 wdog_i            : in std_logic;
24                 wdog_we_i         : in std_logic;
25                 -- BRAM access
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)
32         );
33 end lxmaster_transmitter;
34
35 architecture Behavioral of lxmaster_transmitter is
36
37         -- Types
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;
45         --
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);
49         -- State
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;
54         -- Data
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);
61         -- Transmission
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         -- Counters
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);
71         -- CRC
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);
77         -- RAM reset
78         signal lxmaster_ram_reset_s     : std_logic;
79         -- Register
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);
84
85 begin
86
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);
93         -- CRC
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';
97
98         -- Register
99         register_o           <= lxmaster_register_out_s;
100
101 ram: xilinx_dualport_bram_write_first
102         generic map
103         (
104                 we_width      => 2,
105                 byte_width    => 8,
106                 address_width => 9
107         )
108         port map
109         (
110                 -- Internal
111                 clka  => clk_i,
112                 rsta  => ram_rst_s,
113                 ena   => ram_en_s,
114                 wea   => (others => '0'),
115                 addra => ram_addr_s,
116                 dina  => (others => '0'),
117                 douta => ram_data_o_s,
118                 -- External
119                 clkb  => mem_clk_i,
120                 rstb  => '0',
121                 enb   => mem_en_i,
122                 web   => mem_we_i,
123                 addrb => mem_addr_i,
124                 dinb  => mem_data_i,
125                 doutb => mem_data_o
126         );
127
128 crc_out: crc
129         port map
130         (
131                 clk_i   => clk_i,
132                 reset_i => lxmaster_crc_reset_s,
133                 input_i => lxmaster_crc_data_s,
134                 crc_o   => lxmaster_crc_out_s
135         );
136
137         ram_rst_s <= reset_i or lxmaster_ram_reset_s;
138
139 -- Update
140 -- TODO: Maybe some exception handling (overflows etc.)
141 transmitter_update:
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);
145         begin
146
147                 -- Defaults
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;
158
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';
165                         --
166                         ram_addr_s                       <= '0' & x"00";
167                         ram_en_s                         <= '0';
168                         --
169                         lxmaster_ram_reset_s             <= '1';
170
171                 else
172
173                         -- OK, we are enabled, default values
174                         lxmaster_sync_s                  <= '0'; -- Not transferring
175                         ram_en_s                         <= '0'; -- Not reading
176
177                         case lxmaster_state_r is
178
179                                 when ST_INIT =>
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
183                                         else
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
189                                         end if;
190
191                                         -- Prepare message counter
192                                         lxmaster_msg_counter_s       <= 0;
193
194                                 when ST_READY =>
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
200
201                                 when ST_XFER =>
202                                         lxmaster_loaded_data_s       <= '0' & lxmaster_loaded_data_r(15 downto 1); -- Shift it
203                                         lxmaster_sync_s              <= '1'; -- Transferring data next cycle
204
205                                         if lxmaster_data_counter_r = x"E" then
206                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
207
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';
213                                                 else
214                                                         lxmaster_last_word_s       <= '1';
215                                                 end if;
216
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";
222                                                 else
223                                                         lxmaster_loaded_data_s   <= ram_data_o_s;
224                                                         lxmaster_data_counter_s  <= x"0";
225                                                 end if;
226                                         else
227                                                 -- Increment
228                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1;
229                                         end if;
230
231                                 when ST_CRC =>
232
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
237                                                 else
238                                                         lxmaster_msg_counter_s  <= lxmaster_msg_counter_r + 1;
239                                                 end if;
240
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
243
244                                         elsif lxmaster_data_counter_r = x"1" then
245
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
251                                                 else
252                                                         lxmaster_num_data_s      <= x"00"; -- Signalize termination
253                                                 end if;
254
255                                         end if;
256
257                                         if lxmaster_data_counter_r = x"7" then -- Ending
258                                                 lxmaster_data_counter_s    <= x"0";
259
260                                                 if lxmaster_num_data_r(7 downto 0) = x"00" then
261                                                         lxmaster_state_s         <= ST_END; -- Last command
262                                                 else
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
268                                                 end if;
269
270                                         else
271                                                 if lxmaster_data_counter_r /= x"6" then
272                                                         lxmaster_sync_s          <= '1'; -- Sync goes inactive to signalize termination
273                                                 else
274                                                   lxmaster_sync_last_bit_s <= '1';
275                                                 end if;
276
277                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
278                                         end if;
279
280                                 when ST_END =>
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";
285                                                 ram_en_s                   <= '1';
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';
289                                                 end if;
290                                         end if;
291
292                         end case;
293
294                 end if;
295
296         end process;
297
298 -- This function toggles outputs directly, make sure the outputs
299 -- are updated with clock to minimize phase.
300 state:
301         process
302         begin
303
304                 wait until clk_i'event and clk_i = '1';
305
306                 -- State update
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;
315
316                 -- Increment counter
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';
323                 else
324
325                         if register_we_i = '1' then
326                                 lxmaster_register_in_s     <= register_i;
327                         end if;
328
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;
332                         else
333                                 lxmaster_frame_counter_s   <= lxmaster_frame_counter_s + 1;
334                         end if;
335
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';
342                         else
343                                 lxmaster_register_out_s(1)  <= '1';
344                         end if;
345
346                 end if;
347
348                 lxmaster_sync_r                 <= lxmaster_sync_s;
349                 lxmaster_sync_last_bit_r        <= lxmaster_sync_last_bit_s;
350
351         end process;
352
353 end Behavioral;