]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - hw/lx_rocon_top.vhd
Add FPGA sources with Makefile
[fpga/lx-cpu1/lx-rocon.git] / hw / lx_rocon_top.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_arith.all;
4 use ieee.std_logic_unsigned.all;
5 use ieee.numeric_std.all;
6
7 -- lx_rocon_top - wires the modules with outside world
8
9 -- ======================================================
10 --  INTERNAL MEMORY BUS
11 -- ======================================================
12 --
13 -- Internal memory bus has the following wires:
14 --
15 -- - address[15..0]          The address
16 -- - data_in[31..0]          The data coming to bus
17 -- - data_out[31..0]         The data coming from bus, multiplexed
18 -- - rd                      Read enable, active LOW
19 -- - bls[3..0]               Write enable for respective bytes, active LOW
20 --                           In some cases, only WR is used
21 -- - ta                      Transaction acknowledge (latches data out), active LOW, multiplexed
22
23 entity lx_rocon_top is
24         port
25         (
26                 -- External
27                 clk      : in std_logic;
28
29                 cs0_xc   : in std_logic;
30
31                 rd       : in std_logic;
32                 bls      : in std_logic_vector(3 downto 0);
33                 address  : in std_logic_vector(15 downto 0);
34                 data     : inout std_logic_vector(31 downto 0);
35
36                 irc1_a     : in std_logic;
37                 irc1_b     : in std_logic;
38                 irc1_index : in std_logic;
39                 irc1_mark  : in std_logic;
40
41                 irc2_a     : in std_logic;
42                 irc2_b     : in std_logic;
43                 irc2_index : in std_logic;
44                 irc2_mark  : in std_logic;
45
46                 irc3_a     : in std_logic;
47                 irc3_b     : in std_logic;
48                 irc3_index : in std_logic;
49                 irc3_mark  : in std_logic;
50
51                 irc4_a     : in std_logic;
52                 irc4_b     : in std_logic;
53                 irc4_index : in std_logic;
54                 irc4_mark  : in std_logic;
55
56                 init       : in std_logic
57         );
58 end lx_rocon_top;
59
60 architecture Behavioral of lx_rocon_top is
61
62         -- Reset signal
63         signal reset : std_logic;
64
65         -- Peripherals on the memory bus
66         signal bram_out : std_logic_vector(31 downto 0);
67         signal bram_ta : std_logic;
68         signal bram_ce : std_logic;
69
70         signal irc_reg_out : std_logic_vector(31 downto 0);
71         signal irc_reg_ta : std_logic;
72         signal irc_reg_ce : std_logic;
73
74         -- Signals for external bus transmission
75         signal data_in_bus : std_logic_vector(31 downto 0);
76         signal data_out_bus : std_logic_vector(31 downto 0);
77
78         -- Signals for internal transaction
79         signal last_address : std_logic_vector(15 downto 0);
80         signal last_rd : std_logic;
81
82         -- Latching logic:
83         -- Broadcast rd only till ta (transaction acknowledge)
84         -- is received, then latch the data till the state of
85         -- rd or address changes
86         signal i_ta : std_logic;
87         signal i_rd : std_logic;
88         signal data_latched : std_logic_vector(31 downto 0);
89         signal acked : std_logic;
90
91         component bus_irc
92         port
93         (
94                 clk         : in std_logic;
95                 reset       : in std_logic;
96
97                 address     : in std_logic_vector(3 downto 0);
98                 ce          : in std_logic;
99
100                 data_in     : in std_logic;
101                 data_out    : out std_logic_vector(31 downto 0);
102
103                 rd          : in std_logic;
104                 wr          : in std_logic;
105                 ta          : out std_logic;
106
107                 irc1_a      : in std_logic;
108                 irc1_b      : in std_logic;
109                 irc1_index  : in std_logic;
110                 irc1_mark   : in std_logic;
111
112                 irc2_a      : in std_logic;
113                 irc2_b      : in std_logic;
114                 irc2_index  : in std_logic;
115                 irc2_mark   : in std_logic;
116
117                 irc3_a      : in std_logic;
118                 irc3_b      : in std_logic;
119                 irc3_index  : in std_logic;
120                 irc3_mark   : in std_logic;
121
122                 irc4_a      : in std_logic;
123                 irc4_b      : in std_logic;
124                 irc4_index  : in std_logic;
125                 irc4_mark   : in std_logic
126         );
127         end component;
128
129         component bus_control_bram
130         port
131         (
132                 clk : in std_logic;
133
134     ena : in std_logic;
135     wea : in std_logic_vector(3 downto 0);
136     addra : in std_logic_vector(9 downto 0);
137     dina : in std_logic_vector(31 downto 0);
138     douta : out std_logic_vector(31 downto 0);
139                 taa : out std_logic;
140
141     enb : in std_logic;
142     web : in std_logic_vector(3 downto 0);
143     addrb : in std_logic_vector(9 downto 0);
144     dinb : in std_logic_vector(31 downto 0);
145     doutb : out std_logic_vector(31 downto 0)
146   );
147         end component;
148
149 begin
150
151         -- IRC interconnect
152         memory_bus_irc: bus_irc
153         port map
154         (
155                 clk => clk,
156                 reset => reset,
157                 address => address(3 downto 0),
158                 ce => irc_reg_ce,
159                 data_in => data_in_bus(0),
160                 data_out => irc_reg_out,
161                 rd => i_rd,
162                 wr => bls(0),
163                 ta => irc_reg_ta,
164
165                 irc1_a => irc1_a,
166                 irc1_b => irc1_b,
167                 irc1_index => irc1_index,
168                 irc1_mark => irc1_mark,
169
170                 irc2_a => irc2_a,
171                 irc2_b => irc2_b,
172                 irc2_index => irc2_index,
173                 irc2_mark => irc2_mark,
174
175                 irc3_a => irc3_a,
176                 irc3_b => irc3_b,
177                 irc3_index => irc3_index,
178                 irc3_mark => irc3_mark,
179
180                 irc4_a => irc4_a,
181                 irc4_b => irc4_b,
182                 irc4_index => irc4_index,
183                 irc4_mark => irc4_mark
184         );
185
186         -- Control BRAM interconnect (9 kiB)
187         memory_bus_control_bram: bus_control_bram
188         port map
189         (
190                 clk => clk,
191                 ena => bram_ce,
192                 taa => bram_ta,
193                 wea => bls,
194                 addra => address(9 downto 0),
195                 dina => data_in_bus,
196                 douta => bram_out,
197
198                 enb => '0',
199                 web => (others => '0'),
200                 addrb => (others => '0'),
201                 dinb => (others => '0'),
202                 doutb => open
203         );
204
205         -- Bus update
206         memory_bus_update: process(clk)
207         begin
208
209                 if clk = '1' and clk'event then
210
211                         -- Set every signal to inactive state here
212                         irc_reg_ce <= '1';
213                         bram_ce <= '1';
214                         i_rd <= '1';
215
216                         -- TODO: Make sure our CPU actually follows the convention
217                         if cs0_xc = '0' then
218
219                                 -- Memory Map (16-bit address @ 32-bit each)
220
221                                 -- 0x0000 - 0x0900: Control dual-port BRAM
222                                 -- 0x8000 - 0x800F: IRC registers
223
224                                 if address < "0000100100000000" then -- Control BRAM
225                                         bram_ce <= '0';
226                                         i_ta <= bram_ta;
227                                         data_out_bus <= bram_out;
228                                 elsif address(15 downto 4) = "100000000000" then -- IRC
229                                         irc_reg_ce <= '0';
230                                         i_ta <= irc_reg_ta;
231                                         data_out_bus <= irc_reg_out;
232                                 end if;
233
234                                 if rd = '0' then
235                                         if last_rd = '1' or last_address /= address then
236                                                 -- Getting something new
237                                                 -- Set internal RD to active and reset ack and latched data
238                                                 acked <= '0';
239                                                 i_rd <= '0';
240                                                 -- Latching must be performed synchronously, otherwise poor timing performance
241                                                 -- caused by significant routing delay
242                                                 data_latched <= (others => 'X');
243                                         elsif i_rd = '0' and acked = '0' and i_ta = '0' then
244                                                 -- Got acknowledge, latch data
245                                                 acked <= '1';
246                                                 data_latched <= data_out_bus;
247                                         elsif acked = '0' then
248                                                 -- Ongoing read, keep the signal low
249                                                 i_rd <= '0';
250                                                 data_latched <= (others => 'X');
251                                         end if;
252
253                                         last_address <= address;
254                                 else
255                                         -- Not reading, anything goes
256                                         data_latched <= (others => 'X');
257                                 end if;
258
259                                 last_rd <= rd;
260                         end if;
261
262                 end if;
263
264         end process;
265
266         -- If RD and BLS is not high, we must keep DATA at high impedance
267         -- or the FPGA collides with SDRAM (burning each other)
268
269         memory_bus_out: process(cs0_xc, rd, data, data_latched)
270         begin
271
272                 -- CS0 / RD / BLS are active LOW
273                 if cs0_xc = '0' and rd = '0' then
274                         data <= data_latched;
275                 else
276                         -- IMPORTANT!!!
277                         data <= (others => 'Z');
278                 end if;
279
280                 data_in_bus <= data;
281
282         end process;
283
284         -- Reset
285         initialization: process(init)
286         begin
287
288                 reset <= init;
289
290         end process;
291
292 end Behavioral;
293