]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/lxmaster_receiver.vhd
LX master: implement CRC checking in receiver.
[fpga/lx-cpu1/lx-rocon.git] / hw / lxmaster_receiver.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_receiver is
10         port
11         (
12                 clk_i             : in std_logic;
13                 reset_i           : in std_logic;
14                 -- Transmision
15                 clock_i           : in std_logic;
16                 miso_i            : in std_logic;
17                 sync_i            : in std_logic;
18                 -- Receive done pulse
19                 rx_done_o         : out std_logic;
20                 rx_crc_error_o    : out std_logic;
21                 -- Register
22                 register_i        : in std_logic;
23                 register_o        : out std_logic_vector(1 downto 0);
24                 register_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_receiver;
34
35 architecture Behavioral of lxmaster_receiver is
36
37         -- Types
38         type state_t is (ST_INIT, ST_READY, ST_XFER, ST_CRC, ST_END);
39         constant msg_max_count_c        : positive := 8;
40         -- RAM Access
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;
50         -- State
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;
55         -- Data
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;
60         -- Receiption
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);
73         -- Counters
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);
76         -- CRC
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);
82
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;
87
88         signal rx_done_s                : std_logic;
89
90         -- RAM reset
91         signal lxmaster_ram_reset_s     : std_logic;
92         -- Register
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);
96
97 begin
98
99         -- Directly route out some signals
100         lxmaster_frame_start_s <= '1' when (sync_s = '1') and (prev_sync_r = '0') else '0';
101
102         -- CRC
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;
107
108         -- Register
109         register_o           <= lxmaster_register_out_s;
110
111 ram: xilinx_dualport_bram
112         generic map
113         (
114                 we_width      => 2,
115                 byte_width    => 8,
116                 address_width => 9,
117                 port_a_type   => WRITE_FIRST,
118                 port_b_type   => READ_FIRST
119         )
120         port map
121         (
122                 -- Internal
123                 clka  => clk_i,
124                 rsta  => ram_rst_s,
125                 ena   => ram_en_s,
126                 wea   => ram_we_s,
127                 addra => ram_addr_s,
128                 dina  => ram_data_i_s,
129                 douta => ram_data_o_s,
130                 -- External
131                 clkb  => mem_clk_i,
132                 rstb  => '0',
133                 enb   => mem_en_i,
134                 web   => mem_we_i,
135                 addrb => mem_addr_i,
136                 dinb  => mem_data_i,
137                 doutb => mem_data_o
138         );
139
140 crc_out: crc
141         port map
142         (
143                 clk_i   => clk_i,
144                 reset_i => lxmaster_crc_reset_s,
145                 input_i => lxmaster_crc_data_s,
146                 crc_o   => lxmaster_crc_out_s
147         );
148
149         ram_rst_s <= reset_i or lxmaster_ram_reset_s;
150
151 crosdom_ser_fifo: lx_crosdom_ser_fifo
152         generic map
153         (
154                 sync_adj_g   => -1
155         )
156         port map
157         (
158                 -- Asynchronous clock domain interface
159                 acd_clock_i  => clock_i,
160                 acd_miso_i   => miso_i,
161                 acd_sync_i   => sync_i,
162                 -- Clock
163                 clk_i        => clk_i,
164                 reset_i      => reset_i,
165                 -- Output synchronous with clk_i
166                 miso_o       => miso_s,
167                 sync_o       => sync_s,
168                 data_ready_o => data_ready_s -- Not used for now
169         );
170
171 -- Update
172 -- TODO: Maybe some exception handling (overflows etc.)
173 transmitter_update:
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;
180         begin
181
182                 -- Defaults
183                 lxmaster_ram_reset_s               <= '0';
184                 lxmaster_sync_last_bit_s           <= '0';
185                 rx_done_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;
196
197                 prev_sync_s                        <=  sync_s;
198                 ram_we_s                           <= "00";
199
200                 ram_data_i_s                       <= received_data_r;
201                 received_data_s <= miso_s & received_data_r(received_data_r'length - 1 downto 1);
202
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';
208                         --
209                         ram_addr_s                       <= '0' & x"00";
210                         ram_en_s                         <= '0';
211                         --
212                         lxmaster_ram_reset_s             <= '1';
213                         lxmaster_crc_error_s             <= '0';
214
215                 else
216
217                         -- OK, we are enabled, default values
218                         lxmaster_sync_s                  <= '0'; -- Not transferring
219                         ram_en_s                         <= '0'; -- Not reading
220
221                         case lxmaster_state_r is
222
223                                 when ST_INIT =>
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
227                                                 rx_done_s <= '1';
228                                         else
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
234                                         end if;
235
236                                         -- Prepare message counter
237                                         lxmaster_msg_counter_s       <= 0;
238
239                                         lxmaster_crc_error_int_s     <= '0';
240
241                                 when ST_READY =>
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
246
247                                 when ST_XFER =>
248                                         lxmaster_sync_s              <= '1'; -- Transferring data next cycle
249
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);
253                                         end if;
254
255                                         if lxmaster_data_counter_r = 14 then
256                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
257
258                                                 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
259                                                         lxmaster_last_word_s       <= '0';
260                                                 else
261                                                         lxmaster_last_word_s       <= '1';
262                                                 end if;
263
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;
269                                                 else
270                                                         lxmaster_data_counter_s  <= 0;
271                                                 end if;
272
273                                                 ram_we_s                   <= "11";
274                                                 ram_en_s                   <= '1';
275                                                 inc_ram_addr_s             <= '1';
276                                         else
277                                                 -- Increment
278                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1;
279                                         end if;
280
281                                 when ST_CRC =>
282
283                                         if received_data_r(received_data_r'length - 1) /= lxmaster_crc_reg_r(0) then
284                                                 crc_bit_mismatch_v := '1';
285                                         else
286                                                 crc_bit_mismatch_v := '0';
287                                         end if;
288
289                                         if crc_bit_mismatch_v = '1' then
290                                                 lxmaster_crc_error_int_s <= '1';
291                                         end if;
292
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
297                                                 else
298                                                         lxmaster_msg_counter_s  <= lxmaster_msg_counter_r + 1;
299                                                 end if;
300
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
303
304                                         elsif lxmaster_data_counter_r = 1 then
305
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
311                                                 else
312                                                         lxmaster_num_data_s      <= x"00"; -- Signalize termination
313                                                 end if;
314
315                                         end if;
316
317                                         if lxmaster_data_counter_r = 7 then -- Ending
318                                                 lxmaster_data_counter_s    <= 0;
319
320                                                 if lxmaster_num_data_r = x"00" then
321                                                         lxmaster_state_s         <= ST_END; -- Last command
322                                                         rx_done_s <= '1';
323                                                         lxmaster_crc_error_s     <= lxmaster_crc_error_int_r or crc_bit_mismatch_v;
324                                                 else
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
329                                                 end if;
330
331                                         else
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';
335                                                 else
336                                                   lxmaster_sync_last_bit_s <= '1';
337                                                 end if;
338
339                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
340                                         end if;
341
342                                 when ST_END =>
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";
347                                                 ram_en_s                   <= '1';
348                                         end if;
349
350                         end case;
351
352                 end if;
353
354         end process;
355
356 -- This function toggles outputs directly, make sure the outputs
357 -- are updated with clock to minimize phase.
358 state:
359         process
360         begin
361
362                 wait until clk_i'event and clk_i = '1';
363
364                 -- State update
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;
375
376                 rx_done_o                      <= rx_done_s;
377
378                 -- Increment counter
379                 if reset_i = '1' then
380
381                         lxmaster_register_in_s       <= '0';
382                         lxmaster_register_out_s      <= (others => '0');
383                         lxmaster_last_word_r         <= '1';
384
385                 else
386
387                         if register_we_i = '1' then
388                                 lxmaster_register_in_s     <= register_i;
389                         end if;
390
391                         if lxmaster_frame_start_s = '1' then
392                                 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
393                         end if;
394
395                         if lxmaster_state_s = ST_END then
396                                 lxmaster_register_out_s(1)  <= '0';
397                         else
398                                 lxmaster_register_out_s(1)  <= '1';
399                         end if;
400                 end if;
401
402                 lxmaster_sync_r                 <= lxmaster_sync_s;
403                 lxmaster_sync_last_bit_r        <= lxmaster_sync_last_bit_s;
404
405                 prev_sync_r <= prev_sync_s;
406                 received_data_r <= received_data_s;
407
408         end process;
409
410 end Behavioral;