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

Subversion Repositories astron_fifo

[/] [astron_fifo/] [trunk/] [dp_fifo_core.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3 3 danv
-- Copyright 2020
4 2 danv
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6 3 danv
-- 
7
-- Licensed under the Apache License, Version 2.0 (the "License");
8
-- you may not use this file except in compliance with the License.
9
-- You may obtain a copy of the License at
10
-- 
11
--     http://www.apache.org/licenses/LICENSE-2.0
12
-- 
13
-- Unless required by applicable law or agreed to in writing, software
14
-- distributed under the License is distributed on an "AS IS" BASIS,
15
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
-- See the License for the specific language governing permissions and
17
-- limitations under the License.
18 2 danv
--
19
-------------------------------------------------------------------------------
20
 
21
-- Purpose:
22
--   Provide input ready control and use output ready control to the FIFO.
23
--   Pass sop and eop along with the data through the FIFO if g_use_ctrl=TRUE.
24
--   Default the RL=1, use g_fifo_rl=0 for a the show ahead FIFO.
25
-- Description:
26
--   Provide the sink ready for FIFO write control and use source ready for
27
--   FIFO read access. The sink ready output is derived from FIFO almost full.
28
--   Data without framing can use g_use_ctrl=FALSE to avoid implementing two
29
--   data bits for sop and eop in the FIFO word width. Idem for g_use_sync,
30
--   g_use_empty, g_use_channel and g_use_error.
31
-- Remark:
32
-- . The bsn, empty, channel and error fields are valid at the sop and or eop.
33
--   Therefore alternatively these fields can be passed on through a separate
34
--   FIFO, with only one entry per frame, to save FIFO memory in case
35
--   concatenating them makes the FIFO word width larger than a standard
36
--   memory data word width.
37
-- . The FIFO makes that the src_in.ready and snk_out.ready are not
38
--   combinatorially connected, so this can ease the timing closure for the
39
--   ready signal.
40
 
41 4 danv
LIBRARY IEEE, common_pkg_lib, dp_components_lib, dp_pkg_lib;
42 2 danv
USE IEEE.STD_LOGIC_1164.ALL;
43
USE IEEE.numeric_std.ALL;
44
USE common_pkg_lib.common_pkg.ALL;
45
USE dp_pkg_lib.dp_stream_pkg.ALL;
46 4 danv
--USE technology_lib.technology_select_pkg.ALL;
47 2 danv
 
48
ENTITY dp_fifo_core IS
49
  GENERIC (
50 4 danv
    g_technology     : NATURAL := 0;
51 2 danv
    g_note_is_ful    : BOOLEAN := TRUE;   -- when TRUE report NOTE when FIFO goes full, fifo overflow is always reported as FAILURE
52
    g_use_dual_clock : BOOLEAN := FALSE;
53
    g_use_lut_sc     : BOOLEAN := FALSE;  -- when TRUE then force using LUTs instead of block RAM for single clock FIFO (bot available for dual clock FIFO)
54
    g_data_w         : NATURAL := 16; -- Should be 2 times the c_complex_w if g_use_complex = TRUE
55
    g_data_signed    : BOOLEAN := FALSE; -- TRUE extends g_data_w bits with the sign bit, FALSE pads g_data_w bits with zeros.
56
    g_bsn_w          : NATURAL := 1;
57
    g_empty_w        : NATURAL := 1;
58
    g_channel_w      : NATURAL := 1;
59
    g_error_w        : NATURAL := 1;
60
    g_use_bsn        : BOOLEAN := FALSE;
61
    g_use_empty      : BOOLEAN := FALSE;
62
    g_use_channel    : BOOLEAN := FALSE;
63
    g_use_error      : BOOLEAN := FALSE;
64
    g_use_sync       : BOOLEAN := FALSE;
65
    g_use_ctrl       : BOOLEAN := TRUE;  -- sop & eop
66
    g_use_complex    : BOOLEAN := FALSE; -- TRUE feeds the concatenated complex fields (im & re) through the FIFO instead of the data field.
67
    g_fifo_size      : NATURAL := 512;   -- (16+2) * 512 = 1 M9K, g_data_w+2 for sop and eop
68
    g_fifo_af_margin : NATURAL := 4;     -- >=4, Nof words below max (full) at which fifo is considered almost full
69
    g_fifo_rl        : NATURAL := 1
70
  );
71
  PORT (
72
    wr_rst      : IN  STD_LOGIC;
73
    wr_clk      : IN  STD_LOGIC;
74
    rd_rst      : IN  STD_LOGIC;
75
    rd_clk      : IN  STD_LOGIC;
76
    -- Monitor FIFO filling
77
    wr_ful      : OUT STD_LOGIC;  -- corresponds to the carry bit of wr_usedw when FIFO is full
78
    wr_usedw    : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0);
79
    rd_usedw    : OUT STD_LOGIC_VECTOR(ceil_log2(g_fifo_size)-1 DOWNTO 0);
80
    rd_emp      : OUT STD_LOGIC;
81
    -- ST sink
82
    snk_out     : OUT t_dp_siso;
83
    snk_in      : IN  t_dp_sosi;
84
    -- ST source
85
    src_in      : IN  t_dp_siso;
86
    src_out     : OUT t_dp_sosi
87
  );
