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