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