88
END dp_fifo_core;
89
 
90
 
91
ARCHITECTURE str OF dp_fifo_core IS
92
 
93
  CONSTANT c_use_data         : BOOLEAN := TRUE;
94
  CONSTANT c_ctrl_w           : NATURAL := 2;  -- sop and eop
95
 
96
  CONSTANT c_complex_w        : NATURAL := smallest(c_dp_stream_dsp_data_w, g_data_w/2);  -- needed to cope with g_data_w > 2*c_dp_stream_dsp_data_w
97
 
98
  CONSTANT c_fifo_almost_full : NATURAL := g_fifo_size-g_fifo_af_margin;  -- FIFO almost full level for snk_out.ready
99
  CONSTANT c_fifo_dat_w       : NATURAL := func_slv_concat_w(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl,
100
                                                             g_data_w,   g_bsn_w,   g_empty_w,   g_channel_w,   g_error_w,   1,          c_ctrl_w);  -- concat via FIFO
101
 
102
  SIGNAL nxt_snk_out   : t_dp_siso := c_dp_siso_rst;
103
 
104
  SIGNAL arst          : STD_LOGIC;
105
 
106
  SIGNAL wr_data_complex : STD_LOGIC_VECTOR(2*c_complex_w-1 DOWNTO 0);
107
  SIGNAL wr_data         : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
108
  SIGNAL rd_data         : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
109
 
110
  SIGNAL fifo_wr_dat   : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0);
111
  SIGNAL fifo_wr_req   : STD_LOGIC;
112
  SIGNAL fifo_wr_ful   : STD_LOGIC;
113
  SIGNAL fifo_wr_usedw : STD_LOGIC_VECTOR(wr_usedw'RANGE);
114
 
115
  SIGNAL fifo_rd_dat   : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0) := (OTHERS=>'0');
116
  SIGNAL fifo_rd_val   : STD_LOGIC;
117
  SIGNAL fifo_rd_req   : STD_LOGIC;
118
  SIGNAL fifo_rd_emp   : STD_LOGIC;
