]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/bus_lxmaster.vhd
pxmc: I component accumulator with long type and PXMC_SUBDIV argument protection.
[fpga/lx-cpu1/lx-rocon.git] / hw / bus_lxmaster.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.lx_rocon_pkg.all;
6
7 -- LX Master bus interconnect
8 entity bus_lxmaster is
9         port
10         (
11                 clk_i        : in std_logic;
12                 reset_i      : in std_logic;
13                 -- Data bus
14                 address_i    : in std_logic_vector(10 downto 0);
15                 ce_i         : in std_logic;
16                 data_i       : in std_logic_vector(15 downto 0);
17                 data_o       : out std_logic_vector(15 downto 0);
18                 --
19                 bls_i        : in std_logic_vector(1 downto 0);
20                 --
21                 rx_done_o    : out std_logic;
22                 -- Signals for LX Master
23                 clock_i      : in std_logic;
24                 miso_i       : in std_logic;
25                 sync_i       : in std_logic;
26                 --
27                 clock_o      : out std_logic;
28                 mosi_o       : out std_logic;
29                 sync_o       : out std_logic
30         );
31 end bus_lxmaster;
32
33 architecture Behavioral of bus_lxmaster is
34
35         constant cycle_cnt_width_c  : natural := 12; -- number of bits
36         constant rx_done_div_width_c : natural := 5; -- number of bits
37         constant rx_done_cnt_width_c : natural := 5; -- number of bits
38
39         signal mem_trans_en_s       : std_logic;
40         signal mem_trans_bls_s      : std_logic_vector(1 downto 0);
41         signal mem_trans_addr_s     : std_logic_vector(8 downto 0);
42         signal mem_trans_data_s     : std_logic_vector(15 downto 0);
43         signal mem_trans_out_s      : std_logic;
44         signal mem_trans_out_r      : std_logic;
45         --
46         signal mem_recv_en_s        : std_logic;
47         signal mem_recv_bls_s       : std_logic_vector(1 downto 0);
48         signal mem_recv_addr_s      : std_logic_vector(8 downto 0);
49         signal mem_recv_data_s      : std_logic_vector(15 downto 0);
50         signal mem_recv_out_s       : std_logic;
51         signal mem_recv_out_r       : std_logic;
52         --
53         signal state_o_s            : std_logic_vector(15 downto 0);
54         signal state_o_r            : std_logic_vector(15 downto 0);
55         --
56         signal reset_reg_s          : std_logic;
57         signal reset_reg_r          : std_logic;
58         signal reset_reg_wr_s       : std_logic;
59         --
60         signal reset_s              : std_logic;
61         signal ce_r                 : std_logic;
62         --
63         signal register_trans_in_s  : std_logic;
64         signal register_trans_out_s : std_logic_vector(1 downto 0);
65         signal register_trans_wr_s  : std_logic;
66         signal register_cycle_in_s  : std_logic_vector(cycle_cnt_width_c-1 downto 0);
67         signal register_cycle_out_s : std_logic_vector(cycle_cnt_width_c-1 downto 0);
68         signal register_cycle_wr_s  : std_logic;
69         signal wdog_trans_in_s      : std_logic;
70         signal wdog_trans_wr_s      : std_logic;
71         --
72         signal register_recv_in_s   : std_logic;
73         signal register_recv_out_s  : std_logic_vector(1 downto 0);
74         signal register_recv_wr_s   : std_logic;
75         signal rx_done_s            : std_logic;
76         signal rx_done_ratio_s      : std_logic_vector(rx_done_div_width_c-1 downto 0);
77         signal rx_done_ratio_r      : std_logic_vector(rx_done_div_width_c-1 downto 0);
78         signal rx_done_ratio_wr_s   : std_logic;
79         signal rx_done_cnt_r        : natural range 0 to (2**rx_done_cnt_width_c - 1);
80         --
81         signal rx_crc_error_s       : std_logic;
82         signal rx_crc_error_r       : std_logic;
83 begin
84
85 master_transmitter: lxmaster_transmitter
86         generic map
87         (
88                 cycle_cnt_width_g => cycle_cnt_width_c
89         )
90         port map
91         (
92                 clk_i            => clk_i,
93                 reset_i          => reset_s,
94                 -- Transmission
95                 clock_o          => clock_o,
96                 mosi_o           => mosi_o,
97                 sync_o           => sync_o,
98                 -- Register
99                 register_i       => register_trans_in_s,
100                 register_o       => register_trans_out_s,
101                 register_we_i    => register_trans_wr_s,
102                 -- Cycle period
103                 cycle_reg_i      => register_cycle_in_s,
104                 cycle_reg_o      => register_cycle_out_s,
105                 cycle_reg_we_i   => register_cycle_wr_s,
106                 -- Watchdog
107                 wdog_i           => wdog_trans_in_s,
108                 wdog_we_i        => wdog_trans_wr_s,
109                 -- BRAM
110                 mem_clk_i        => clk_i,
111                 mem_en_i         => mem_trans_en_s,
112                 mem_we_i         => mem_trans_bls_s,
113                 mem_addr_i       => mem_trans_addr_s,
114                 mem_data_i       => data_i,
115                 mem_data_o       => mem_trans_data_s
116         );
117
118 master_receiver: lxmaster_receiver
119         port map
120         (
121                 clk_i            => clk_i,
122                 reset_i          => reset_s,
123                 -- Receiver serial data
124                 clock_i          => clock_i,
125                 miso_i           => miso_i,
126                 sync_i           => sync_i,
127                 -- Receive done pulse
128                 rx_done_o        => rx_done_s,
129                 rx_crc_error_o   => rx_crc_error_s,
130                 -- Register
131                 register_i       => register_recv_in_s,
132                 register_o       => register_recv_out_s,
133                 register_we_i    => register_recv_wr_s,
134                 -- BRAM
135                 mem_clk_i        => clk_i,
136                 mem_en_i         => mem_recv_en_s,
137                 mem_we_i         => mem_recv_bls_s,
138                 mem_addr_i       => mem_recv_addr_s,
139                 mem_data_i       => data_i,
140                 mem_data_o       => mem_recv_data_s
141         );
142
143 rx_done_divider : cnt_div
144         generic map (
145                 cnt_width_g      => rx_done_div_width_c
146         )
147         port map
148         (
149                 clk_i            => clk_i,
150                 en_i             => rx_done_s,
151                 reset_i          => reset_s,
152                 ratio_i          => rx_done_ratio_r,
153                 q_out_o          => rx_done_o
154         );
155
156         reset_s <= reset_reg_r or reset_i;
157
158
159 wire_in:
160         process(ce_i, ce_r, reset_reg_r, bls_i, address_i, mem_trans_data_s,
161                 mem_recv_data_s, data_i, register_trans_out_s, register_recv_out_s,
162                 register_cycle_out_s, rx_done_ratio_r, rx_done_cnt_r, rx_crc_error_r)
163         begin
164
165                 mem_trans_en_s       <= '0';
166                 mem_trans_out_s      <= '0';
167                 mem_trans_bls_s      <= (others => '0');
168                 mem_trans_addr_s     <= (others => '0');
169                 mem_recv_en_s        <= '0';
170                 mem_recv_out_s       <= '0';
171                 mem_recv_bls_s       <= (others => '0');
172                 mem_recv_addr_s      <= (others => '0');
173                 state_o_s            <= (others => '0');
174                 reset_reg_s          <= '0';
175                 reset_reg_wr_s       <= '0';
176                 register_trans_in_s  <= '0';
177                 register_trans_wr_s  <= '0';
178                 register_cycle_in_s  <= (others => '0');
179                 register_cycle_wr_s  <= '0';
180                 register_recv_in_s   <= '0';
181                 register_recv_wr_s   <= '0';
182                 wdog_trans_in_s      <= '0';
183                 wdog_trans_wr_s      <= '0';
184                 rx_done_ratio_wr_s   <= '0';
185                 rx_done_ratio_s      <= rx_done_ratio_r;
186
187                 -- Incoming bus request
188                 if ce_i = '1' then
189
190                         -- Mapping:
191                         -- 00 & xxxxxxxx - LX Master transmitter BRAM
192                         -- 01 & xxxxxxxx - LX Master receiver BRAM
193                         -- 10 & 00000000 - LX Master reset
194                         -- 10 & 00000001 - LX Master transmitter register
195                         -- 10 & 00000010 - LX Master watchdog
196                         -- 10 & 00000011 - LX Master cycle period register
197                         -- 10 & 00000100 - LX Master receiver control register
198                         if address_i(10 downto 9) = "00" then
199
200                                 mem_trans_addr_s    <= address_i(8 downto 0);
201                                 mem_trans_en_s      <= '1';
202                                 mem_trans_bls_s     <= bls_i;
203                                 mem_trans_out_s     <= '1';
204
205                         elsif address_i(10 downto 9) = "01" then
206
207                                 mem_recv_addr_s     <= address_i(8 downto 0);
208                                 mem_recv_en_s       <= '1';
209                                 mem_recv_bls_s      <= bls_i;
210                                 mem_recv_out_s      <= '1';
211
212                         else
213
214                                 if address_i(8 downto 3) = "000000" then
215
216                                         if address_i(2 downto 0) = "000" then
217                                                 -- LX Master reset
218                                                 if bls_i(0) = '1' then
219                                                         reset_reg_s          <= data_i(0);
220                                                         reset_reg_wr_s       <= '1';
221                                                 else
222                                                         -- Ugh, hack :-)
223                                                         state_o_s(0)         <= reset_reg_r;
224                                                         state_o_s(1)         <= '0';
225                                                         state_o_s(15 downto 2) <= (others => '0');
226                                                 end if;
227                                         elsif address_i(2 downto 0) = "001" then
228                                                 -- LX Master register
229                                                 if bls_i(0) = '1' then
230                                                         register_trans_in_s  <= data_i(0);
231                                                         register_trans_wr_s  <= '1';
232                                                 else
233                                                         state_o_s(1 downto 0) <= register_trans_out_s;
234                                                         state_o_s(15 downto 2) <= (others => '0');
235                                                 end if;
236                                         elsif address_i(2 downto 0) = "010" then
237                                                 if bls_i(0) = '1' then
238                                                         wdog_trans_in_s      <= data_i(0);
239                                                         wdog_trans_wr_s      <= '1';
240                                                 end if;
241                                         elsif address_i(2 downto 0) = "011" then
242                                                 -- LX Master period register
243                                                 if bls_i(0) = '1' then
244                                                         register_cycle_in_s  <= data_i(cycle_cnt_width_c-1 downto 0);
245                                                         register_cycle_wr_s  <= '1';
246                                                 else
247                                                         state_o_s            <= (15 downto cycle_cnt_width_c => '0') &
248                                                                                 register_cycle_out_s;
249                                                 end if;
250                                         elsif address_i(2 downto 0) = "100" then
251                                                 if bls_i(0) = '1' then
252                                                         register_recv_in_s  <= data_i(0);
253                                                         register_recv_wr_s  <= '1';
254                                                 else
255                                                         state_o_s(1 downto 0) <= register_recv_out_s;
256                                                         state_o_s(15 downto 2) <= (others => '0');
257                                                 end if;
258                                         elsif address_i(2 downto 0) = "101" then
259                                                 -- LX Master receiver done divisor
260                                                 if bls_i(0) = '1' then
261                                                         rx_done_ratio_s <= data_i(rx_done_div_width_c + 8 - 1 downto 8);
262                                                         rx_done_ratio_wr_s  <= '1';
263                                                 else
264                                                         state_o_s(rx_done_cnt_width_c - 1 downto 0) <= 
265                                                                 std_logic_vector(to_unsigned(rx_done_cnt_r, rx_done_cnt_width_c));
266                                                         state_o_s(7 downto rx_done_cnt_width_c) <= (others => '0');
267                                                         state_o_s(rx_done_div_width_c + 8 - 1 downto 8) <= rx_done_ratio_r;
268                                                         state_o_s(14 downto rx_done_div_width_c + 8) <= (others => '0');
269                                                         state_o_s(15) <= rx_crc_error_r;
270                                                 end if;
271                                         end if;
272
273                                 end if;
274                         end if;
275                 end if;
276
277         end process;
278
279 wire_out:
280         process(ce_r, mem_trans_data_s, mem_trans_out_r, 
281                 mem_recv_data_s, mem_recv_out_r, state_o_r)
282         begin
283
284                 data_o <= (others => '0');
285
286                 if ce_r = '1' then
287                         if mem_trans_out_r = '1' then
288                                 data_o             <= mem_trans_data_s;
289                         elsif mem_recv_out_r = '1' then
290                                 data_o             <= mem_recv_data_s;
291                         else
292                                 data_o             <= state_o_r;
293                         end if;
294                 end if;
295
296         end process;
297
298 update:
299         process
300         begin
301                 wait until clk_i'event and clk_i= '1';
302                 ce_r            <= ce_i;
303                 mem_trans_out_r <= mem_trans_out_s;
304                 mem_recv_out_r  <= mem_recv_out_s;
305                 state_o_r       <= state_o_s;
306
307                 if reset_i = '1' then
308                         reset_reg_r   <= '1';
309                 elsif reset_reg_wr_s = '1' then
310                         reset_reg_r   <= reset_reg_s;
311                 end if;
312
313                 if reset_i = '1' then
314                         rx_done_ratio_r <= ( 0 => '1', others => '0');
315                 elsif rx_done_ratio_wr_s = '1' then
316                         rx_done_ratio_r <= rx_done_ratio_s;
317                 end if;
318
319                 if reset_i = '1' then
320                         rx_done_cnt_r <= 0;
321                         rx_crc_error_r <= '0';
322                 elsif rx_done_s = '1' then
323                         rx_done_cnt_r <= rx_done_cnt_r + 1;
324                         rx_crc_error_r <= rx_crc_error_s;
325                 end if;
326
327         end process;
328
329 end Behavioral;