OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_slink.vhd] - Blame information for rev 62

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 61 zero_gravi
-- #################################################################################################
2
-- # << NEORV32 - Stream Link Interface (SLINK) >>                                                 #
3
-- # ********************************************************************************************* #
4 62 zero_gravi
-- # Up to 8 input (RX) and up to 8 output (TX) stream links are supported. Each link provides an  #
5
-- # internal FIFO for buffering. Each stream direction provides a global interrupt to indicate    #
6
-- # that a RX link has received new data or that a TX link has finished sending data              #
7
-- # (if FIFO_DEPTH = 1) OR if RX/TX link FIFO has become half full (if FIFO_DEPTH > 1).           #
8 61 zero_gravi
-- # ********************************************************************************************* #
9
-- # BSD 3-Clause License                                                                          #
10
-- #                                                                                               #
11
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
12
-- #                                                                                               #
13
-- # Redistribution and use in source and binary forms, with or without modification, are          #
14
-- # permitted provided that the following conditions are met:                                     #
15
-- #                                                                                               #
16
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
17
-- #    conditions and the following disclaimer.                                                   #
18
-- #                                                                                               #
19
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
20
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
21
-- #    provided with the distribution.                                                            #
22
-- #                                                                                               #
23
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
24
-- #    endorse or promote products derived from this software without specific prior written      #
25
-- #    permission.                                                                                #
26
-- #                                                                                               #
27
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
28
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
29
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
30
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
31
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
32
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
33
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
34
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
35
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
36
-- # ********************************************************************************************* #
37
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
38
-- #################################################################################################
39
 
40
library ieee;
41
use ieee.std_logic_1164.all;
42
use ieee.numeric_std.all;
43
 
44
library neorv32;
45
use neorv32.neorv32_package.all;
46
 
47
entity neorv32_slink is
48
  generic (
49 62 zero_gravi
    SLINK_NUM_TX  : natural; -- number of TX links (0..8)
50
    SLINK_NUM_RX  : natural; -- number of TX links (0..8)
51
    SLINK_TX_FIFO : natural; -- TX fifo depth, has to be a power of two
52
    SLINK_RX_FIFO : natural  -- RX fifo depth, has to be a power of two
53 61 zero_gravi
  );
54
  port (
55
    -- host access --
56
    clk_i          : in  std_ulogic; -- global clock line
57
    addr_i         : in  std_ulogic_vector(31 downto 0); -- address
58
    rden_i         : in  std_ulogic; -- read enable
59
    wren_i         : in  std_ulogic; -- write enable
60
    data_i         : in  std_ulogic_vector(31 downto 0); -- data in
61
    data_o         : out std_ulogic_vector(31 downto 0); -- data out
62
    ack_o          : out std_ulogic; -- transfer acknowledge
63
    -- interrupt --
64
    irq_tx_o       : out std_ulogic; -- transmission done
65
    irq_rx_o       : out std_ulogic; -- data received
66
    -- TX stream interfaces --
67
    slink_tx_dat_o : out sdata_8x32_t; -- output data
68
    slink_tx_val_o : out std_ulogic_vector(7 downto 0); -- valid output
69
    slink_tx_rdy_i : in  std_ulogic_vector(7 downto 0); -- ready to send
70
    -- RX stream interfaces --
71
    slink_rx_dat_i : in  sdata_8x32_t; -- input data
72
    slink_rx_val_i : in  std_ulogic_vector(7 downto 0); -- valid input
73
    slink_rx_rdy_o : out std_ulogic_vector(7 downto 0)  -- ready to receive
74
  );
75
end neorv32_slink;
76
 
77
architecture neorv32_slink_rtl of neorv32_slink is
78
 
79
  -- IO space: module base address --
80
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
81
  constant lo_abb_c : natural := index_size_f(slink_size_c); -- low address boundary bit
82
 
83 62 zero_gravi
  -- control register bits --
84
  constant ctrl_rx_num_lsb_c  : natural :=  0; -- r/-: number of implemented RX links
85
  constant ctrl_rx_num_msb_c  : natural :=  3;
86 61 zero_gravi
  --
87 62 zero_gravi
  constant ctrl_tx_num_lsb_c  : natural :=  4; -- r/-: number of implemented TX links
88
  constant ctrl_tx_num_msb_c  : natural :=  7;
89 61 zero_gravi
  --
