fpga: lib: Fix SWITCH_ON_LAST in axi_mux_select
Thange allows the mux to switch cleanly between packets, if the mux select input is changed while a packet is in flight. Original-commit: cee09d96aee51795ba2c6578f75f25f30ea11548
This commit is contained in:
+39
-18
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
//
|
//
|
||||||
// AXI-Stream multipler with select line
|
// AXI-Stream multiplexer with select line
|
||||||
//
|
//
|
||||||
|
|
||||||
module axi_mux_select #(
|
module axi_mux_select #(
|
||||||
@@ -29,12 +29,12 @@ module axi_mux_select #(
|
|||||||
|
|
||||||
genvar n;
|
genvar n;
|
||||||
generate
|
generate
|
||||||
if (PRE_FIFO_SIZE == 0) begin
|
if (PRE_FIFO_SIZE == 0) begin : gen_no_pre_fifo
|
||||||
assign i_tdata_int = i_tdata;
|
assign i_tdata_int = i_tdata;
|
||||||
assign i_tlast_int = i_tlast;
|
assign i_tlast_int = i_tlast;
|
||||||
assign i_tvalid_int = i_tvalid;
|
assign i_tvalid_int = i_tvalid;
|
||||||
assign i_tready = i_tready_int;
|
assign i_tready = i_tready_int;
|
||||||
end else begin
|
end else begin : gen_pre_fifo
|
||||||
for (n = 0; n < SIZE; n = n + 1) begin
|
for (n = 0; n < SIZE; n = n + 1) begin
|
||||||
axi_fifo #(.WIDTH(WIDTH+1), .SIZE(PRE_FIFO_SIZE)) axi_fifo (
|
axi_fifo #(.WIDTH(WIDTH+1), .SIZE(PRE_FIFO_SIZE)) axi_fifo (
|
||||||
.clk(clk), .reset(reset), .clear(clear),
|
.clk(clk), .reset(reset), .clear(clear),
|
||||||
@@ -48,32 +48,53 @@ module axi_mux_select #(
|
|||||||
// Make arrays for easier muxing
|
// Make arrays for easier muxing
|
||||||
genvar i;
|
genvar i;
|
||||||
generate
|
generate
|
||||||
for (i = 0; i < SIZE; i = i + 1) begin
|
for (i = 0; i < SIZE; i = i + 1) begin : gen_muxing
|
||||||
assign i_tdata_arr[i] = i_tdata_int[WIDTH*(i+1)-1:WIDTH*i];
|
assign i_tdata_arr[i] = i_tdata_int[WIDTH*(i+1)-1:WIDTH*i];
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
// Switch select line either immediately or after the last word in a packet
|
// Switch select line either immediately or if we're not in the middle of a
|
||||||
reg [$clog2(SIZE)-1:0] select_hold;
|
// packet.
|
||||||
|
reg [$clog2(SIZE)-1:0] select_hold = 0;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (SWITCH_ON_LAST) begin
|
if (SWITCH_ON_LAST) begin : gen_switch_on_last
|
||||||
reg init;
|
reg in_packet_reg = 1'b0;
|
||||||
|
wire in_packet;
|
||||||
|
wire end_of_packet;
|
||||||
|
wire enable_switch;
|
||||||
|
|
||||||
|
// Create a signal to indicate if we're in the middle of a packet
|
||||||
|
assign in_packet = in_packet_reg || o_tvalid_int;
|
||||||
|
|
||||||
|
// Create a signal to indicate if this is the last transfer of the packet
|
||||||
|
assign end_of_packet = o_tlast_int & o_tvalid_int & o_tready_int;
|
||||||
|
|
||||||
|
// Create a signal that indicates when it's OK to switch the mux select.
|
||||||
|
// We can switch if we're not in the middle of outputting a packet, or if
|
||||||
|
// we're on the last transfer of a packet.
|
||||||
|
assign enable_switch = !in_packet || end_of_packet;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (reset | clear) begin
|
if (reset | clear) begin
|
||||||
init <= 1'b0;
|
select_hold <= 0;
|
||||||
select_hold <= 'd0;
|
in_packet_reg <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (|i_tvalid) begin
|
// Use in_packet_reg to indicate if we're in a packet. But this
|
||||||
init <= 1'b1;
|
// register is delayed by a clock cycle, so we need the in_pakcet
|
||||||
|
// signal above to add the first clock cycle of a packet.
|
||||||
|
if (end_of_packet) begin
|
||||||
|
in_packet_reg <= 1'b0;
|
||||||
|
end else if (o_tvalid_int) begin
|
||||||
|
in_packet_reg <= 1'b1;
|
||||||
end
|
end
|
||||||
// Set select any time after reset and before the first packet OR
|
|
||||||
// at the end of a packet
|
if (enable_switch) begin
|
||||||
if (~init | (o_tlast_int & o_tvalid_int & o_tready_int)) begin
|
|
||||||
select_hold <= select;
|
select_hold <= select;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin : gen_no_switch_on_last
|
||||||
always @(*) begin
|
always @(*) begin
|
||||||
select_hold <= select;
|
select_hold <= select;
|
||||||
end
|
end
|
||||||
@@ -87,12 +108,12 @@ module axi_mux_select #(
|
|||||||
assign i_tready_int = (1'b1 << select_hold) & {SIZE{o_tready_int}};
|
assign i_tready_int = (1'b1 << select_hold) & {SIZE{o_tready_int}};
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if(POST_FIFO_SIZE == 0) begin
|
if(POST_FIFO_SIZE == 0) begin : gen_no_post_fifo
|
||||||
assign o_tdata = o_tdata_int;
|
assign o_tdata = o_tdata_int;
|
||||||
assign o_tlast = o_tlast_int;
|
assign o_tlast = o_tlast_int;
|
||||||
assign o_tvalid = o_tvalid_int;
|
assign o_tvalid = o_tvalid_int;
|
||||||
assign o_tready_int = o_tready;
|
assign o_tready_int = o_tready;
|
||||||
end else begin
|
end else begin : gen_post_fifo
|
||||||
axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo (
|
axi_fifo #(.WIDTH(WIDTH+1),.SIZE(POST_FIFO_SIZE)) axi_fifo (
|
||||||
.clk(clk), .reset(reset), .clear(clear),
|
.clk(clk), .reset(reset), .clear(clear),
|
||||||
.i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
|
.i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
|
||||||
|
|||||||
Reference in New Issue
Block a user