119
  SIGNAL fifo_rd_usedw : STD_LOGIC_VECTOR(rd_usedw'RANGE);
120
 
121
  SIGNAL wr_sync       : STD_LOGIC_VECTOR(0 DOWNTO 0);
122
  SIGNAL rd_sync       : STD_LOGIC_VECTOR(0 DOWNTO 0);
123
  SIGNAL wr_ctrl       : STD_LOGIC_VECTOR(1 DOWNTO 0);
124
  SIGNAL rd_ctrl       : STD_LOGIC_VECTOR(1 DOWNTO 0);
125
 
126
  SIGNAL rd_siso       : t_dp_siso;
127
  SIGNAL rd_sosi       : t_dp_sosi := c_dp_sosi_rst;  -- initialize default values for unused sosi fields
128
 
129
BEGIN
130
 
131
  -- Output monitor FIFO filling
132
  wr_ful   <= fifo_wr_ful;
133
  wr_usedw <= fifo_wr_usedw;
134
  rd_usedw <= fifo_rd_usedw;
135
  rd_emp   <= fifo_rd_emp;
136
 
137
  p_wr_clk: PROCESS(wr_clk, wr_rst)
138
  BEGIN
139
    IF wr_rst='1' THEN
140
      snk_out <= c_dp_siso_rst;
141
    ELSIF rising_edge(wr_clk) THEN
142
      snk_out <= nxt_snk_out;
143
    END IF;
144
  END PROCESS;
145
 
146
  wr_sync(0) <= snk_in.sync;
147
  wr_ctrl    <= snk_in.sop & snk_in.eop;
148
 
149
  -- Assign the snk_in data field or concatenated complex fields to the FIFO wr_data depending on g_use_complex
150
  wr_data_complex <= snk_in.im(c_complex_w-1 DOWNTO 0) & snk_in.re(c_complex_w-1 DOWNTO 0);
151
  wr_data         <= snk_in.data(g_data_w-1 DOWNTO 0) WHEN g_use_complex = FALSE ELSE RESIZE_UVEC(wr_data_complex, g_data_w);
152
 
153
  -- fifo wr wires
154
  fifo_wr_req <= snk_in.valid;
155
  fifo_wr_dat <= func_slv_concat(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl,
156
                                 wr_data,
157
                                 snk_in.bsn(        g_bsn_w-1 DOWNTO 0),
158
                                 snk_in.empty(    g_empty_w-1 DOWNTO 0),
159
                                 snk_in.channel(g_channel_w-1 DOWNTO 0),
160
                                 snk_in.err(      g_error_w-1 DOWNTO 0),
161
                                 wr_sync,
162
                                 wr_ctrl);
163
 
164
  -- pass on frame level flow control
165
  nxt_snk_out.xon <= src_in.xon;
166
 
167
  -- up stream use fifo almost full to control snk_out.ready
168
  nxt_snk_out.ready <= '1' WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0';
169
 
170
  gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
171 4 danv
    u_common_fifo_sc : ENTITY work.common_fifo_sc
172 2 danv
    GENERIC MAP (
173
      g_technology => g_technology,
174
      g_note_is_ful => g_note_is_ful,
175
      g_use_lut   => g_use_lut_sc,
176
      g_dat_w     => c_fifo_dat_w,
177
      g_nof_words => g_fifo_size
178
    )
179
    PORT MAP (
180
      rst      => rd_rst,
181
      clk      => rd_clk,
182
      wr_dat   => fifo_wr_dat,
183
      wr_req   => fifo_wr_req,
184
      wr_ful   => fifo_wr_ful,
185
      rd_dat   => fifo_rd_dat,
186
      rd_req   => fifo_rd_req,
187
      rd_emp   => fifo_rd_emp,
188
      rd_val   => fifo_rd_val,
189
      usedw    => fifo_rd_usedw
190
    );
191
 
192
    fifo_wr_usedw <= fifo_rd_usedw;
193
  END GENERATE;
194
 
195
  gen_common_fifo_dc : IF g_use_dual_clock=TRUE GENERATE
196 4 danv
    u_common_fifo_dc : ENTITY work.common_fifo_dc
197 2 danv
    GENERIC MAP (
198
      g_technology => g_technology,
199
      g_dat_w     => c_fifo_dat_w,
200
      g_nof_words => g_fifo_size
201
    )
202
    PORT MAP (
203
      rst     => arst,
204
      wr_clk  => wr_clk,
205
      wr_dat  => fifo_wr_dat,
206
      wr_req  => fifo_wr_req,
207
      wr_ful  => fifo_wr_ful,
208
      wrusedw => fifo_wr_usedw,
209
      rd_clk  => rd_clk,
210
      rd_dat  => fifo_rd_dat,
211
      rd_req  => fifo_rd_req,
212
      rd_emp  => fifo_rd_emp,
213
      rdusedw => fifo_rd_usedw,
214
      rd_val  => fifo_rd_val
215
    );
216
 
217
    arst <= wr_rst OR rd_rst;
218
  END GENERATE;
219
 
220
  -- Extract the data from the wide FIFO output SLV. rd_data will be assigned to rd_sosi.data or rd_sosi.im & rd_sosi.re depending on g_use_complex.
221
  rd_data <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 0);
222
 
223
  -- fifo rd wires
224
  -- SISO
225
  fifo_rd_req <= rd_siso.ready;
226
 
227
  -- SOSI
228
  rd_sosi.data    <= RESIZE_DP_SDATA(rd_data) WHEN g_data_signed=TRUE ELSE RESIZE_DP_DATA(rd_data);
229
  rd_sosi.re      <= RESIZE_DP_DSP_DATA(rd_data(  c_complex_w-1 DOWNTO 0));
230
  rd_sosi.im      <= RESIZE_DP_DSP_DATA(rd_data(2*c_complex_w-1 DOWNTO c_complex_w));
231
  rd_sosi.bsn     <= RESIZE_DP_BSN(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 1));
232
  rd_sosi.empty   <= RESIZE_DP_EMPTY(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 2));
233
  rd_sosi.channel <= RESIZE_DP_CHANNEL(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 3));
234
  rd_sosi.err     <= RESIZE_DP_ERROR(func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 4));
235
  rd_sync         <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 5);
236
  rd_ctrl         <= func_slv_extract(c_use_data, g_use_bsn, g_use_empty, g_use_channel, g_use_error, g_use_sync, g_use_ctrl, g_data_w, g_bsn_w, g_empty_w, g_channel_w, g_error_w, 1, c_ctrl_w, fifo_rd_dat, 6);
237
 
238
  rd_sosi.sync    <= fifo_rd_val AND rd_sync(0);
239
  rd_sosi.valid   <= fifo_rd_val;
240
  rd_sosi.sop     <= fifo_rd_val AND rd_ctrl(1);
241
  rd_sosi.eop     <= fifo_rd_val AND rd_ctrl(0);
242
 
243
  u_ready_latency : ENTITY dp_components_lib.dp_latency_adapter
244
  GENERIC MAP (
245
    g_in_latency  => 1,
246
    g_out_latency => g_fifo_rl
247
  )
248
  PORT MAP (
249
    rst       => rd_rst,
250
    clk       => rd_clk,
251
    -- ST sink
252
    snk_out   => rd_siso,
253
    snk_in    => rd_sosi,
254
    -- ST source
255
    src_in    => src_in,
256
    src_out   => src_out
257
  );
258
 
259
END str;

powered by: WebSVN 2.1.0

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