90 62 zero_gravi
  constant ctrl_rx_size_lsb_c : natural :=  8; -- r/-: log2(RX FIFO size)
91
  constant ctrl_rx_size_msb_c : natural := 11;
92 61 zero_gravi
  --
93 62 zero_gravi
  constant ctrl_tx_size_lsb_c : natural := 12; -- r/-: log2(TX FIFO size)
94
  constant ctrl_tx_size_msb_c : natural := 15;
95 61 zero_gravi
  --
96 62 zero_gravi
  constant ctrl_en_c          : natural := 31; -- r/w: global enable
97 61 zero_gravi
 
98 62 zero_gravi
  -- status register bits --
99
  constant status_rx_avail_lsb_c : natural :=  0; -- r/-: set if TX link 0..7 is ready to send
100
  constant status_rx_avail_msb_c : natural :=  7;
101
  --
102
  constant status_tx_free_lsb_c  : natural :=  8; -- r/-: set if RX link 0..7 data available
103
  constant status_tx_free_msb_c  : natural := 15;
104
  --
105
  constant status_rx_half_lsb_c  : natural := 16; -- r/-: set if TX link 0..7 FIFO fill-level is >= half-full
106
  constant status_rx_half_msb_c  : natural := 23;
107
  --
108
  constant status_tx_half_lsb_c  : natural := 24; -- r/-: set if RX link 0..7 FIFO fill-level is > half-full
109
  constant status_tx_half_msb_c  : natural := 31;
110
 
111 61 zero_gravi
  -- bus access control --
112
  signal ack_read  : std_ulogic;
113
  signal ack_write : std_ulogic;
114
  signal acc_en    : std_ulogic;
115
  signal addr      : std_ulogic_vector(31 downto 0);
116
 
117
  -- control register --
118
  signal enable : std_ulogic; -- global enable
119
 
120
  -- stream link fifo interface --
121
  type fifo_data_t is array (0 to 7) of std_ulogic_vector(31 downto 0);
122 62 zero_gravi
  type fifo_rx_level_t is array (0 to 7) of std_ulogic_vector(index_size_f(SLINK_RX_FIFO) downto 0);
123
  type fifo_tx_level_t is array (0 to 7) of std_ulogic_vector(index_size_f(SLINK_TX_FIFO) downto 0);
124
  signal rx_fifo_rdata                   : fifo_data_t;
125
  signal rx_fifo_level                   : fifo_rx_level_t;
126
  signal tx_fifo_level                   : fifo_tx_level_t;
127
  signal fifo_clear                      : std_ulogic;
128
  signal link_sel                        : std_ulogic_vector(7 downto 0);
129
  signal tx_fifo_we,    rx_fifo_re       : std_ulogic_vector(7 downto 0);
130
  signal rx_fifo_avail, rx_fifo_avail_ff : std_ulogic_vector(7 downto 0);
131
  signal tx_fifo_free,  tx_fifo_free_ff  : std_ulogic_vector(7 downto 0);
132
  signal rx_fifo_half,  rx_fifo_half_ff  : std_ulogic_vector(7 downto 0);
133
  signal tx_fifo_half,  tx_fifo_half_ff  : std_ulogic_vector(7 downto 0);
134 61 zero_gravi
 
135 62 zero_gravi
  -- interrupt controller --
136
  type irq_t is record
137
    rx_pending    : std_ulogic;
138
    rx_pending_ff : std_ulogic;
139
    rx_fire       : std_ulogic;
140
    tx_pending    : std_ulogic;
141
    tx_pending_ff : std_ulogic;
142
    tx_fire       : std_ulogic;
143
    wr_ack        : std_ulogic;
144
    rd_ack        : std_ulogic;
145
  end record;
146
  signal irq : irq_t;
147
 
148 61 zero_gravi
begin
149
 
150
  -- Sanity Checks --------------------------------------------------------------------------
151
  -- -------------------------------------------------------------------------------------------
