@@ -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;
@@ -117,8 +129,7 @@ module util_axis_fifo_asym #(
117129 .ALMOST_EMPTY_THRESHOLD (A_ALMOST_EMPTY_THRESHOLD),
118130 .ALMOST_FULL_THRESHOLD (A_ALMOST_FULL_THRESHOLD),
119131 .TKEEP_EN (TKEEP_EN),
120- .TLAST_EN (TLAST_EN),
121- .REMOVE_NULL_BEAT_EN(0 )
132+ .TLAST_EN (TLAST_EN)
122133 ) i_fifo (
123134 .m_axis_aclk (m_axis_aclk),
124135 .m_axis_aresetn (m_axis_aresetn),
@@ -146,6 +157,46 @@ module util_axis_fifo_asym #(
146157 // write or slave logic
147158 generate
148159
160+ integer j;
161+ always @(posedge s_axis_aclk) begin
162+ if (! s_axis_aresetn) begin
163+ num_of_words <= 1 ;
164+ s_axis_ready_d <= 0 ;
165+ s_axis_valid_d <= 0 ;
166+ end else begin
167+ s_axis_ready_d <= s_axis_ready;
168+ s_axis_valid_d <= s_axis_valid;
169+ word_counter = 0 ;
170+ for (j = 0 ; j < RATIO; j = j + 1 ) begin
171+ word_counter = word_counter + (| s_axis_tkeep[M_DATA_WIDTH/ 8 * j+ :M_DATA_WIDTH/ 8 ]);
172+ end
173+ num_of_words <= word_counter;
174+ end
175+ end
176+
177+ always @(posedge s_axis_aclk) begin
178+ if (! s_axis_aresetn) begin
179+ s_input_level <= 0 ;
180+ s_input_room <= {ADDRESS_WIDTH{1'b1 }};
181+ end else begin
182+ s_input_room <= s_input_room_next;
183+ s_input_level <= s_input_level_next;
184+ end
185+ end
186+
187+ always @(* ) begin
188+ s_input_level_next = s_input_level;
189+ s_input_room_next = s_input_room;
190+ if (s_axis_ready_d && s_axis_valid_d) begin
191+ s_input_level_next = s_input_level_next + num_of_words;
192+ s_input_room_next = s_input_room_next - 1 ;
193+ end
194+ if (sdi_output_read_sync) begin
195+ s_input_level_next = s_input_level_next - 1 ;
196+ s_input_room_next = s_input_room_next + num_of_words;
197+ end
198+ end
199+
149200 if (RATIO_TYPE) begin : big_slave
150201
151202 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
@@ -205,12 +256,18 @@ module util_axis_fifo_asym #(
205256
206257 // FULL/ALMOST_FULL is driven by the current atomic instance
207258 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)
212259 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 }}};
260+
261+ // FIFO room behavior relies on the TKEEP_EN parameter
262+ // When TKEEP_EN == 0, the FIFO has the same room as
263+ // the last atomic instance multiplied by RATIO. The
264+ // value of the room is only updated every RATIO reads.
265+ // s_axis_room == {s_axis_room_int_s[A_ADDRESS*(RATIO-1)+:A_ADDRESS], {$clog2(RATIO){1'b1}}}
266+ //
267+ // When TKEEP_EN == 1, it is using a counter whose decrement
268+ // relies on the tkeep.
269+ // s_axis_room == s_input_room
270+ assign s_axis_room = (TKEEP_EN) ? s_input_room : {s_axis_room_int_s[A_ADDRESS* (RATIO- 1 )+ :A_ADDRESS], {$clog2(RATIO){1'b1 }}};
214271
215272 end
216273
@@ -227,7 +284,7 @@ module util_axis_fifo_asym #(
227284 end
228285
229286 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 ) ;
287+ 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
231288
232289 // VALID/EMPTY/ALMOST_EMPTY is driven by the current atomic instance
233290 assign m_axis_valid_int = m_axis_valid_int_s >> m_axis_counter;
@@ -244,13 +301,29 @@ module util_axis_fifo_asym #(
244301
245302 assign m_axis_tlast = m_axis_tlast_int_s >> m_axis_counter;
246303
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 }}};
304+ // FIFO level behavior relies on the TKEEP_EN parameter
305+ // When TKEEP_EN == 0, the FIFO has the same level as
306+ // the last atomic instance multiplied by RATIO. The
307+ // value of the level is only updated every RATIO reads.
308+ // m_axis_level == {m_axis_level_int_s[A_ADDRESS-1:0], {$clog2(RATIO){1'b0}}}
309+ //
310+ // When TKEEP_EN == 1, it is using a counter whose increment
311+ // relies on the tkeep.
312+ // m_axis_level == m_output_level
313+ assign m_axis_level = (TKEEP_EN) ? m_output_level : {m_axis_level_int_s[A_ADDRESS- 1 :0 ], {$clog2(RATIO){1'b0 }}};
251314 assign m_axis_almost_empty = m_axis_almost_empty_int_s[RATIO- 1 ];
252315 assign m_axis_empty = m_axis_empty_int_s[RATIO- 1 ];
253316
317+ sync_data #(
318+ .NUM_OF_BITS (ADDRESS_WIDTH),
319+ .ASYNC_CLK (ASYNC_CLK)
320+ ) i_sdi_level_sync (
321+ .in_clk (s_axis_aclk),
322+ .in_data (s_input_level),
323+ .out_clk (m_axis_aclk),
324+ .out_data (m_output_level)
325+ );
326+
254327 end else begin : big_master
255328
256329 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
@@ -260,14 +333,13 @@ module util_axis_fifo_asym #(
260333 for (i= 0 ; i< RATIO; i= i+ 1 ) begin
261334 assign m_axis_tkeep[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] = ((m_axis_tlast_int_s[i:0 ] == 0 ) ||
262335 (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 }};
336+ m_axis_tkeep_int_s[i* A_WIDTH/ 8 + :A_WIDTH/ 8 ] :
337+ {(A_WIDTH/ 8 ){1'b0 }};
265338 end
266339
267340 assign m_axis_data = m_axis_data_int_s;
268341 // if every instance has a valid data, the interface has valid data,
269342 // 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;
271343 if (TLAST_EN) begin
272344 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;
273345 end else begin
@@ -285,12 +357,21 @@ module util_axis_fifo_asym #(
285357
286358 end
287359
360+ sync_event #(
361+ .NUM_OF_EVENTS (1 ),
362+ .ASYNC_CLK (ASYNC_CLK)
363+ ) i_sdi_output_read_sync (
364+ .in_clk (m_axis_aclk),
365+ .in_event (m_axis_ready & m_axis_valid),
366+ .out_clk (s_axis_aclk),
367+ .out_event (sdi_output_read_sync));
368+
288369 endgenerate
289370
290371 generate
291372 if (RATIO == 1 ) begin
292373 initial begin
293- s_axis_counter = 1'b1 ;
374+ s_axis_counter = 1'b1 ; // s_axis_counter == 1 is never executed in small_slave
294375 end
295376 end else if (RATIO > 1 ) begin
296377 if (RATIO_TYPE) begin
0 commit comments