@@ -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
@@ -210,12 +262,18 @@ module util_axis_fifo_asym #(
210262
211263 // FULL/ALMOST_FULL is driven by the current atomic instance
212264 assign s_axis_almost_full = s_axis_almost_full_int_s >> s_axis_counter;
213-
214- // the FIFO has the same room as the last atomic instance
215- // (NOTE: this is not the real room value, rather the value will be updated
216- // after every RATIO number of writes)
217265 assign s_axis_full = s_axis_full_int_s[RATIO- 1 ];
218- assign s_axis_room = {s_axis_room_int_s[A_ADDRESS* (RATIO- 1 )+ :A_ADDRESS], {$clog2(RATIO){1'b1 }}};
266+
267+ // FIFO room behavior relies on the TKEEP_EN parameter
268+ // When TKEEP_EN == 0, the FIFO has the same room as
269+ // the last atomic instance multiplied by RATIO. The
270+ // value of the room is only updated every RATIO reads.
271+ // s_axis_room == {s_axis_room_int_s[A_ADDRESS*(RATIO-1)+:A_ADDRESS], {$clog2(RATIO){1'b1}}}
272+ //
273+ // When TKEEP_EN == 1, it is using a counter whose decrement
274+ // relies on the tkeep.
275+ // s_axis_room == s_input_room
276+ assign s_axis_room = (TKEEP_EN) ? s_input_room : {s_axis_room_int_s[A_ADDRESS* (RATIO- 1 )+ :A_ADDRESS], {$clog2(RATIO){1'b1 }}};
219277
220278 end
221279
@@ -232,7 +290,7 @@ module util_axis_fifo_asym #(
232290 end
233291
234292 assign m_axis_data = m_axis_data_int_s >> (m_axis_counter* A_WIDTH) ;
235- assign m_axis_tkeep = m_axis_tkeep_int_s >> (m_axis_counter* A_WIDTH/ 8 ) ;
293+ 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
236294
237295 // VALID/EMPTY/ALMOST_EMPTY is driven by the current atomic instance
238296 assign m_axis_valid_int = m_axis_valid_int_s >> m_axis_counter;
@@ -249,13 +307,29 @@ module util_axis_fifo_asym #(
249307
250308 assign m_axis_tlast = m_axis_tlast_int_s >> m_axis_counter;
251309
252- // the FIFO has the same level as the last atomic instance
253- // (NOTE: this is not the real level value, rather the value will be updated
254- // after every RATIO number of reads)
255- assign m_axis_level = {m_axis_level_int_s[A_ADDRESS- 1 :0 ], {$clog2(RATIO){1'b0 }}};
310+ // FIFO level behavior relies on the TKEEP_EN parameter
311+ // When TKEEP_EN == 0, the FIFO has the same level as
312+ // the last atomic instance multiplied by RATIO. The
313+ // value of the level is only updated every RATIO reads.
314+ // m_axis_level == {m_axis_level_int_s[A_ADDRESS-1:0], {$clog2(RATIO){1'b0}}}
315+ //
316+ // When TKEEP_EN == 1, it is using a counter whose increment
317+ // relies on the tkeep.
318+ // m_axis_level == m_output_level
319+ assign m_axis_level = (TKEEP_EN) ? m_output_level : {m_axis_level_int_s[A_ADDRESS- 1 :0 ], {$clog2(RATIO){1'b0 }}};
256320 assign m_axis_almost_empty = m_axis_almost_empty_int_s[RATIO- 1 ];
257321 assign m_axis_empty = m_axis_empty_int_s[RATIO- 1 ];
258322
323+ sync_data #(
324+ .NUM_OF_BITS (ADDRESS_WIDTH),
325+ .ASYNC_CLK (ASYNC_CLK)
326+ ) i_sdi_level_sync (
327+ .in_clk (s_axis_aclk),
328+ .in_data (s_input_level),
329+ .out_clk (m_axis_aclk),
330+ .out_data (m_output_level)
331+ );
332+
259333 end else begin : big_master
260334
261335 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
@@ -265,14 +339,13 @@ module util_axis_fifo_asym #(
265339 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
266340 assign m_axis_tkeep[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] = ((m_axis_tlast_int_s[i:0 ] == 0 ) ||
267341 (m_axis_tlast_int_s[i])) ?
268- m_axis_tkeep_int_s[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] :
269- {(A_WIDTH/ 8 ){1'b0 }};
342+ m_axis_tkeep_int_s[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] :
343+ {(A_WIDTH/ 8 ){1'b0 }};
270344 end
271345
272346 assign m_axis_data = m_axis_data_int_s;
273347 // if every instance has a valid data, the interface has valid data,
274348 // otherwise valid is asserted only if TLAST is asserted
275- // 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;
276349 if (TLAST_EN) begin
277350 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;
278351 end else begin
@@ -290,12 +363,21 @@ module util_axis_fifo_asym #(
290363
291364 end
292365
366+ sync_event #(
367+ .NUM_OF_EVENTS (1 ),
368+ .ASYNC_CLK (ASYNC_CLK)
369+ ) i_sdi_output_read_sync (
370+ .in_clk (m_axis_aclk),
371+ .in_event (m_axis_ready & m_axis_valid),
372+ .out_clk (s_axis_aclk),
373+ .out_event (sdi_output_read_sync));
374+
293375 endgenerate
294376
295377 generate
296378 if (RATIO == 1 ) begin
297379 initial begin
298- s_axis_counter = 1'b1 ;
380+ s_axis_counter = 1'b1 ; // s_axis_counter == 1 is never executed in small_slave
299381 end
300382 end else if (RATIO > 1 ) begin
301383 if (RATIO_TYPE) begin
0 commit comments