@@ -85,6 +85,18 @@ module util_axis_fifo_asym #(
8585 reg [$clog2(RATIO)- 1 :0 ] s_axis_counter;
8686 reg [$clog2(RATIO)- 1 :0 ] m_axis_counter;
8787
88+ // FIFO level signals
89+ reg s_axis_ready_d;
90+ reg s_axis_valid_d;
91+ reg [ 2 :0 ] word_counter;
92+ reg [ 2 :0 ] num_of_words;
93+ reg [ADDRESS_WIDTH- 1 :0 ] s_input_level;
94+ reg [ADDRESS_WIDTH- 1 :0 ] s_input_room;
95+ reg [ADDRESS_WIDTH- 1 :0 ] s_input_level_next;
96+ reg [ADDRESS_WIDTH- 1 :0 ] s_input_room_next;
97+ wire [ADDRESS_WIDTH- 1 :0 ] m_output_level;
98+ wire sdi_output_read_sync;
99+
88100 wire [RATIO- 1 :0 ] m_axis_ready_int_s;
89101 wire [RATIO- 1 :0 ] m_axis_valid_int_s;
90102 wire [RATIO* A_WIDTH- 1 :0 ] m_axis_data_int_s;
@@ -146,6 +158,46 @@ module util_axis_fifo_asym #(
146158 // write or slave logic
147159 generate
148160
161+ integer j;
162+ always @(posedge s_axis_aclk) begin
163+ if (! s_axis_aresetn) begin
164+ num_of_words <= 1 ;
165+ s_axis_ready_d <= 0 ;
166+ s_axis_valid_d <= 0 ;
167+ end else begin
168+ s_axis_ready_d <= s_axis_ready;
169+ s_axis_valid_d <= s_axis_valid;
170+ word_counter = 0 ;
171+ for (j = 0 ; j < RATIO; j = j + 1 ) begin
172+ word_counter = word_counter + (| s_axis_tkeep[M_DATA_WIDTH/ 8 * j+ :M_DATA_WIDTH/ 8 ]);
173+ end
174+ num_of_words <= word_counter;
175+ end
176+ end
177+
178+ always @(posedge s_axis_aclk) begin
179+ if (! s_axis_aresetn) begin
180+ s_input_level <= 0 ;
181+ s_input_room <= {ADDRESS_WIDTH{1'b1 }};
182+ end else begin
183+ s_input_room <= s_input_room_next;
184+ s_input_level <= s_input_level_next;
185+ end
186+ end
187+
188+ always @(* ) begin
189+ s_input_level_next = s_input_level;
190+ s_input_room_next = s_input_room;
191+ if (s_axis_ready_d && s_axis_valid_d) begin
192+ s_input_level_next = s_input_level_next + num_of_words;
193+ s_input_room_next = s_input_room_next - 1 ;
194+ end
195+ if (sdi_output_read_sync) begin
196+ s_input_level_next = s_input_level_next - 1 ;
197+ s_input_room_next = s_input_room_next + num_of_words;
198+ end
199+ end
200+
149201 if (RATIO_TYPE) begin : big_slave
150202
151203 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
@@ -205,12 +257,18 @@ module util_axis_fifo_asym #(
205257
206258 // FULL/ALMOST_FULL is driven by the current atomic instance
207259 assign s_axis_almost_full = s_axis_almost_full_int_s >> s_axis_counter;
208-
209- // the FIFO has the same room as the last atomic instance
210- // (NOTE: this is not the real room value, rather the value will be updated
211- // after every RATIO number of writes)
212260 assign s_axis_full = s_axis_full_int_s[RATIO- 1 ];
213- assign s_axis_room = {s_axis_room_int_s[A_ADDRESS* (RATIO- 1 )+ :A_ADDRESS], {$clog2(RATIO){1'b1 }}};
261+
262+ // FIFO room behavior relies on the TKEEP_EN parameter
263+ // When TKEEP_EN == 0, the FIFO has the same room as
264+ // the last atomic instance multiplied by RATIO. The
265+ // value of the room is only updated every RATIO reads.
266+ // s_axis_room == {s_axis_room_int_s[A_ADDRESS*(RATIO-1)+:A_ADDRESS], {$clog2(RATIO){1'b1}}}
267+ //
268+ // When TKEEP_EN == 1, it is using a counter whose decrement
269+ // relies on the tkeep.
270+ // s_axis_room == s_input_room
271+ assign s_axis_room = (TKEEP_EN) ? s_input_room : {s_axis_room_int_s[A_ADDRESS* (RATIO- 1 )+ :A_ADDRESS], {$clog2(RATIO){1'b1 }}};
214272
215273 end
216274
@@ -227,7 +285,7 @@ module util_axis_fifo_asym #(
227285 end
228286
229287 assign m_axis_data = m_axis_data_int_s >> (m_axis_counter* A_WIDTH) ;
230- assign m_axis_tkeep = m_axis_tkeep_int_s >> (m_axis_counter* A_WIDTH/ 8 ) ;
288+ assign m_axis_tkeep = m_axis_tkeep_int_s >> (m_axis_counter* A_WIDTH/ 8 ); // m_axis_tkeep is always high when TKEEP_EN == 0
231289
232290 // VALID/EMPTY/ALMOST_EMPTY is driven by the current atomic instance
233291 assign m_axis_valid_int = m_axis_valid_int_s >> m_axis_counter;
@@ -244,13 +302,29 @@ module util_axis_fifo_asym #(
244302
245303 assign m_axis_tlast = m_axis_tlast_int_s >> m_axis_counter;
246304
247- // the FIFO has the same level as the last atomic instance
248- // (NOTE: this is not the real level value, rather the value will be updated
249- // after every RATIO number of reads)
250- assign m_axis_level = {m_axis_level_int_s[A_ADDRESS- 1 :0 ], {$clog2(RATIO){1'b0 }}};
305+ // FIFO level behavior relies on the TKEEP_EN parameter
306+ // When TKEEP_EN == 0, the FIFO has the same level as
307+ // the last atomic instance multiplied by RATIO. The
308+ // value of the level is only updated every RATIO reads.
309+ // m_axis_level == {m_axis_level_int_s[A_ADDRESS-1:0], {$clog2(RATIO){1'b0}}}
310+ //
311+ // When TKEEP_EN == 1, it is using a counter whose increment
312+ // relies on the tkeep.
313+ // m_axis_level == m_output_level
314+ assign m_axis_level = (TKEEP_EN) ? m_output_level : {m_axis_level_int_s[A_ADDRESS- 1 :0 ], {$clog2(RATIO){1'b0 }}};
251315 assign m_axis_almost_empty = m_axis_almost_empty_int_s[RATIO- 1 ];
252316 assign m_axis_empty = m_axis_empty_int_s[RATIO- 1 ];
253317
318+ sync_data #(
319+ .NUM_OF_BITS (ADDRESS_WIDTH),
320+ .ASYNC_CLK (ASYNC_CLK)
321+ ) i_sdi_level_sync (
322+ .in_clk (s_axis_aclk),
323+ .in_data (s_input_level),
324+ .out_clk (m_axis_aclk),
325+ .out_data (m_output_level)
326+ );
327+
254328 end else begin : big_master
255329
256330 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
@@ -260,14 +334,13 @@ module util_axis_fifo_asym #(
260334 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
261335 assign m_axis_tkeep[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] = ((m_axis_tlast_int_s[i:0 ] == 0 ) ||
262336 (m_axis_tlast_int_s[i])) ?
263- m_axis_tkeep_int_s[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] :
264- {(A_WIDTH/ 8 ){1'b0 }};
337+ m_axis_tkeep_int_s[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] :
338+ {(A_WIDTH/ 8 ){1'b0 }};
265339 end
266340
267341 assign m_axis_data = m_axis_data_int_s;
268342 // if every instance has a valid data, the interface has valid data,
269343 // otherwise valid is asserted only if TLAST is asserted
270- // assign m_axis_valid_int = (|(m_axis_tlast_int_s & m_axis_valid_int_s)) ? |m_axis_valid_int_s : &m_axis_valid_int_s;
271344 if (TLAST_EN) begin
272345 assign m_axis_valid_int = (| (m_axis_tlast_int_s & m_axis_valid_int_s)) ? | m_axis_valid_int_s : & m_axis_valid_int_s;
273346 end else begin
@@ -285,12 +358,21 @@ module util_axis_fifo_asym #(
285358
286359 end
287360
361+ sync_event #(
362+ .NUM_OF_EVENTS (1 ),
363+ .ASYNC_CLK (ASYNC_CLK)
364+ ) i_sdi_output_read_sync (
365+ .in_clk (m_axis_aclk),
366+ .in_event (m_axis_ready & m_axis_valid),
367+ .out_clk (s_axis_aclk),
368+ .out_event (sdi_output_read_sync));
369+
288370 endgenerate
289371
290372 generate
291373 if (RATIO == 1 ) begin
292374 initial begin
293- s_axis_counter = 1'b1 ;
375+ s_axis_counter = 1'b1 ; // s_axis_counter == 1 is never executed in small_slave
294376 end
295377 end else if (RATIO > 1 ) begin
296378 if (RATIO_TYPE) begin
0 commit comments