152
  assert not (is_power_of_two_f(SLINK_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be a power of two." severity error;
153
  assert not (SLINK_TX_FIFO > 2**15) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_TX_FIFO> has to be 1..32768." severity error;
154
  --
155
  assert not (is_power_of_two_f(SLINK_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_RX_FIFO> has to be a power of two." severity error;
156
  assert not (SLINK_RX_FIFO > 2**15) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_RX_FIFO> has to be 1..32768." severity error;
157
  --
158
  assert not (SLINK_NUM_RX > 8) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_NUM_RX> has to be 0..8." severity error;
159
  assert not (SLINK_NUM_TX > 8) report "NEORV32 PROCESSOR CONFIG ERROR: SLINK <SLINK_NUM_TX> has to be 0..8." severity error;
160
  --
161
  assert false report "NEORV32 PROCESSOR CONFIG NOTE: Implementing " & integer'image(SLINK_NUM_RX) & " RX and " &
162
  integer'image(SLINK_NUM_TX) & " TX stream links." severity note;
163
 
164
 
165
  -- Access Control -------------------------------------------------------------------------
166
  -- -------------------------------------------------------------------------------------------
167
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = slink_base_c(hi_abb_c downto lo_abb_c)) else '0';
168
  addr   <= slink_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
169
 
170
 
171
  -- Read/Write Access ----------------------------------------------------------------------
172
  -- -------------------------------------------------------------------------------------------
173
  rw_access: process(clk_i)
174
  begin
175
    if rising_edge(clk_i) then
176
      -- write access --
177 62 zero_gravi
      irq.wr_ack <= '0';
178
      ack_write  <= '0';
179 61 zero_gravi
      if (acc_en = '1') and (wren_i = '1') then
180 62 zero_gravi
        if (addr(5) = '0') then -- control/status 
181
          if (addr(4) = '0') then -- control register
182
            enable <= data_i(ctrl_en_c);
183
          else -- status register
184
            irq.wr_ack <= '1';
185
          end if;
186 61 zero_gravi
          ack_write <= '1';
187
        else -- TX links
188
          ack_write <= or_reduce_f(link_sel and tx_fifo_free);
189
        end if;
190
      end if;
191
 
192
      -- read access --
193 62 zero_gravi
      irq.rd_ack <= '0';
194
      data_o     <= (others => '0');
195
      ack_read   <= '0';
196 61 zero_gravi
      if (acc_en = '1') and (rden_i = '1') then
197 62 zero_gravi
        if (addr(5) = '0') then -- control/status registers
198 61 zero_gravi
          ack_read <= '1';
199 62 zero_gravi
          if (addr(4) = '0') then -- control register
200
            data_o(ctrl_rx_num_msb_c  downto ctrl_rx_num_lsb_c)  <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
201
            data_o(ctrl_tx_num_msb_c  downto ctrl_tx_num_lsb_c)  <= std_ulogic_vector(to_unsigned(SLINK_NUM_TX, 4));
202
            data_o(ctrl_rx_size_msb_c downto ctrl_rx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_RX_FIFO), 4));
203
            data_o(ctrl_tx_size_msb_c downto ctrl_tx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_TX_FIFO), 4));
204
            data_o(ctrl_en_c)                                    <= enable;
205
          else -- fifo status register
206
            data_o(status_rx_avail_msb_c downto status_rx_avail_lsb_c) <= rx_fifo_avail;
207
            data_o(status_tx_free_msb_c  downto status_tx_free_lsb_c)  <= tx_fifo_free;
208
            data_o(status_rx_half_msb_c  downto status_rx_half_lsb_c)  <= rx_fifo_half;
209
            data_o(status_tx_half_msb_c  downto status_tx_half_lsb_c)  <= tx_fifo_half;
210
            irq.rd_ack <= '1';
211
          end if;
212 61 zero_gravi
        else -- RX links
213
          data_o   <= rx_fifo_rdata(to_integer(unsigned(addr(4 downto 2))));
214
          ack_read <= or_reduce_f(link_sel and rx_fifo_avail);
215
        end if;
216
      end if;
217
    end if;
218
  end process rw_access;
219
 
220
  -- bus access acknowledge --
221
  ack_o <= ack_write or ack_read;
222
 
223
  -- link fifo reset (sync) --
224
  fifo_clear <= not enable;
225
 
226
 
227 62 zero_gravi
  -- FIFO Level Monitoring ------------------------------------------------------------------
228
  -- -------------------------------------------------------------------------------------------
229
  level_monitor: process(rx_fifo_level, tx_fifo_level)
230
  begin
231
    -- RX FIFO --
232
    rx_fifo_half <= (others => '0');
233
    for i in 0 to SLINK_NUM_RX-1 loop
