]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/bus_tumbl.vhd
IRC coprocessor with muxed access between Master CPU and Tumbl
[fpga/lx-cpu1/lx-rocon.git] / hw / bus_tumbl.vhd
1 library ieee;
2
3 use ieee.std_logic_1164.all;
4 use ieee.std_logic_arith.all;
5 use ieee.std_logic_unsigned.all;
6 use ieee.numeric_std.all;
7 use work.mbl_Pkg.all;
8 use work.lx_rocon_pkg.all;
9
10 -- Connects tumbl to the Master CPU
11
12 entity bus_tumbl is
13         port
14         (
15                 -- Clock
16                 clk_100m_i       : in std_logic;
17                 clk_50m_i        : in std_logic;
18                 -- Chip enable
19                 ce_100m_i        : in std_logic;
20                 -- Global Reset
21                 reset_100m_i     : in std_logic;
22                 -- Master CPU bus for the memory
23     rd_100m_i        : in std_logic;
24     bls_100m_i       : in std_logic_vector(3 downto 0);
25     address_100m_i   : in std_logic_vector(11 downto 0);
26     data_100m_i      : in std_logic_vector(31 downto 0);
27     data_100m_o      : out std_logic_vector(31 downto 0);
28                 ta_100m_o        : out std_logic;
29                 -- Tumbl extrenal memory bus
30                 xmemb_sel_100m_o : out std_logic;
31                 xmemb_100m_i     : in DMEMB2CORE_Type;
32                 xmemb_100m_o     : out CORE2DMEMB_Type
33   );
34 end bus_tumbl;
35
36 architecture Behavioral of bus_tumbl is
37
38         -- Internal state
39         -- The following signals are driven by 100M clock
40         signal tumbl_reset_100m_s : std_logic;
41         signal tumbl_halt_100m_s  : std_logic;
42         signal tumbl_int_100m_s   : std_logic;
43         signal tumbl_trace_100m_s : std_logic;
44
45         -- The following signals kick in at 50M clock
46         signal tumbl_reset_50m_s  : std_logic;
47         signal tumbl_halt_50m_s   : std_logic;
48         signal tumbl_int_50m_s    : std_logic;
49         signal tumbl_trace_50m_s  : std_logic;
50
51         -- Trace kick (since this is "one cycle command", it needs req / ack)
52         signal tumbl_trace_kick_50m_s      : std_logic;
53         signal tumbl_trace_kick_ack_50m_s  : std_logic;
54         signal tumbl_trace_kick_req_100m_s : std_logic;
55
56         -- Tumbl PC (copy it with cpu clock and then wire further)
57         signal tumbl_pc_50m_s         : std_logic_vector(31 downto 0);
58
59         -- Halting using halt instruction
60         -- Driven by 50M clock
61         signal tumbl_halted_50m_s     : std_logic;
62         signal tumbl_halt_code_50m_s  : std_logic_vector(4 downto 0);
63
64         -- Tumbl signals under 100M domain
65         -- Driven by 100M clock
66         signal tumbl_pc_100m_s        : std_logic_vector(31 downto 0);
67         signal tumbl_halted_100m_s    : std_logic;
68         signal tumbl_halt_code_100m_s : std_logic_vector(4 downto 0);
69
70         -- Internal memory signals
71         -- Driven by 100M clock
72         signal imem_en_100m_s     : std_logic;
73         signal dmem_en_100m_s     : std_logic;
74
75         signal imem_we_100m_s     : std_logic_vector(3 downto 0);
76         signal dmem_we_100m_s     : std_logic_vector(3 downto 0);
77
78         signal imem_data_o_100m_s : std_logic_vector(31 downto 0);
79         signal dmem_data_o_100m_s : std_logic_vector(31 downto 0);
80
81         -- Tumbl external memory
82         -- Driven by 50M clock
83         signal xmemb_sel_50m_s    : std_logic;
84         signal xmemb_50m_i_s      : DMEMB2CORE_Type;
85         signal xmemb_50m_o_s      : CORE2DMEMB_Type;
86
87         -- Internal bus structure
88         -- 12 address bits: 2 bits for selection, 10 bits for address
89         --
90         -- Selection:
91         -- 00 - imem
92         -- 01 - dmem
93         -- 10 - reserved
94         -- 11 - registers
95
96         -- Registers
97         -- 0x000
98         --
99         -- Bit 0: RW - Reset
100         -- Bit 1: RW - Interrupt
101         -- Bit 2: RW - Halt
102         -- Bit 3: RW - Trace
103         -- Bit 4: R  - Halted
104
105         -- 0x001
106         -- Bit 0: W - Write 1 for trace kick
107
108         -- 0x002
109         -- Tumbl program counter (R)
110
111   -- 0x003
112         -- Halt code
113
114 begin
115
116         -- Wire it to the tumbl
117         I_TUMBL: lx_rocon_tumbl
118         generic map
119         (
120                 IMEM_ABITS_g => 11,
121                 DMEM_ABITS_g => 12,
122                 --
123                 USE_HW_MUL_g => true,
124                 USE_BARREL_g => true,
125                 COMPATIBILITY_MODE_g => false
126         )
127         port map
128         (
129                 clk_i        => clk_50m_i,
130                 rst_i        => tumbl_reset_50m_s,
131                 halt_i       => tumbl_halt_50m_s,
132                 int_i        => tumbl_int_50m_s,
133                 trace_i      => tumbl_trace_50m_s,
134                 trace_kick_i => tumbl_trace_kick_50m_s,
135
136                 pc_o         => tumbl_pc_50m_s,
137                 halted_o     => tumbl_halted_50m_s,
138                 halt_code_o  => tumbl_halt_code_50m_s,
139
140                 -- Internal memory (instruction)
141                 imem_clk_i   => clk_100m_i,
142     imem_en_i    => imem_en_100m_s,
143     imem_we_i    => imem_we_100m_s,
144     imem_addr_i  => address_100m_i(8 downto 0),
145     imem_data_i  => data_100m_i,
146     imem_data_o  => imem_data_o_100m_s,
147
148                 -- Internal memory (data)
149                 dmem_clk_i   => clk_100m_i,
150     dmem_en_i    => dmem_en_100m_s,
151     dmem_we_i    => dmem_we_100m_s,
152     dmem_addr_i  => address_100m_i(9 downto 0),
153     dmem_data_i  => data_100m_i,
154     dmem_data_o  => dmem_data_o_100m_s,
155
156                 -- External memory bus
157                 xmemb_sel_o  => xmemb_sel_50m_s,
158                 xmemb_i      => xmemb_50m_i_s,
159                 xmemb_o      => xmemb_50m_o_s
160         );
161
162         -- Enabling
163         enabling: process(ce_100m_i, address_100m_i)
164         begin
165
166                 if ce_100m_i = '1' and address_100m_i(11 downto 10) = "00" then
167                         imem_en_100m_s <= '1';
168                 else
169                         imem_en_100m_s <= '0';
170                 end if;
171
172                 if ce_100m_i = '1' and address_100m_i(11 downto 10) = "01" then
173                         dmem_en_100m_s <= '1';
174                 else
175                         dmem_en_100m_s <= '0';
176                 end if;
177
178         end process;
179
180         -- Wiring
181         -- NOTE: This is only modifying signals inside 100m domain
182         wiring: process(ce_100m_i, rd_100m_i, bls_100m_i, address_100m_i, imem_en_100m_s, imem_data_o_100m_s, dmem_en_100m_s,
183                                                                         dmem_data_o_100m_s, tumbl_reset_100m_s, tumbl_int_100m_s, tumbl_halt_100m_s, tumbl_trace_100m_s,
184                                                                         tumbl_halted_100m_s, tumbl_halt_code_100m_s, tumbl_pc_100m_s)
185         begin
186
187                 if imem_en_100m_s = '1' then
188                         imem_we_100m_s <= bls_100m_i;
189                 else
190                         imem_we_100m_s <= "0000";
191                 end if;
192
193                 if dmem_en_100m_s = '1' then
194                         dmem_we_100m_s <= bls_100m_i;
195                 else
196                         dmem_we_100m_s <= "0000";
197                 end if;
198
199                 if imem_en_100m_s = '1' then
200                         data_100m_o <= imem_data_o_100m_s;
201                 elsif dmem_en_100m_s = '1' then
202                         data_100m_o <= dmem_data_o_100m_s;
203                 elsif ce_100m_i = '1' and rd_100m_i = '1' and address_100m_i(11 downto 10) = "11" then
204                         if address_100m_i(9 downto 0) = "0000000000" then
205                                 data_100m_o(0) <= tumbl_reset_100m_s;
206                                 data_100m_o(1) <= tumbl_int_100m_s;
207                                 data_100m_o(2) <= tumbl_halt_100m_s;
208                                 data_100m_o(3) <= tumbl_trace_100m_s;
209                                 data_100m_o(4) <= tumbl_halted_100m_s;
210                                 data_100m_o(31 downto 5) <= (others => '0');
211                         elsif address_100m_i(9 downto 0) = "0000000010" then
212                                 data_100m_o <= tumbl_pc_100m_s;
213                         elsif address_100m_i(9 downto 0) = "0000000011" then
214                                 data_100m_o(4 downto 0)  <= tumbl_halt_code_100m_s;
215                                 data_100m_o(31 downto 5) <= (others => '0');
216                         else
217                                 data_100m_o <= (others => 'X');
218                         end if;
219                 else
220                         data_100m_o <= (others => 'X');
221                 end if;
222
223         end process;
224
225         -- Transaction acknowledge and writing to registers
226         -- The clocks are synchronous!
227         update: process(clk_100m_i)
228         begin
229
230                 -- Update on the 100 MHz clock
231                 if clk_100m_i = '1' and clk_100m_i'event then
232                         ta_100m_o <= '0';
233
234                         -- Copy the 50M driven signals to 100M domain
235                         tumbl_pc_100m_s        <= tumbl_pc_50m_s;
236                         tumbl_halted_100m_s    <= tumbl_halted_50m_s;
237                         tumbl_halt_code_100m_s <= tumbl_halt_code_50m_s;
238                         --
239                         xmemb_sel_100m_o       <= xmemb_sel_50m_s;
240                         xmemb_100m_o           <= xmemb_50m_o_s;
241
242                         if imem_en_100m_s = '1' or dmem_en_100m_s = '1' then
243                                 ta_100m_o <= '1';
244                         end if;
245
246                         if reset_100m_i = '1' then
247                                 tumbl_reset_100m_s            <= '1';
248                                 tumbl_int_100m_s              <= '0';
249                                 tumbl_halt_100m_s             <= '0';
250                                 tumbl_trace_100m_s            <= '0';
251                                 tumbl_trace_kick_req_100m_s   <= '0';
252                         else
253                                 if tumbl_trace_kick_ack_50m_s = '1' then
254                                         tumbl_trace_kick_req_100m_s <= '0';
255                                 end if;
256
257                                 if ce_100m_i = '1' and address_100m_i(11 downto 10) = "11" then
258                                         if bls_100m_i(0) = '1' then
259                                                 if address_100m_i(9 downto 0) = "0000000000" then
260                                                         tumbl_reset_100m_s      <= data_100m_i(0);
261                                                         tumbl_int_100m_s        <= data_100m_i(1);
262                                                         tumbl_halt_100m_s       <= data_100m_i(2);
263                                                         tumbl_trace_100m_s      <= data_100m_i(3);
264                                                 elsif address_100m_i(9 downto 0) = "0000000001" then
265                                                         if data_100m_i(0) = '1' then
266                                                                 tumbl_trace_kick_req_100m_s <= '1';
267                                                         end if;
268                                                 end if;
269                                         end if;
270
271                                         if rd_100m_i = '1' then
272                                                 ta_100m_o <= '1';
273                                         end if;
274                                 end if;
275                         end if;
276
277                 end if;
278         end process;
279
280         -- Update tracing
281         tumbl: process(clk_50m_i)
282         begin
283
284                 -- Update on the 50 MHz clock
285                 if clk_50m_i = '1' and clk_50m_i'event then
286
287                         -- Copy the 100M driven signals to their 50M domain
288                         -- and then route them further
289                         tumbl_reset_50m_s <= tumbl_reset_100m_s;
290                         tumbl_int_50m_s   <= tumbl_int_100m_s;
291                         tumbl_halt_50m_s  <= tumbl_halt_100m_s;
292                         tumbl_trace_50m_s <= tumbl_trace_100m_s;
293                         --
294                         xmemb_50m_i_s     <= xmemb_100m_i;
295
296                         if reset_100m_i = '1' then
297                                 tumbl_trace_kick_50m_s       <= '0';
298                                 tumbl_trace_kick_ack_50m_s   <= '0';
299                         else
300                                 if tumbl_trace_kick_50m_s = '0' and tumbl_trace_kick_req_100m_s = '1' then
301                                         tumbl_trace_kick_50m_s     <= '1';
302                                         tumbl_trace_kick_ack_50m_s <= '1';
303                                 else
304                                         tumbl_trace_kick_50m_s     <= '0';
305                                 end if;
306                         end if;
307
308                         if tumbl_trace_kick_req_100m_s = '0' then
309                                 tumbl_trace_kick_ack_50m_s   <= '0';
310                         end if;
311
312                 end if;
313
314         end process;
315
316 end Behavioral;