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