Skip to content

Commit 6bcd96f

Browse files
committed
Bypass pipeline FIFO when length is zero
1 parent a613cc8 commit 6bcd96f

File tree

2 files changed

+157
-141
lines changed

2 files changed

+157
-141
lines changed

rtl/axis_pipeline_fifo.v

+156-140
Original file line numberDiff line numberDiff line change
@@ -85,156 +85,172 @@ module axis_pipeline_fifo #
8585

8686
parameter FIFO_ADDR_WIDTH = LENGTH < 2 ? 3 : $clog2(LENGTH*4);
8787

88-
initial begin
89-
if (LENGTH < 1) begin
90-
$error("Error: LENGTH must be at least 1 (instance %m)");
91-
$finish;
92-
end
93-
end
94-
95-
// pipeline
96-
(* shreg_extract = "no" *)
97-
reg [DATA_WIDTH-1:0] axis_tdata_reg[0:LENGTH-1];
98-
(* shreg_extract = "no" *)
99-
reg [KEEP_WIDTH-1:0] axis_tkeep_reg[0:LENGTH-1];
100-
(* shreg_extract = "no" *)
101-
reg axis_tvalid_reg[0:LENGTH-1];
102-
(* shreg_extract = "no" *)
103-
reg axis_tready_reg[0:LENGTH-1];
104-
(* shreg_extract = "no" *)
105-
reg axis_tlast_reg[0:LENGTH-1];
106-
(* shreg_extract = "no" *)
107-
reg [ID_WIDTH-1:0] axis_tid_reg[0:LENGTH-1];
108-
(* shreg_extract = "no" *)
109-
reg [DEST_WIDTH-1:0] axis_tdest_reg[0:LENGTH-1];
110-
(* shreg_extract = "no" *)
111-
reg [USER_WIDTH-1:0] axis_tuser_reg[0:LENGTH-1];
112-
113-
wire [DATA_WIDTH-1:0] m_axis_tdata_int = axis_tdata_reg[LENGTH-1];
114-
wire [KEEP_WIDTH-1:0] m_axis_tkeep_int = axis_tkeep_reg[LENGTH-1];
115-
wire m_axis_tvalid_int = axis_tvalid_reg[LENGTH-1];
116-
wire m_axis_tready_int;
117-
wire m_axis_tlast_int = axis_tlast_reg[LENGTH-1];
118-
wire [ID_WIDTH-1:0] m_axis_tid_int = axis_tid_reg[LENGTH-1];
119-
wire [DEST_WIDTH-1:0] m_axis_tdest_int = axis_tdest_reg[LENGTH-1];
120-
wire [USER_WIDTH-1:0] m_axis_tuser_int = axis_tuser_reg[LENGTH-1];
121-
122-
assign s_axis_tready = axis_tready_reg[0];
123-
124-
integer i;
125-
126-
initial begin
127-
for (i = 0; i < LENGTH; i = i + 1) begin
128-
axis_tdata_reg[i] = {DATA_WIDTH{1'b0}};
129-
axis_tkeep_reg[i] = {KEEP_WIDTH{1'b0}};
130-
axis_tvalid_reg[i] = 1'b0;
131-
axis_tready_reg[i] = 1'b0;
132-
axis_tlast_reg[i] = 1'b0;
133-
axis_tid_reg[i] = {ID_WIDTH{1'b0}};
134-
axis_tdest_reg[i] = {DEST_WIDTH{1'b0}};
135-
axis_tuser_reg[i] = {USER_WIDTH{1'b0}};
136-
end
137-
end
138-
139-
always @(posedge clk) begin
140-
axis_tdata_reg[0] <= s_axis_tdata;
141-
axis_tkeep_reg[0] <= s_axis_tkeep;
142-
axis_tvalid_reg[0] <= s_axis_tvalid && s_axis_tready;
143-
axis_tready_reg[LENGTH-1] <= m_axis_tready_int;
144-
axis_tlast_reg[0] <= s_axis_tlast;
145-
axis_tid_reg[0] <= s_axis_tid;
146-
axis_tdest_reg[0] <= s_axis_tdest;
147-
axis_tuser_reg[0] <= s_axis_tuser;
148-
149-
for (i = 0; i < LENGTH-1; i = i + 1) begin
150-
axis_tdata_reg[i+1] <= axis_tdata_reg[i];
151-
axis_tkeep_reg[i+1] <= axis_tkeep_reg[i];
152-
axis_tvalid_reg[i+1] <= axis_tvalid_reg[i];
153-
axis_tready_reg[i] <= axis_tready_reg[i+1];
154-
axis_tlast_reg[i+1] <= axis_tlast_reg[i];
155-
axis_tid_reg[i+1] <= axis_tid_reg[i];
156-
axis_tdest_reg[i+1] <= axis_tdest_reg[i];
157-
axis_tuser_reg[i+1] <= axis_tuser_reg[i];
158-
end
159-
160-
if (rst) begin
88+
generate
89+
90+
if (LENGTH > 0) begin
91+
92+
// pipeline
93+
(* shreg_extract = "no" *)
94+
reg [DATA_WIDTH-1:0] axis_tdata_reg[0:LENGTH-1];
95+
(* shreg_extract = "no" *)
96+
reg [KEEP_WIDTH-1:0] axis_tkeep_reg[0:LENGTH-1];
97+
(* shreg_extract = "no" *)
98+
reg axis_tvalid_reg[0:LENGTH-1];
99+
(* shreg_extract = "no" *)
100+
reg axis_tready_reg[0:LENGTH-1];
101+
(* shreg_extract = "no" *)
102+
reg axis_tlast_reg[0:LENGTH-1];
103+
(* shreg_extract = "no" *)
104+
reg [ID_WIDTH-1:0] axis_tid_reg[0:LENGTH-1];
105+
(* shreg_extract = "no" *)
106+
reg [DEST_WIDTH-1:0] axis_tdest_reg[0:LENGTH-1];
107+
(* shreg_extract = "no" *)
108+
reg [USER_WIDTH-1:0] axis_tuser_reg[0:LENGTH-1];
109+
110+
wire [DATA_WIDTH-1:0] m_axis_tdata_int = axis_tdata_reg[LENGTH-1];
111+
wire [KEEP_WIDTH-1:0] m_axis_tkeep_int = axis_tkeep_reg[LENGTH-1];
112+
wire m_axis_tvalid_int = axis_tvalid_reg[LENGTH-1];
113+
wire m_axis_tready_int;
114+
wire m_axis_tlast_int = axis_tlast_reg[LENGTH-1];
115+
wire [ID_WIDTH-1:0] m_axis_tid_int = axis_tid_reg[LENGTH-1];
116+
wire [DEST_WIDTH-1:0] m_axis_tdest_int = axis_tdest_reg[LENGTH-1];
117+
wire [USER_WIDTH-1:0] m_axis_tuser_int = axis_tuser_reg[LENGTH-1];
118+
119+
assign s_axis_tready = axis_tready_reg[0];
120+
121+
integer i;
122+
123+
initial begin
161124
for (i = 0; i < LENGTH; i = i + 1) begin
125+
axis_tdata_reg[i] = {DATA_WIDTH{1'b0}};
126+
axis_tkeep_reg[i] = {KEEP_WIDTH{1'b0}};
162127
axis_tvalid_reg[i] = 1'b0;
163128
axis_tready_reg[i] = 1'b0;
129+
axis_tlast_reg[i] = 1'b0;
130+
axis_tid_reg[i] = {ID_WIDTH{1'b0}};
131+
axis_tdest_reg[i] = {DEST_WIDTH{1'b0}};
132+
axis_tuser_reg[i] = {USER_WIDTH{1'b0}};
164133
end
165134
end
166-
end
167135

168-
// output datapath logic
169-
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
170-
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
171-
reg m_axis_tvalid_reg = 1'b0;
172-
reg m_axis_tlast_reg = 1'b0;
173-
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
174-
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
175-
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
176-
177-
reg [FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0;
178-
reg [FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0;
179-
reg out_fifo_half_full_reg = 1'b0;
180-
181-
wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {FIFO_ADDR_WIDTH{1'b0}}});
182-
wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg;
183-
184-
(* ram_style = "distributed" *)
185-
reg [DATA_WIDTH-1:0] out_fifo_tdata[2**FIFO_ADDR_WIDTH-1:0];
186-
(* ram_style = "distributed" *)
187-
reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**FIFO_ADDR_WIDTH-1:0];
188-
(* ram_style = "distributed" *)
189-
reg out_fifo_tlast[2**FIFO_ADDR_WIDTH-1:0];
190-
(* ram_style = "distributed" *)
191-
reg [ID_WIDTH-1:0] out_fifo_tid[2**FIFO_ADDR_WIDTH-1:0];
192-
(* ram_style = "distributed" *)
193-
reg [DEST_WIDTH-1:0] out_fifo_tdest[2**FIFO_ADDR_WIDTH-1:0];
194-
(* ram_style = "distributed" *)
195-
reg [USER_WIDTH-1:0] out_fifo_tuser[2**FIFO_ADDR_WIDTH-1:0];
196-
197-
assign m_axis_tready_int = !out_fifo_half_full_reg;
198-
199-
assign m_axis_tdata = m_axis_tdata_reg;
200-
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
201-
assign m_axis_tvalid = m_axis_tvalid_reg;
202-
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
203-
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
204-
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
205-
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
206-
207-
always @(posedge clk) begin
208-
m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready;
209-
210-
out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(FIFO_ADDR_WIDTH-1);
211-
212-
if (!out_fifo_full && m_axis_tvalid_int) begin
213-
out_fifo_tdata[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_int;
214-
out_fifo_tkeep[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_int;
215-
out_fifo_tlast[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_int;
216-
out_fifo_tid[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_int;
217-
out_fifo_tdest[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_int;
218-
out_fifo_tuser[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_int;
219-
out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1;
220-
end
136+
always @(posedge clk) begin
137+
axis_tdata_reg[0] <= s_axis_tdata;
138+
axis_tkeep_reg[0] <= s_axis_tkeep;
139+
axis_tvalid_reg[0] <= s_axis_tvalid && s_axis_tready;
140+
axis_tlast_reg[0] <= s_axis_tlast;
141+
axis_tid_reg[0] <= s_axis_tid;
142+
axis_tdest_reg[0] <= s_axis_tdest;
143+
axis_tuser_reg[0] <= s_axis_tuser;
144+
145+
axis_tready_reg[LENGTH-1] <= m_axis_tready_int;
146+
147+
for (i = 0; i < LENGTH-1; i = i + 1) begin
148+
axis_tdata_reg[i+1] <= axis_tdata_reg[i];
149+
axis_tkeep_reg[i+1] <= axis_tkeep_reg[i];
150+
axis_tvalid_reg[i+1] <= axis_tvalid_reg[i];
151+
axis_tlast_reg[i+1] <= axis_tlast_reg[i];
152+
axis_tid_reg[i+1] <= axis_tid_reg[i];
153+
axis_tdest_reg[i+1] <= axis_tdest_reg[i];
154+
axis_tuser_reg[i+1] <= axis_tuser_reg[i];
155+
156+
axis_tready_reg[i] <= axis_tready_reg[i+1];
157+
end
221158

222-
if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready)) begin
223-
m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
224-
m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
225-
m_axis_tvalid_reg <= 1'b1;
226-
m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
227-
m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
228-
m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
229-
m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
230-
out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1;
159+
if (rst) begin
160+
for (i = 0; i < LENGTH; i = i + 1) begin
161+
axis_tvalid_reg[i] = 1'b0;
162+
axis_tready_reg[i] = 1'b0;
163+
end
164+
end
231165
end
232166

233-
if (rst) begin
234-
out_fifo_wr_ptr_reg <= 0;
235-
out_fifo_rd_ptr_reg <= 0;
236-
m_axis_tvalid_reg <= 1'b0;
167+
// output datapath logic
168+
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
169+
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
170+
reg m_axis_tvalid_reg = 1'b0;
171+
reg m_axis_tlast_reg = 1'b0;
172+
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
173+
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
174+
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
175+
176+
reg [FIFO_ADDR_WIDTH+1-1:0] out_fifo_wr_ptr_reg = 0;
177+
reg [FIFO_ADDR_WIDTH+1-1:0] out_fifo_rd_ptr_reg = 0;
178+
reg out_fifo_half_full_reg = 1'b0;
179+
180+
wire out_fifo_full = out_fifo_wr_ptr_reg == (out_fifo_rd_ptr_reg ^ {1'b1, {FIFO_ADDR_WIDTH{1'b0}}});
181+
wire out_fifo_empty = out_fifo_wr_ptr_reg == out_fifo_rd_ptr_reg;
182+
183+
(* ram_style = "distributed" *)
184+
reg [DATA_WIDTH-1:0] out_fifo_tdata[2**FIFO_ADDR_WIDTH-1:0];
185+
(* ram_style = "distributed" *)
186+
reg [KEEP_WIDTH-1:0] out_fifo_tkeep[2**FIFO_ADDR_WIDTH-1:0];
187+
(* ram_style = "distributed" *)
188+
reg out_fifo_tlast[2**FIFO_ADDR_WIDTH-1:0];
189+
(* ram_style = "distributed" *)
190+
reg [ID_WIDTH-1:0] out_fifo_tid[2**FIFO_ADDR_WIDTH-1:0];
191+
(* ram_style = "distributed" *)
192+
reg [DEST_WIDTH-1:0] out_fifo_tdest[2**FIFO_ADDR_WIDTH-1:0];
193+
(* ram_style = "distributed" *)
194+
reg [USER_WIDTH-1:0] out_fifo_tuser[2**FIFO_ADDR_WIDTH-1:0];
195+
196+
assign m_axis_tready_int = !out_fifo_half_full_reg;
197+
198+
assign m_axis_tdata = m_axis_tdata_reg;
199+
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
200+
assign m_axis_tvalid = m_axis_tvalid_reg;
201+
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
202+
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
203+
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
204+
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
205+
206+
always @(posedge clk) begin
207+
m_axis_tvalid_reg <= m_axis_tvalid_reg && !m_axis_tready;
208+
209+
out_fifo_half_full_reg <= $unsigned(out_fifo_wr_ptr_reg - out_fifo_rd_ptr_reg) >= 2**(FIFO_ADDR_WIDTH-1);
210+
211+
if (!out_fifo_full && m_axis_tvalid_int) begin
212+
out_fifo_tdata[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdata_int;
213+
out_fifo_tkeep[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tkeep_int;
214+
out_fifo_tlast[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tlast_int;
215+
out_fifo_tid[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tid_int;
216+
out_fifo_tdest[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tdest_int;
217+
out_fifo_tuser[out_fifo_wr_ptr_reg[FIFO_ADDR_WIDTH-1:0]] <= m_axis_tuser_int;
218+
out_fifo_wr_ptr_reg <= out_fifo_wr_ptr_reg + 1;
219+
end
220+
221+
if (!out_fifo_empty && (!m_axis_tvalid_reg || m_axis_tready)) begin
222+
m_axis_tdata_reg <= out_fifo_tdata[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
223+
m_axis_tkeep_reg <= out_fifo_tkeep[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
224+
m_axis_tvalid_reg <= 1'b1;
225+
m_axis_tlast_reg <= out_fifo_tlast[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
226+
m_axis_tid_reg <= out_fifo_tid[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
227+
m_axis_tdest_reg <= out_fifo_tdest[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
228+
m_axis_tuser_reg <= out_fifo_tuser[out_fifo_rd_ptr_reg[FIFO_ADDR_WIDTH-1:0]];
229+
out_fifo_rd_ptr_reg <= out_fifo_rd_ptr_reg + 1;
230+
end
231+
232+
if (rst) begin
233+
out_fifo_wr_ptr_reg <= 0;
234+
out_fifo_rd_ptr_reg <= 0;
235+
m_axis_tvalid_reg <= 1'b0;
236+
end
237237
end
238+
239+
end else begin
240+
// bypass
241+
242+
assign m_axis_tdata = s_axis_tdata;
243+
assign m_axis_tkeep = KEEP_ENABLE ? s_axis_tkeep : {KEEP_WIDTH{1'b1}};
244+
assign m_axis_tvalid = s_axis_tvalid;
245+
assign m_axis_tlast = LAST_ENABLE ? s_axis_tlast : 1'b1;
246+
assign m_axis_tid = ID_ENABLE ? s_axis_tid : {ID_WIDTH{1'b0}};
247+
assign m_axis_tdest = DEST_ENABLE ? s_axis_tdest : {DEST_WIDTH{1'b0}};
248+
assign m_axis_tuser = USER_ENABLE ? s_axis_tuser : {USER_WIDTH{1'b0}};
249+
250+
assign s_axis_tready = m_axis_tready;
251+
238252
end
239253

254+
endgenerate
255+
240256
endmodule

tb/axis_pipeline_fifo/test_axis_pipeline_fifo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def incrementing_payload(length):
213213

214214

215215
@pytest.mark.parametrize("data_width", [8, 16])
216-
@pytest.mark.parametrize("length", list(range(1, 17)))
216+
@pytest.mark.parametrize("length", list(range(17)))
217217
def test_axis_pipeline_fifo(request, length, data_width):
218218
dut = "axis_pipeline_fifo"
219219
module = os.path.splitext(os.path.basename(__file__))[0]

0 commit comments

Comments
 (0)