]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/lxmaster_transmitter.vhd
Update LX PWR communication
[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;
21                 register_we_i     : in std_logic;
22                 -- BRAM access
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)
29         );
30 end lxmaster_transmitter;
31
32 architecture Behavioral of lxmaster_transmitter is
33
34         -- Types
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;
40         --
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);
44         -- State
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;
49         -- Data
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);
56         -- Transmission
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;
61         -- Frame counter
62         signal lxmaster_frame_counter_s : natural range 0 to (frame_length_c-1);
63         -- CRC
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);
69         -- RAM reset
70         signal lxmaster_ram_reset_s     : std_logic;
71         -- Register
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;
75
76 begin
77
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);
84         -- CRC
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';
88
89         -- Register
90         register_o           <= lxmaster_register_out_s;
91
92 ram: xilinx_dualport_bram_write_first
93         generic map
94         (
95                 we_width      => 2,
96                 byte_width    => 8,
97                 address_width => 9
98         )
99         port map
100         (
101                 -- Internal
102                 clka  => clk_i,
103                 rsta  => ram_rst_s,
104                 ena   => ram_en_s,
105                 wea   => (others => '0'),
106                 addra => ram_addr_s,
107                 dina  => (others => '0'),
108                 douta => ram_data_o_s,
109                 -- External
110                 clkb  => mem_clk_i,
111                 rstb  => '0',
112                 enb   => mem_en_i,
113                 web   => mem_we_i,
114                 addrb => mem_addr_i,
115                 dinb  => mem_data_i,
116                 doutb => mem_data_o
117         );
118
119 crc_out: crc
120         port map
121         (
122                 clk_i   => clk_i,
123                 reset_i => lxmaster_crc_reset_s,
124                 input_i => lxmaster_crc_data_s,
125                 crc_o   => lxmaster_crc_out_s
126         );
127
128         ram_rst_s <= reset_i or lxmaster_ram_reset_s;
129
130 -- Update
131 -- TODO: Maybe some exception handling (overflows etc.)
132 transmitter_update:
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);
136         begin
137
138                 -- Defaults
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;
148
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';
154                         --
155                         ram_addr_s                       <= '0' & x"00";
156                         ram_en_s                         <= '0';
157                         --
158                         lxmaster_ram_reset_s             <= '1';
159
160                 else
161
162                         -- OK, we are enabled, default values
163                         lxmaster_sync_s                  <= '0'; -- Not transferring
164                         ram_en_s                         <= '0'; -- Not reading
165
166                         case lxmaster_state_r is
167
168                                 when ST_INIT =>
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
172                                         else
173                                                 lxmaster_state_s           <= ST_READY; -- Make next read init the transfer
174                                         end if;
175
176                                         -- Regardless, write the number of data
177                                         lxmaster_num_data_s          <= ram_data_o_s(7 downto 0);
178
179                                         -- And schedule reading
180                                         ram_addr_s                   <= ram_addr_r + 1; -- Update address
181                                         ram_en_s                     <= '1'; -- Read
182
183                                 when ST_READY =>
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
190
191                                 when ST_XFER =>
192                                         lxmaster_loaded_data_s       <= '0' & lxmaster_loaded_data_r(15 downto 1); -- Shift it
193                                         lxmaster_sync_s              <= '1'; -- Transferring data next cycle
194
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";
206                                                 else
207                                                         lxmaster_loaded_data_s   <= ram_data_o_s;
208                                                         lxmaster_data_counter_s  <= x"0";
209                                                         lxmaster_not_last_word_s <= '0';
210                                                 end if;
211                                         else
212                                                 -- Increment
213                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1;
214                                         end if;
215
216                                 when ST_CRC =>
217
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
222                                                 end if;
223
224                                                 ram_addr_s                 <= ram_addr_r + 1; -- Update address
225                                                 ram_en_s                   <= '1'; -- Read
226
227                                         elsif lxmaster_data_counter_r = x"1" then
228
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
234                                                 else
235                                                         lxmaster_num_data_s      <= x"00"; -- Signalize termination
236                                                 end if;
237
238                                         end if;
239
240                                         if lxmaster_data_counter_r = x"7" then -- Ending
241                                                 lxmaster_data_counter_s    <= x"0";
242
243                                                 if lxmaster_num_data_r(7 downto 0) = x"00" then
244                                                         lxmaster_state_s         <= ST_END; -- Last command
245                                                 else
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
252                                                 end if;
253
254                                         else
255                                                 if lxmaster_data_counter_r /= x"6" then
256                                                         lxmaster_sync_s          <= '1'; -- Sync goes inactive to signalize termination
257                                                 else
258                                                   lxmaster_sync_last_bit_s <= '1';
259                                                 end if;
260
261                                                 lxmaster_data_counter_s    <= lxmaster_data_counter_r + 1; -- Increment
262                                         end if;
263
264                                 when ST_END =>
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";
269                                                 ram_en_s                   <= '1';
270                                         end if;
271
272                         end case;
273
274                 end if;
275
276         end process;
277
278 -- This function toggles outputs directly, make sure the outputs
279 -- are updated with clock to minimize phase.
280 state:
281         process
282         begin
283
284                 wait until clk_i'event and clk_i = '1';
285
286                 -- State update
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;
294
295                 -- Increment counter
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';
300                 else
301
302                         if register_we_i = '1' then
303                                 lxmaster_register_in_s   <= register_i;
304                         end if;
305
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;
309                         else
310                                 lxmaster_frame_counter_s <= lxmaster_frame_counter_s + 1;
311                         end if;
312
313                 end if;
314
315                 lxmaster_sync_r              <= lxmaster_sync_s;
316                 lxmaster_sync_last_bit_r     <= lxmaster_sync_last_bit_s;
317
318         end process;
319
320 end Behavioral;