@@ -118,6 +118,15 @@ wire [S_COUNT-1:0] grant;
118118wire grant_valid;
119119wire [CL_S_COUNT- 1 :0 ] grant_encoded;
120120
121+ // input registers to pipeline arbitration delay
122+ reg [S_COUNT* DATA_WIDTH- 1 :0 ] s_axis_tdata_reg = 0 ;
123+ reg [S_COUNT* KEEP_WIDTH- 1 :0 ] s_axis_tkeep_reg = 0 ;
124+ reg [S_COUNT- 1 :0 ] s_axis_tvalid_reg = 0 ;
125+ reg [S_COUNT- 1 :0 ] s_axis_tlast_reg = 0 ;
126+ reg [S_COUNT* S_ID_WIDTH- 1 :0 ] s_axis_tid_reg = 0 ;
127+ reg [S_COUNT* DEST_WIDTH- 1 :0 ] s_axis_tdest_reg = 0 ;
128+ reg [S_COUNT* USER_WIDTH- 1 :0 ] s_axis_tuser_reg = 0 ;
129+
121130// internal datapath
122131reg [DATA_WIDTH- 1 :0 ] m_axis_tdata_int;
123132reg [KEEP_WIDTH- 1 :0 ] m_axis_tkeep_int;
@@ -129,17 +138,17 @@ reg [DEST_WIDTH-1:0] m_axis_tdest_int;
129138reg [USER_WIDTH- 1 :0 ] m_axis_tuser_int;
130139wire m_axis_tready_int_early;
131140
132- assign s_axis_tready = ( m_axis_tready_int_reg && grant_valid) << grant_encoded ;
141+ assign s_axis_tready = ~ s_axis_tvalid_reg | ({S_COUNT{ m_axis_tready_int_reg}} & grant) ;
133142
134143// mux for incoming packet
135- wire [DATA_WIDTH- 1 :0 ] current_s_tdata = s_axis_tdata [grant_encoded* DATA_WIDTH + : DATA_WIDTH];
136- wire [KEEP_WIDTH- 1 :0 ] current_s_tkeep = s_axis_tkeep [grant_encoded* KEEP_WIDTH + : KEEP_WIDTH];
137- wire current_s_tvalid = s_axis_tvalid [grant_encoded];
144+ wire [DATA_WIDTH- 1 :0 ] current_s_tdata = s_axis_tdata_reg [grant_encoded* DATA_WIDTH + : DATA_WIDTH];
145+ wire [KEEP_WIDTH- 1 :0 ] current_s_tkeep = s_axis_tkeep_reg [grant_encoded* KEEP_WIDTH + : KEEP_WIDTH];
146+ wire current_s_tvalid = s_axis_tvalid_reg [grant_encoded];
138147wire current_s_tready = s_axis_tready[grant_encoded];
139- wire current_s_tlast = s_axis_tlast [grant_encoded];
140- wire [S_ID_WIDTH- 1 :0 ] current_s_tid = s_axis_tid [grant_encoded* S_ID_WIDTH + : S_ID_WIDTH_INT];
141- wire [DEST_WIDTH- 1 :0 ] current_s_tdest = s_axis_tdest [grant_encoded* DEST_WIDTH + : DEST_WIDTH];
142- wire [USER_WIDTH- 1 :0 ] current_s_tuser = s_axis_tuser [grant_encoded* USER_WIDTH + : USER_WIDTH];
148+ wire current_s_tlast = s_axis_tlast_reg [grant_encoded];
149+ wire [S_ID_WIDTH- 1 :0 ] current_s_tid = s_axis_tid_reg [grant_encoded* S_ID_WIDTH + : S_ID_WIDTH_INT];
150+ wire [DEST_WIDTH- 1 :0 ] current_s_tdest = s_axis_tdest_reg [grant_encoded* DEST_WIDTH + : DEST_WIDTH];
151+ wire [USER_WIDTH- 1 :0 ] current_s_tuser = s_axis_tuser_reg [grant_encoded* USER_WIDTH + : USER_WIDTH];
143152
144153// arbiter instance
145154arbiter #(
@@ -159,8 +168,8 @@ arb_inst (
159168 .grant_encoded(grant_encoded)
160169);
161170
162- assign request = s_axis_tvalid & ~ grant;
163- assign acknowledge = grant & s_axis_tvalid & s_axis_tready & (LAST_ENABLE ? s_axis_tlast : {S_COUNT{1'b1 }});
171+ assign request = (s_axis_tvalid_reg & ~ grant) | (s_axis_tvalid & grant) ;
172+ assign acknowledge = grant & s_axis_tvalid_reg & {S_COUNT{m_axis_tready_int_reg}} & (LAST_ENABLE ? s_axis_tlast_reg : {S_COUNT{1'b1 }});
164173
165174always @* begin
166175 // pass through selected packet data
@@ -176,6 +185,27 @@ always @* begin
176185 m_axis_tuser_int = current_s_tuser;
177186end
178187
188+ integer i;
189+
190+ always @(posedge clk) begin
191+ // register inputs
192+ for (i = 0 ; i < S_COUNT; i = i + 1 ) begin
193+ if (s_axis_tready[i]) begin
194+ s_axis_tdata_reg[i* DATA_WIDTH + : DATA_WIDTH] <= s_axis_tdata[i* DATA_WIDTH + : DATA_WIDTH];
195+ s_axis_tkeep_reg[i* KEEP_WIDTH + : KEEP_WIDTH] <= s_axis_tkeep[i* KEEP_WIDTH + : KEEP_WIDTH];
196+ s_axis_tvalid_reg[i] <= s_axis_tvalid[i];
197+ s_axis_tlast_reg[i] <= s_axis_tlast[i];
198+ s_axis_tid_reg[i* S_ID_WIDTH + : S_ID_WIDTH_INT] <= s_axis_tid[i* S_ID_WIDTH + : S_ID_WIDTH_INT];
199+ s_axis_tdest_reg[i* DEST_WIDTH + : DEST_WIDTH] <= s_axis_tdest[i* DEST_WIDTH + : DEST_WIDTH];
200+ s_axis_tuser_reg[i* USER_WIDTH + : USER_WIDTH] <= s_axis_tuser[i* USER_WIDTH + : USER_WIDTH];
201+ end
202+ end
203+
204+ if (rst) begin
205+ s_axis_tvalid_reg <= 0 ;
206+ end
207+ end
208+
179209// output datapath logic
180210reg [DATA_WIDTH- 1 :0 ] m_axis_tdata_reg = {DATA_WIDTH{1'b0 }};
181211reg [KEEP_WIDTH- 1 :0 ] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0 }};
@@ -206,8 +236,8 @@ assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {M_ID_WIDTH{1'b0}};
206236assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0 }};
207237assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0 }};
208238
209- // enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle ( output reg empty or no input)
210- assign m_axis_tready_int_early = m_axis_tready || (! temp_m_axis_tvalid_reg && ( ! m_axis_tvalid_reg || ! m_axis_tvalid_int) );
239+ // enable ready input next cycle if output is ready or if both output registers are empty
240+ assign m_axis_tready_int_early = m_axis_tready || (! temp_m_axis_tvalid_reg && ! m_axis_tvalid_reg);
211241
212242always @* begin
213243 // transfer sink ready state to source
@@ -238,15 +268,9 @@ always @* begin
238268end
239269
240270always @(posedge clk) begin
241- if (rst) begin
242- m_axis_tvalid_reg <= 1'b0 ;
243- m_axis_tready_int_reg <= 1'b0 ;
244- temp_m_axis_tvalid_reg <= 1'b0 ;
245- end else begin
246- m_axis_tvalid_reg <= m_axis_tvalid_next;
247- m_axis_tready_int_reg <= m_axis_tready_int_early;
248- temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next;
249- end
271+ m_axis_tvalid_reg <= m_axis_tvalid_next;
272+ m_axis_tready_int_reg <= m_axis_tready_int_early;
273+ temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next;
250274
251275 // datapath
252276 if (store_axis_int_to_output) begin
@@ -273,6 +297,12 @@ always @(posedge clk) begin
273297 temp_m_axis_tdest_reg <= m_axis_tdest_int;
274298 temp_m_axis_tuser_reg <= m_axis_tuser_int;
275299 end
300+
301+ if (rst) begin
302+ m_axis_tvalid_reg <= 1'b0 ;
303+ m_axis_tready_int_reg <= 1'b0 ;
304+ temp_m_axis_tvalid_reg <= 1'b0 ;
305+ end
276306end
277307
278308endmodule
0 commit comments