234
      if (unsigned(rx_fifo_level(i)) >= to_unsigned(cond_sel_natural_f(boolean(SLINK_RX_FIFO > 1), SLINK_RX_FIFO/2, 1), rx_fifo_level(i)'length)) then
235
        rx_fifo_half(i) <= '1';
236
      end if;
237
    end loop;
238
    -- TX FIFO --
239
    tx_fifo_half <= (others => '0');
240
    for i in 0 to SLINK_NUM_TX-1 loop
241
      if (unsigned(tx_fifo_level(i)) >= to_unsigned(cond_sel_natural_f(boolean(SLINK_TX_FIFO > 1), SLINK_TX_FIFO/2, 1), tx_fifo_level(i)'length)) then
242
        tx_fifo_half(i) <= '1';
243
      end if;
244
    end loop;
245
  end process level_monitor;
246
 
247
 
248 61 zero_gravi
  -- Interrupt Generator --------------------------------------------------------------------
249
  -- -------------------------------------------------------------------------------------------
250 62 zero_gravi
  irq_arbiter: process(clk_i)
251 61 zero_gravi
  begin
252
    if rising_edge(clk_i) then
253 62 zero_gravi
      if (enable = '0') then
254
        irq.rx_pending <= '0';
255
        irq.tx_pending <= '0';
256
      else
257
        -- RX IRQ --
258
        if (irq.rx_pending = '0') then
259
          irq.rx_pending <= irq.rx_fire;
260
        elsif (irq.rd_ack = '1') or (irq.wr_ack = '1') then
261
          irq.rx_pending <= '0';
262
        end if;
263
        -- TX IRQ --
264
        if (irq.tx_pending = '0') then
265
          irq.tx_pending <= irq.tx_fire;
266
        elsif (irq.rd_ack = '1') or (irq.wr_ack = '1') then
267
          irq.tx_pending <= '0';
268
        end if;
269
      end if;
270
      -- CPU IRQs --
271
      irq.rx_pending_ff <= irq.rx_pending;
272
      irq.tx_pending_ff <= irq.tx_pending;
273
      irq_rx_o <= irq.rx_pending and (not irq.rx_pending_ff);
274
      irq_tx_o <= irq.tx_pending and (not irq.tx_pending_ff);
275 61 zero_gravi
    end if;
276 62 zero_gravi
  end process irq_arbiter;
277 61 zero_gravi
 
278 62 zero_gravi
  -- status buffer --
279
  irq_generator_sync: process(clk_i)
280
  begin
281
    if rising_edge(clk_i) then
282
      rx_fifo_avail_ff <= rx_fifo_avail;
283
      rx_fifo_half_ff  <= rx_fifo_half;
284
      tx_fifo_free_ff  <= tx_fifo_free;
285
      tx_fifo_half_ff  <= tx_fifo_half;
286
    end if;
287
  end process irq_generator_sync;
288 61 zero_gravi
 
289 62 zero_gravi
  -- IRQ event detector --
290
  -- RX interrupt: fire if any RX_FIFO gets full / fire if any RX_FIFO.level becomes half-full
291
  irq.rx_fire <= or_reduce_f(rx_fifo_avail and (not rx_fifo_avail_ff)) when (SLINK_RX_FIFO = 1) else or_reduce_f(rx_fifo_half and (not rx_fifo_half_ff));
292
  -- TX interrupt: fire if any TX_FIFO gets empty / fire if any TX_FIFO.level falls below half-full level
293
  irq.tx_fire <= or_reduce_f(tx_fifo_free and (not tx_fifo_free_ff)) when (SLINK_TX_FIFO = 1) else or_reduce_f((not tx_fifo_half) and tx_fifo_half_ff);
294
 
295
 
296 61 zero_gravi
  -- Link Select ----------------------------------------------------------------------------
297
  -- -------------------------------------------------------------------------------------------
298
  link_select: process(addr)
299
  begin
300
    case addr(5 downto 2) is -- MSB = data fifo access at all?
301
      when "1000" => link_sel <= "00000001";
302
      when "1001" => link_sel <= "00000010";
303
      when "1010" => link_sel <= "00000100";
304
      when "1011" => link_sel <= "00001000";
305
      when "1100" => link_sel <= "00010000";
306
      when "1101" => link_sel <= "00100000";
307
      when "1110" => link_sel <= "01000000";
308
      when "1111" => link_sel <= "10000000";
309
      when others => link_sel <= "00000000";
310
    end case;
311
  end process link_select;
312
 
313
  fifo_access_gen:
314
  for i in 0 to 7 generate
315
    tx_fifo_we(i) <= link_sel(i) and acc_en and wren_i;
316
    rx_fifo_re(i) <= link_sel(i) and acc_en and rden_i;
317
  end generate;
318
 
319
 
320
  -- TX Link FIFOs --------------------------------------------------------------------------
321
  -- -------------------------------------------------------------------------------------------
322
  transmit_fifo_gen:
323
  for i in 0 to SLINK_NUM_TX-1 generate
324
    transmit_fifo_inst: neorv32_fifo
325
    generic map (
326
      FIFO_DEPTH => SLINK_TX_FIFO, -- number of fifo entries; has to be a power of two; min 1
327
      FIFO_WIDTH => 32,            -- size of data elements in fifo
328
      FIFO_RSYNC => false,         -- false = async read; true = sync read
329 62 zero_gravi
      FIFO_SAFE  => true           -- true = allow read/write only if entry available
330 61 zero_gravi
    )
331
    port map (
332
      -- control --
333
      clk_i   => clk_i,             -- clock, rising edge
334
      rstn_i  => '1',               -- async reset, low-active
335
      clear_i => fifo_clear,        -- sync reset, high-active
336 62 zero_gravi
      level_o => tx_fifo_level(i),  -- fill level
337 61 zero_gravi
      -- write port --
338
      wdata_i => data_i,            -- write data
339
      we_i    => tx_fifo_we(i),     -- write enable
340
      free_o  => tx_fifo_free(i),   -- at least one entry is free when set
341
      -- read port --
342
      re_i    => slink_tx_rdy_i(i), -- read enable
343
      rdata_o => slink_tx_dat_o(i), -- read data
344
      avail_o => slink_tx_val_o(i)  -- data available when set
345
    );
346
  end generate;
347
 
348
  -- terminate unimplemented links --
349
  transmit_fifo_gen_terminate:
350
  for i in SLINK_NUM_TX to 7 generate
351
    tx_fifo_free(i)   <= '0';
352
    slink_tx_dat_o(i) <= (others => '0');
353
    slink_tx_val_o(i) <= '0';
354 62 zero_gravi
    tx_fifo_level(i)  <= (others => '0');
355 61 zero_gravi
  end generate;
356
 
357
 
358
  -- RX Link FIFOs --------------------------------------------------------------------------
359
  -- -------------------------------------------------------------------------------------------
360
  receive_fifo_gen:
361
  for i in 0 to SLINK_NUM_RX-1 generate
362
    receive_fifo_inst: neorv32_fifo
363
    generic map (
364
      FIFO_DEPTH => SLINK_RX_FIFO, -- number of fifo entries; has to be a power of two; min 1
365
      FIFO_WIDTH => 32,            -- size of data elements in fifo
366
      FIFO_RSYNC => false,         -- false = async read; true = sync read
367 62 zero_gravi
      FIFO_SAFE  => true           -- true = allow read/write only if entry available
368 61 zero_gravi
    )
369
    port map (
370
      -- control --
371
      clk_i   => clk_i,             -- clock, rising edge
372
      rstn_i  => '1',               -- async reset, low-active
373
      clear_i => fifo_clear,        -- sync reset, high-active
374 62 zero_gravi
      level_o => rx_fifo_level(i),  -- fill level
375 61 zero_gravi
      -- write port --
376
      wdata_i => slink_rx_dat_i(i), -- write data
377
      we_i    => slink_rx_val_i(i), -- write enable
378
      free_o  => slink_rx_rdy_o(i), -- at least one entry is free when set
379
      -- read port --
380
      re_i    => rx_fifo_re(i),     -- read enable
381
      rdata_o => rx_fifo_rdata(i),  -- read data
382
      avail_o => rx_fifo_avail(i)   -- data available when set
383
    );
384
  end generate;
385
 
386
  -- terminate unimplemented links --
387
  receive_fifo_gen_terminate:
388
  for i in SLINK_NUM_RX to 7 generate
389
    rx_fifo_avail(i)  <= '0';
390
    slink_rx_rdy_o(i) <= '0';
391
    rx_fifo_rdata(i)  <= (others => '0');
392 62 zero_gravi
    rx_fifo_level(i)  <= (others => '0');
393 61 zero_gravi
  end generate;
394
 
395
 
396
end neorv32_slink_rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.