Add DEFAULT_M and DEFAULT_N parameters for rate changing cores. This allows the host to not need to configure fixed rate change cores. Original-commit: 983fad664436301c31c3bc8c81b538a41537598b
142 lines
5.3 KiB
Verilog
142 lines
5.3 KiB
Verilog
//
|
|
// Copyright 2016 Ettus Research
|
|
// Copyright 2018 Ettus Research, a National Instruments Company
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
//
|
|
// Drop packets that are larger or smaller than the allowed packet size.
|
|
//
|
|
|
|
module axi_drop_partial_packet #(
|
|
parameter WIDTH = 32,
|
|
parameter MAX_PKT_SIZE = 1024,
|
|
parameter HOLD_LAST_WORD = 0, // Hold off sending last word until next full packet arrives
|
|
parameter SR_PKT_SIZE_ADDR = 1,
|
|
parameter DEFAULT_PKT_SIZE = 1
|
|
)(
|
|
input clk, input reset, input clear,
|
|
input flush, // If using HOLD_LAST_WORD, will forcibly release all words in FIFO
|
|
input set_stb, input [7:0] set_addr, input [31:0] set_data,
|
|
input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready,
|
|
output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready
|
|
);
|
|
|
|
generate
|
|
// Packet size of 1 means it is impossible to form a partial packet, so this module does nothing...
|
|
if (MAX_PKT_SIZE == 1) begin
|
|
assign o_tdata = i_tdata;
|
|
assign o_tlast = i_tlast;
|
|
assign o_tvalid = i_tvalid;
|
|
assign i_tready = o_tready;
|
|
// All other packet sizes
|
|
end else begin
|
|
// Settings register
|
|
wire [$clog2(MAX_PKT_SIZE+1)-1:0] sr_pkt_size;
|
|
setting_reg #(.my_addr(SR_PKT_SIZE_ADDR), .width($clog2(MAX_PKT_SIZE+1)), .at_reset(DEFAULT_PKT_SIZE)) set_pkt_size (
|
|
.clk(clk), .rst(reset), .strobe(set_stb), .addr(set_addr), .in(set_data),
|
|
.out(sr_pkt_size), .changed());
|
|
|
|
// Do not change n unless block is not active
|
|
reg active;
|
|
reg [$clog2(MAX_PKT_SIZE+1)-1:0] pkt_size = 1;
|
|
always @(posedge clk) begin
|
|
if (reset | clear) begin
|
|
active <= 1'b0;
|
|
end else begin
|
|
if (i_tready & i_tvalid) begin
|
|
active <= 1'b1;
|
|
end
|
|
end
|
|
if (clear | ~active) begin
|
|
pkt_size <= (sr_pkt_size == 0) ? 1 : sr_pkt_size;
|
|
end
|
|
end
|
|
|
|
wire [WIDTH-1:0] int_tdata;
|
|
wire int_tlast, int_tvalid, int_tready;
|
|
wire i_tlast_int, i_terror;
|
|
|
|
reg small_pkt, large_pkt;
|
|
wire hold_last_sample;
|
|
reg release_last;
|
|
reg [$clog2(MAX_PKT_SIZE+1)-1:0] in_cnt;
|
|
reg [15:0] in_pkt_cnt, in_pkt_cnt_hold, out_pkt_cnt;
|
|
always @(posedge clk) begin
|
|
if (reset | clear) begin
|
|
small_pkt <= 1'b0;
|
|
large_pkt <= 1'b0;
|
|
release_last <= 1'b0;
|
|
in_cnt <= 1;
|
|
in_pkt_cnt <= 0;
|
|
in_pkt_cnt_hold <= 0;
|
|
out_pkt_cnt <= 0;
|
|
end else begin
|
|
if (i_tvalid & i_tready) begin
|
|
if (in_cnt == pkt_size | i_tlast_int) begin
|
|
in_cnt <= 1;
|
|
end else begin
|
|
in_cnt <= in_cnt + 1;
|
|
end
|
|
end
|
|
if (pkt_size == 1) begin
|
|
small_pkt <= 1'b0;
|
|
large_pkt <= 1'b0;
|
|
end else begin
|
|
if (i_tvalid & i_tready) begin
|
|
if ((in_cnt == pkt_size-1'b1) & ~i_tlast) begin
|
|
small_pkt <= 1'b0;
|
|
end else begin
|
|
small_pkt <= 1'b1;
|
|
end
|
|
if ((in_cnt == pkt_size) & ~i_tlast) begin
|
|
large_pkt <= 1'b1;
|
|
end
|
|
if (large_pkt) begin
|
|
large_pkt <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
if (i_tvalid & i_tready & i_tlast & ~i_terror) begin
|
|
in_pkt_cnt <= in_pkt_cnt + 1'b1;
|
|
end
|
|
if (int_tvalid & int_tready & int_tlast & ~hold_last_sample) begin
|
|
out_pkt_cnt <= out_pkt_cnt + 1'b1;
|
|
end
|
|
if ((i_tvalid & i_tready & i_terror) | flush) begin
|
|
release_last <= 1'b1;
|
|
in_pkt_cnt_hold <= in_pkt_cnt;
|
|
end else if (in_pkt_cnt_hold == out_pkt_cnt) begin
|
|
release_last <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
assign hold_last_sample = ((in_pkt_cnt == out_pkt_cnt) | ((in_pkt_cnt == out_pkt_cnt+1) & ~release_last)) & (pkt_size != 1);
|
|
|
|
assign i_tlast_int = i_tlast | large_pkt;
|
|
assign i_terror = i_tlast & i_tvalid & (small_pkt | large_pkt);
|
|
|
|
// FIFO with ability to rewind write pointer back if input packet is flagged as bad
|
|
axi_packet_gate #(.WIDTH(WIDTH+1), .SIZE($clog2(MAX_PKT_SIZE+1)), .USE_AS_BUFF(1)) pkt_gate_i (
|
|
.clk(clk), .reset(reset), .clear(clear),
|
|
.i_tdata({i_tlast,i_tdata}), .i_tvalid(i_tvalid), .i_tlast(i_tlast_int), .i_terror(i_terror), .i_tready(i_tready),
|
|
.o_tdata({int_tlast,int_tdata}), .o_tvalid(int_tvalid), .o_tlast(), .o_tready(int_tready & ~(hold_last_sample & int_tlast)));
|
|
|
|
// Generate output register to hold on to last word
|
|
if (HOLD_LAST_WORD) begin
|
|
axi_fifo_flop2 #(.WIDTH(WIDTH+1)) axi_fifo_flop2 (
|
|
.clk(clk), .reset(reset), .clear(clear),
|
|
.i_tdata({int_tlast,int_tdata}), .i_tvalid(int_tvalid & ~(hold_last_sample & int_tlast)), .i_tready(int_tready),
|
|
.o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
|
|
.space(), .occupied());
|
|
end else begin
|
|
assign o_tdata = int_tdata;
|
|
assign o_tlast = int_tlast;
|
|
assign o_tvalid = int_tvalid;
|
|
assign int_tready = o_tready;
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|