fpga: lib: Clean up and document lib files
Clean-up and document axi_tag_time, dds_freq_tune, and axi_sync. Original-commit: 8edd13e6eba61ef2bfd96c7dc88b2642decbaa7a
This commit is contained in:
+74
-29
@@ -1,14 +1,32 @@
|
||||
//
|
||||
// Copyright 2016 Ettus Research
|
||||
// Copyright 2018 Ettus Research, a National Instruments Company
|
||||
// Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Synchronizes AXI stream buses so data is released on every port simultaneously.
|
||||
// Module: axi_sync
|
||||
//
|
||||
// Note: If inputs have inequal bitwidths, use WIDTH_VEC instead of WIDTH to define
|
||||
// the individual bit widths. Each bit width is defined with 8-bits stuffed
|
||||
// into a vector of width 8*SIZE.
|
||||
// Description:
|
||||
//
|
||||
// Synchronizes AXI stream buses so data is released on every port
|
||||
// simultaneously. Multiple inputs/outputs are supported by concatenating the
|
||||
// bus signals together. The number and size of each input/output bus is
|
||||
// controlled using parameters.
|
||||
//
|
||||
// **WARNING**: This module violates the AXI4-Stream specification by not
|
||||
// asserting TVALID until it receives TREADY. This will not
|
||||
// work if downstream logic waits for TVALID before asserting
|
||||
// TREADY, which is common. Use with care.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// SIZE : The number of inputs streams to synchronize.
|
||||
// WIDTH : The width of TDATA on the input streams, if they are all the
|
||||
// same width. If they are different widths, then use WIDTH_VEC
|
||||
// instead.
|
||||
// WIDTH_VEC : A vector of widths corresponding to each stream's TDATA width.
|
||||
// Each number in this vector must be 32 bits wide. This defaults
|
||||
// to WIDTH bits for all inputs.
|
||||
// FIFO_SIZE : Log2 the size of the FIFO to use internally for each stream.
|
||||
//
|
||||
|
||||
module axi_sync #(
|
||||
@@ -16,48 +34,75 @@ module axi_sync #(
|
||||
parameter WIDTH = 32,
|
||||
parameter [32*SIZE-1:0] WIDTH_VEC = {SIZE{WIDTH[31:0]}},
|
||||
parameter FIFO_SIZE = 0
|
||||
)(
|
||||
input clk, input reset, input clear,
|
||||
input [msb(SIZE,WIDTH_VEC)-1:0] i_tdata, input [SIZE-1:0] i_tlast, input [SIZE-1:0] i_tvalid, output [SIZE-1:0] i_tready,
|
||||
output [msb(SIZE,WIDTH_VEC)-1:0] o_tdata, output [SIZE-1:0] o_tlast, output [SIZE-1:0] o_tvalid, input [SIZE-1:0] o_tready
|
||||
) (
|
||||
input clk,
|
||||
input reset,
|
||||
input clear,
|
||||
|
||||
// Input streams
|
||||
input [len(SIZE)-1:0] i_tdata,
|
||||
input [ SIZE-1:0] i_tlast,
|
||||
input [ SIZE-1:0] i_tvalid,
|
||||
output [ SIZE-1:0] i_tready,
|
||||
|
||||
// Output streams
|
||||
output [len(SIZE)-1:0] o_tdata,
|
||||
output [ SIZE-1:0] o_tlast,
|
||||
output [ SIZE-1:0] o_tvalid,
|
||||
input [ SIZE-1:0] o_tready
|
||||
);
|
||||
|
||||
// Helper function to calculate the MSB index based on widths stored in WIDTH_VEC.
|
||||
// Note: If n is negative, returns 0
|
||||
function automatic integer msb(input integer n, input [SIZE*32-1:0] bit_vec);
|
||||
// Helper function to calculate the combined length of the lower 'n' ports
|
||||
// based on widths stored in WIDTH_VEC. Note: If n is negative, returns 0.
|
||||
function automatic integer len(input integer n);
|
||||
integer i, total;
|
||||
begin
|
||||
total = 0;
|
||||
if (n >= 0) begin
|
||||
for (i = 0; i <= n; i = i + 1) begin
|
||||
total = total + ((bit_vec >> 32*i) & 32'hFF);
|
||||
total = total + ((WIDTH_VEC >> 32*i) & 32'hFFFF);
|
||||
end
|
||||
end
|
||||
msb = total;
|
||||
len = total;
|
||||
end
|
||||
endfunction
|
||||
|
||||
wire [msb(SIZE,WIDTH_VEC)-1:0] int_tdata;
|
||||
wire [SIZE-1:0] int_tlast, int_tvalid, int_tready;
|
||||
wire [len(SIZE)-1:0] int_tdata;
|
||||
wire [ SIZE-1:0] int_tlast;
|
||||
wire [ SIZE-1:0] int_tvalid;
|
||||
wire [ SIZE-1:0] int_tready;
|
||||
|
||||
// Generate a FIFO for each stream
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < SIZE; i = i + 1) begin
|
||||
axi_fifo #(.WIDTH(msb(i,WIDTH_VEC)-msb(i-1,WIDTH_VEC)+1), .SIZE(FIFO_SIZE)) axi_fifo (
|
||||
.clk(clk), .reset(reset), .clear(clear),
|
||||
.i_tdata({i_tlast[i],i_tdata[msb(i,WIDTH_VEC)-1:msb(i-1,WIDTH_VEC)]}),
|
||||
.i_tvalid(i_tvalid[i]), .i_tready(i_tready[i]),
|
||||
.o_tdata({int_tlast[i],int_tdata[msb(i,WIDTH_VEC)-1:msb(i-1,WIDTH_VEC)]}),
|
||||
.o_tvalid(int_tvalid[i]), .o_tready(int_tready[i]),
|
||||
.space(), .occupied());
|
||||
axi_fifo #(
|
||||
.WIDTH (len(i)-len(i-1)+1),
|
||||
.SIZE (FIFO_SIZE)
|
||||
) axi_fifo (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.clear (clear),
|
||||
.i_tdata ({ i_tlast[i], i_tdata[len(i)-1 : len(i-1)] }),
|
||||
.i_tvalid (i_tvalid[i]),
|
||||
.i_tready (i_tready[i]),
|
||||
.o_tdata ({ int_tlast[i], int_tdata[len(i)-1 : len(i-1)] }),
|
||||
.o_tvalid (int_tvalid[i]),
|
||||
.o_tready (int_tready[i]),
|
||||
.space (),
|
||||
.occupied ()
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// We allow a transfer and consume the outputs of the FIFOs when all
|
||||
// downstream blocks are ready to accept a transfer (o_tready is true for all
|
||||
// streams) and all FIFOs have data ready (int_tvalid is true for all FIFOs).
|
||||
wire consume = (&int_tvalid) & (&o_tready);
|
||||
|
||||
assign int_tready = {SIZE{consume}};
|
||||
assign o_tvalid = {SIZE{consume}};
|
||||
assign o_tdata = int_tdata;
|
||||
assign o_tlast = int_tlast;
|
||||
|
||||
wire consume = (&int_tvalid) & (&o_tready);
|
||||
assign int_tready = {SIZE{consume}};
|
||||
assign o_tvalid = {SIZE{consume}};
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user