]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/lxmaster_receiver.vhd
RoCoN: USB CDC ACM use maximal packet length - 64 bytes.
[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 miso_s                   : std_logic;
63         signal sync_s                   : std_logic;
64         signal prev_sync_s              : std_logic;
65         signal prev_sync_r              : std_logic;
66         signal data_ready_s             : std_logic;
67         signal received_data_s          : std_logic_vector(15 downto 0);
68         signal received_data_r          : std_logic_vector(15 downto 0);
69         -- Counters
70         signal lxmaster_msg_counter_s   : natural range 0 to (msg_max_count_c-1);
71         signal lxmaster_msg_counter_r   : natural range 0 to (msg_max_count_c-1);
72         -- CRC
73         signal lxmaster_crc_data_s      : std_logic;
74         signal lxmaster_crc_reset_s     : std_logic;
75         signal lxmaster_crc_out_s       : std_logic_vector(7 downto 0);
76         signal lxmaster_crc_reg_s       : std_logic_vector(7 downto 0);
77         signal lxmaster_crc_reg_r       : std_logic_vector(7 downto 0);
78
79         signal lxmaster_crc_error_int_s : std_logic;
80         signal lxmaster_crc_error_int_r : std_logic;
81         signal lxmaster_crc_error_s     : std_logic;
82         signal lxmaster_crc_error_r     : std_logic;
83
84         signal rx_done_s                : std_logic;
85
86         -- RAM reset
87         signal lxmaster_ram_reset_s     : std_logic;
88         -- Register
89         -- Bit 0: Transmitter - use first or second buffer (I/O)
90         signal lxmaster_register_in_s   : std_logic;
91         signal lxmaster_register_out_s  : std_logic_vector(1 downto 0);
92
93 begin
94
95         -- Directly route out some signals
96         lxmaster_frame_start_s <= '1' when (sync_s = '1') and (prev_sync_r = '0') else '0';
97
98         -- CRC
99         lxmaster_crc_reg_s   <= '0' & lxmaster_crc_reg_r(7 downto 1) when lxmaster_state_r = ST_CRC else lxmaster_crc_out_s;
100         lxmaster_crc_data_s  <= received_data_r(received_data_r'length - 1);
101         lxmaster_crc_reset_s <= '1' when lxmaster_state_r /= ST_XFER or reset_i = '1' else '0';
102         rx_crc_error_o <= lxmaster_crc_error_r;
103
104         -- Register
105         register_o           <= lxmaster_register_out_s;
106
107 ram: xilinx_dualport_bram
108         generic map
109         (
110                 we_width      => 2,
111                 byte_width    => 8,
112                 address_width => 9,
113                 port_a_type   => WRITE_FIRST,
114                 port_b_type   => READ_FIRST
115         )
116         port map
117         (
118                 -- Internal
119                 clka  => clk_i,
120                 rsta  => ram_rst_s,
121                 ena   => ram_en_s,
122                 wea   => ram_we_s,
123                 addra => ram_addr_s,
124                 dina  => ram_data_i_s,
125                 douta => ram_data_o_s,
126                 -- External
127                 clkb  => mem_clk_i,
128                 rstb  => '0',
129                 enb   => mem_en_i,
130                 web   => mem_we_i,
131                 addrb => mem_addr_i,
132                 dinb  => mem_data_i,
133                 doutb => mem_data_o
134         );
135
136 crc_out: crc
137         port map
138         (
139                 clk_i   => clk_i,
140                 reset_i => lxmaster_crc_reset_s,
141                 input_i => lxmaster_crc_data_s,
142                 crc_o   => lxmaster_crc_out_s
143         );
144
145         ram_rst_s <= reset_i or lxmaster_ram_reset_s;
146
147 crosdom_ser_fifo: lx_crosdom_ser_fifo
148         generic map
149         (
150                 sync_adj_g   => -1
151         )
152         port map
153         (
154                 -- Asynchronous clock domain interface
155                 acd_clock_i  => clock_i,
156                 acd_miso_i   => miso_i,
157                 acd_sync_i   => sync_i,
158                 -- Clock
159                 clk_i        => clk_i,
160                 reset_i      => reset_i,
161                 -- Output synchronous with clk_i
162                 miso_o       => miso_s,
163                 sync_o       => sync_s,
164                 data_ready_o => data_ready_s -- Not used for now
165         );
166
167 -- Update
168 -- TODO: Maybe some exception handling (overflows etc.)
169 transmitter_update:
170         process (ram_data_o_s, ram_addr_r, inc_ram_addr_r, lxmaster_state_r, lxmaster_num_data_r, lxmaster_msg_counter_r,
171                  lxmaster_last_word_r, lxmaster_data_counter_r, reset_i, lxmaster_frame_start_s, lxmaster_register_in_s,
172                  sync_s, miso_s, prev_sync_r, received_data_r, lxmaster_crc_reg_r, lxmaster_crc_error_int_r,
173                  lxmaster_crc_error_r)
174                 variable ram_addr_v : std_logic_vector(8 downto 0);
175                 variable crc_bit_mismatch_v : std_logic;
176         begin
177
178                 -- Defaults
179                 lxmaster_ram_reset_s               <= '0';
180                 rx_done_s                          <= '0';
181                 -- Defaults of state variables (no change)
182                 ram_addr_s                         <= ram_addr_r;
183                 inc_ram_addr_s                     <= '0';
184                 lxmaster_state_s                   <= lxmaster_state_r;
185                 lxmaster_data_counter_s            <= lxmaster_data_counter_r;
186                 lxmaster_num_data_s                <= lxmaster_num_data_r;
187                 lxmaster_msg_counter_s             <= lxmaster_msg_counter_r;
188                 lxmaster_last_word_s               <= lxmaster_last_word_r;
189                 lxmaster_crc_error_int_s           <= lxmaster_crc_error_int_r;
190                 lxmaster_crc_error_s               <= lxmaster_crc_error_r;
191
192                 prev_sync_s                        <=  sync_s;
193                 ram_we_s                           <= "00";
194
195                 ram_data_i_s                       <= received_data_r;
196                 received_data_s <= miso_s & received_data_r(received_data_r'length - 1 downto 1);
197
198                 if reset_i = '1' then
199                         lxmaster_num_data_s              <= x"00";
200                         lxmaster_state_s                 <= ST_END;
201                         lxmaster_last_word_s             <= '0';
202                         --
203                         ram_addr_s                       <= '0' & x"00";
204                         ram_en_s                         <= '0';
205                         --
206                         lxmaster_ram_reset_s             <= '1';
207                         lxmaster_crc_error_s             <= '0';
208
209                 else
210
211                         -- OK, we are enabled, default values
212                         ram_en_s                         <= '0'; -- Not reading
213
214                         case lxmaster_state_r is
215
216                                 when ST_INIT =>
217                                         -- We just read number of commands
218                                         if ram_data_o_s(7 downto 0) = x"00" then
219                                                 lxmaster_state_s           <= ST_END; --Nothing
220                                                 rx_done_s <= '1';
221                                         else
222                                                 lxmaster_state_s           <= ST_READY; -- Make next read init the transfer
223                                                 ram_addr_v                   := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
224                                                 ram_addr_s                   <= ram_addr_v;
225                                                 lxmaster_num_data_s          <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
226                                                 ram_en_s                     <= '1'; -- Read
227                                         end if;
228
229                                         -- Prepare message counter
230                                         lxmaster_msg_counter_s       <= 0;
231
232                                         lxmaster_crc_error_int_s     <= '0';
233
234                                 when ST_READY =>
235                                         -- We are ready to begin transferring
236                                         lxmaster_data_counter_s      <= 0; -- Reset counter
237                                         lxmaster_state_s             <= ST_XFER; --Go to transfer loop
238
239                                 when ST_XFER =>
240
241                                         if inc_ram_addr_r = '1' then
242                                                 -- Update address if second and other loop
243                                                 ram_addr_s  <= ram_addr_r(8) & (ram_addr_r(7 downto 0) + 1);
244                                         end if;
245
246                                         if lxmaster_data_counter_r = 14 then
247                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
248
249                                                 if (ram_addr_r(7 downto 0) + 1) /= lxmaster_num_data_r then
250                                                         lxmaster_last_word_s       <= '0';
251                                                 else
252                                                         lxmaster_last_word_s       <= '1';
253                                                 end if;
254
255                                         elsif lxmaster_data_counter_r = 15 then
256                                                 -- At 15th bit, we either stop if ram_addr_r equals lxmaster_num_data_r
257                                                 if lxmaster_last_word_r = '1' then
258                                                         lxmaster_state_s         <= ST_CRC;
259                                                         lxmaster_data_counter_s  <= 0;
260                                                 else
261                                                         lxmaster_data_counter_s  <= 0;
262                                                 end if;
263
264                                                 ram_we_s                   <= "11";
265                                                 ram_en_s                   <= '1';
266                                                 inc_ram_addr_s             <= '1';
267                                         else
268                                                 -- Increment
269                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1;
270                                         end if;
271
272                                 when ST_CRC =>
273
274                                         if received_data_r(received_data_r'length - 1) /= lxmaster_crc_reg_r(0) then
275                                                 crc_bit_mismatch_v := '1';
276                                         else
277                                                 crc_bit_mismatch_v := '0';
278                                         end if;
279
280                                         if crc_bit_mismatch_v = '1' then
281                                                 lxmaster_crc_error_int_s <= '1';
282                                         end if;
283
284                                         -- Check if this is last command, first read one more
285                                         if lxmaster_data_counter_r = 0 then
286                                                 if lxmaster_msg_counter_r = (msg_max_count_c - 1) then
287                                                         lxmaster_ram_reset_s     <= '1'; -- Make sure we read 0 if we are on the last message
288                                                 else
289                                                         lxmaster_msg_counter_s  <= lxmaster_msg_counter_r + 1;
290                                                 end if;
291
292                                                 ram_addr_s                 <= ram_addr_r(8) & std_logic_vector(to_unsigned(lxmaster_msg_counter_r + 1, ram_addr_r'length - 1)); -- Update address
293                                                 ram_en_s                   <= '1'; -- Read
294
295                                         elsif lxmaster_data_counter_r = 1 then
296
297                                                 if ram_data_o_s(15 downto 8) >= msg_max_count_c then -- Need to read first command, make sure it's valid
298                                                         ram_addr_v               := ram_addr_r(8) & ram_data_o_s(15 downto 8); -- Update address
299                                                         ram_addr_s               <= ram_addr_v;
300                                                         lxmaster_num_data_s      <= std_logic_vector(unsigned(ram_addr_v(7 downto 0)) + unsigned(ram_data_o_s(7 downto 0)));
301                                                         ram_en_s                 <= '1'; -- Read
302                                                 else
303                                                         lxmaster_num_data_s      <= x"00"; -- Signalize termination
304                                                 end if;
305
306                                         end if;
307
308                                         if lxmaster_data_counter_r = 7 then -- Ending
309                                                 lxmaster_data_counter_s    <= 0;
310
311                                                 if lxmaster_num_data_r = x"00" then
312                                                         lxmaster_state_s         <= ST_END; -- Last command
313                                                         rx_done_s <= '1';
314                                                         lxmaster_crc_error_s     <= lxmaster_crc_error_int_r or crc_bit_mismatch_v;
315                                                 else
316                                                         -- Begin transmission of next data
317                                                         lxmaster_data_counter_s  <= 0; -- Reset counter
318                                                         lxmaster_state_s         <= ST_XFER; --Go to transfer loop
319                                                 end if;
320
321                                         else
322                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
323                                         end if;
324
325                                 when ST_END =>
326                                         if lxmaster_frame_start_s = '1' then
327                                                 -- Initialize first step
328                                                 lxmaster_state_s           <= ST_INIT;
329                                                 ram_addr_s                 <= lxmaster_register_in_s & x"00";
330                                                 ram_en_s                   <= '1';
331                                         end if;
332
333                         end case;
334
335                 end if;
336
337         end process;
338
339 -- This function toggles outputs directly, make sure the outputs
340 -- are updated with clock to minimize phase.
341 state:
342         process
343         begin
344
345                 wait until clk_i'event and clk_i = '1';
346
347                 -- State update
348                 ram_addr_r                     <= ram_addr_s;
349                 inc_ram_addr_r                 <= inc_ram_addr_s;
350                 lxmaster_state_r               <= lxmaster_state_s;
351                 lxmaster_data_counter_r        <= lxmaster_data_counter_s;
352                 lxmaster_num_data_r            <= lxmaster_num_data_s;
353                 lxmaster_crc_reg_r             <= lxmaster_crc_reg_s;
354                 lxmaster_msg_counter_r         <= lxmaster_msg_counter_s;
355                 lxmaster_last_word_r           <= lxmaster_last_word_s;
356                 lxmaster_crc_error_int_r       <= lxmaster_crc_error_int_s;
357                 lxmaster_crc_error_r           <= lxmaster_crc_error_s;
358
359                 rx_done_o                      <= rx_done_s;
360
361                 -- Increment counter
362                 if reset_i = '1' then
363
364                         lxmaster_register_in_s       <= '0';
365                         lxmaster_register_out_s      <= (others => '0');
366                         lxmaster_last_word_r         <= '1';
367
368                 else
369
370                         if register_we_i = '1' then
371                                 lxmaster_register_in_s     <= register_i;
372                         end if;
373
374                         if lxmaster_frame_start_s = '1' then
375                                 lxmaster_register_out_s(0) <= lxmaster_register_in_s;
376                         end if;
377
378                         if lxmaster_state_s = ST_END then
379                                 lxmaster_register_out_s(1)  <= '0';
380                         else
381                                 lxmaster_register_out_s(1)  <= '1';
382                         end if;
383                 end if;
384
385                 prev_sync_r <= prev_sync_s;
386                 received_data_r <= received_data_s;
387
388         end process;
389
390 end Behavioral;