From 90540bf4470636f0e9a57e16fe5a21e7760c6bd5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 7 Oct 2018 14:39:27 +0200 Subject: [PATCH] Add util_upack2 core The util_upack2 core is similar to the util_upack core. It unpacks, or deinterleaves, a data stream onto multiple ports. The upack2 core uses a streaming AXI interface for its data source instead of a FIFO interface like the upack core uses. On the output side the upack2 core uses a multi-port FIFO interface. There is a single data request signal (fifo_rd_en) for all ports. But each port can be individually enabled or disabled using the enable signals. This modified architecture allows the upack2 core to better generate the valid and underflow control signals to indicate whether data is available in a response to a data request. If fifo_rd_en is asserted and data is available the fifo_rd_valid signal are asserted in the following clock cycle. The enabled fifo_rd_data ports will be contain valid data during the same clock cycle as fifo_rd_valid is asserted. During other clock cycles the output data is undefined. On disabled ports the data is always undefined. If no data is available instead the fifo_rd_underflow signal is asserted in the following clock cycle and the output of all fifo_rd_data ports is undefined. This core is build using the common pack infrastructure. The core that is specific to the upack2 core is mainly only responsible for generating the control signals for the external interfaces. The core is accompanied by a test bench that verifies correct behavior for all possible combinations of enable masks. Signed-off-by: Lars-Peter Clausen --- library/Makefile | 2 + library/util_pack/tb/.gitignore | 2 + library/util_pack/tb/run_tb.sh | 32 ++++ library/util_pack/tb/tb_base.v | 67 +++++++ library/util_pack/tb/underflow_tb | 12 ++ library/util_pack/tb/underflow_tb.v | 119 ++++++++++++ library/util_pack/tb/upack_tb | 12 ++ library/util_pack/tb/upack_tb.v | 169 ++++++++++++++++++ library/util_pack/util_upack2/Makefile | 20 +++ library/util_pack/util_upack2/util_upack2.v | 149 +++++++++++++++ .../util_pack/util_upack2/util_upack2_hw.tcl | 109 +++++++++++ .../util_pack/util_upack2/util_upack2_impl.v | 146 +++++++++++++++ .../util_pack/util_upack2/util_upack2_ip.tcl | 68 +++++++ 13 files changed, 907 insertions(+) create mode 100644 library/util_pack/tb/.gitignore create mode 100644 library/util_pack/tb/run_tb.sh create mode 100644 library/util_pack/tb/tb_base.v create mode 100755 library/util_pack/tb/underflow_tb create mode 100644 library/util_pack/tb/underflow_tb.v create mode 100755 library/util_pack/tb/upack_tb create mode 100644 library/util_pack/tb/upack_tb.v create mode 100644 library/util_pack/util_upack2/Makefile create mode 100644 library/util_pack/util_upack2/util_upack2.v create mode 100644 library/util_pack/util_upack2/util_upack2_hw.tcl create mode 100644 library/util_pack/util_upack2/util_upack2_impl.v create mode 100644 library/util_pack/util_upack2/util_upack2_ip.tcl diff --git a/library/Makefile b/library/Makefile index 08b80ff64..bcd0c7d14 100644 --- a/library/Makefile +++ b/library/Makefile @@ -100,6 +100,7 @@ clean: $(MAKE) -C util_gmii_to_rgmii clean $(MAKE) -C util_i2c_mixer clean $(MAKE) -C util_mfifo clean + $(MAKE) -C util_pack/util_upack2 clean $(MAKE) -C util_pulse_gen clean $(MAKE) -C util_rfifo clean $(MAKE) -C util_sigma_delta_spi clean @@ -208,6 +209,7 @@ lib: $(MAKE) -C util_gmii_to_rgmii $(MAKE) -C util_i2c_mixer $(MAKE) -C util_mfifo + $(MAKE) -C util_pack/util_upack2 $(MAKE) -C util_pulse_gen $(MAKE) -C util_rfifo $(MAKE) -C util_sigma_delta_spi diff --git a/library/util_pack/tb/.gitignore b/library/util_pack/tb/.gitignore new file mode 100644 index 000000000..804d96e77 --- /dev/null +++ b/library/util_pack/tb/.gitignore @@ -0,0 +1,2 @@ +run/ +vcd/ diff --git a/library/util_pack/tb/run_tb.sh b/library/util_pack/tb/run_tb.sh new file mode 100644 index 000000000..43a5b0779 --- /dev/null +++ b/library/util_pack/tb/run_tb.sh @@ -0,0 +1,32 @@ +NAME=`basename $0` + +mkdir -p run +mkdir -p vcd + +WARNINGS="-Wimplicit -Wportbind -Wselect-range -Wtimescale" + +# These warnings are only available with version 11 +iverilog -v 2>&1 | grep -o "version 1[^0]" > /dev/null +if [[ $? = 0 ]]; then + WARNINGS+=" -Wfloating-nets -Wanachronisms -Wimplicit-dimensions" +fi + +# Can be overwritten using a environment variables +NUM_CHANNELS=${NUM_CHANNELS:-"1 2 4 8 16 32"} +SAMPLES_PER_CHANNEL=${SAMPLES_PER_CHANNEL:-1} +VCD=${VCD:-0} + +for i in ${NUM_CHANNELS}; do + if [[ $VCD = 0 ]]; then + VCD_FILE='""'; + else + VCD_FILE='"'${NAME}_${SAMPLES_PER_CHANNEL}_${i}'.vcd"' + fi + echo Testing $i Channels... + iverilog ${WARNINGS} ${SOURCE} -o run/run_${NAME}_${i} $1 \ + -P ${NAME}.NUM_OF_CHANNELS=${i} \ + -P ${NAME}.SAMPLES_PER_CHANNEL=${SAMPLES_PER_CHANNEL} \ + -P ${NAME}.VCD_FILE=${VCD_FILE} \ + || exit 1 + (cd vcd; vvp -N ../run/run_${NAME}_${i}) +done diff --git a/library/util_pack/tb/tb_base.v b/library/util_pack/tb/tb_base.v new file mode 100644 index 000000000..f721d873d --- /dev/null +++ b/library/util_pack/tb/tb_base.v @@ -0,0 +1,67 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + + reg clk = 1'b1; + reg [3:0] reset_shift = 4'b1111; + reg trigger_reset = 1'b0; + wire reset; + + reg failed = 1'b0; + + initial + begin + if (VCD_FILE != "") begin + $dumpfile (VCD_FILE); + $dumpvars; + end + end + + always @(*) #10 clk <= ~clk; + always @(posedge clk) begin + if (trigger_reset == 1'b1) begin + reset_shift <= 4'b1111; + end else begin + reset_shift <= {reset_shift[2:0],1'b0}; + end + end + + assign reset = reset_shift[3]; + + task do_trigger_reset; + begin + @(posedge clk) trigger_reset <= 1'b1; + @(posedge clk) trigger_reset <= 1'b0; + end + endtask diff --git a/library/util_pack/tb/underflow_tb b/library/util_pack/tb/underflow_tb new file mode 100755 index 000000000..08a32708e --- /dev/null +++ b/library/util_pack/tb/underflow_tb @@ -0,0 +1,12 @@ +#!/bin/bash + +SOURCE="underflow_tb.v" +SOURCE+=" ../util_upack2/util_upack2_impl.v" +SOURCE+=" ../util_pack_common/pack_ctrl.v" +SOURCE+=" ../util_pack_common/pack_interconnect.v" +SOURCE+=" ../util_pack_common/pack_network.v" +SOURCE+=" ../util_pack_common/pack_shell.v" +SOURCE+=" ../../common/ad_perfect_shuffle.v" + +cd `dirname $0` +source run_tb.sh diff --git a/library/util_pack/tb/underflow_tb.v b/library/util_pack/tb/underflow_tb.v new file mode 100644 index 000000000..34d69f944 --- /dev/null +++ b/library/util_pack/tb/underflow_tb.v @@ -0,0 +1,119 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module upack2_underflow_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + parameter NUM_OF_CHANNELS = 8; + parameter SAMPLES_PER_CHANNEL = 4; + + `include "tb_base.v" + + initial + begin + #1500000 + if (failed == 1'b0) + $display("SUCCESS"); + else + $display("FAILED"); + $finish; + end + + localparam NUM_OF_PORTS = SAMPLES_PER_CHANNEL * NUM_OF_CHANNELS; + + reg fifo_rd_en = 1'b1; + wire [NUM_OF_PORTS*8-1:0] fifo_rd_data; + wire fifo_rd_valid; + wire fifo_rd_underflow; + + reg s_axis_valid = 1'b1; + wire s_axis_ready; + reg [NUM_OF_PORTS*8-1:0] s_axis_data = {NUM_OF_PORTS*8{1'b1}}; + + reg [NUM_OF_CHANNELS-1:0] enable = {NUM_OF_CHANNELS{1'b1}}; + integer counter = 0; + + always @(posedge clk) begin + if (fifo_rd_underflow == 1'b1 && fifo_rd_data != 'h00) begin + failed <= 1'b1; + end + if (fifo_rd_valid == 1'b1 && fifo_rd_data != {NUM_OF_PORTS*8{1'b1}}) begin + failed <= 1'b1; + end + end + + always @(posedge clk) begin + if (reset == 1'b1) begin + counter <= 0; + s_axis_valid <= 1'b1; + end else begin + if (s_axis_valid == 1'b0) begin + if (counter == 8) begin + s_axis_valid <= 1'b1; + end + counter <= counter + 1; + end else if (s_axis_ready == 1'b1) begin + s_axis_valid <= 1'b0; + counter <= 0; + end + end + end + + always @(posedge clk) begin + fifo_rd_en <= $random & 1; + end + + util_upack2_impl #( + .NUM_OF_CHANNELS(NUM_OF_CHANNELS), + .SAMPLES_PER_CHANNEL(SAMPLES_PER_CHANNEL), + .SAMPLE_DATA_WIDTH(8) + ) i_unpack ( + .clk(clk), + .reset(reset), + + .enable(enable), + + .fifo_rd_en({NUM_OF_CHANNELS{fifo_rd_en}}), + .fifo_rd_data(fifo_rd_data), + .fifo_rd_valid(fifo_rd_valid), + .fifo_rd_underflow(fifo_rd_underflow), + + .s_axis_valid(s_axis_valid), + .s_axis_ready(s_axis_ready), + .s_axis_data(s_axis_data) + ); + +endmodule diff --git a/library/util_pack/tb/upack_tb b/library/util_pack/tb/upack_tb new file mode 100755 index 000000000..4b132d4b7 --- /dev/null +++ b/library/util_pack/tb/upack_tb @@ -0,0 +1,12 @@ +#!/bin/bash + +SOURCE="upack_tb.v" +SOURCE+=" ../util_upack2/util_upack2_impl.v" +SOURCE+=" ../util_pack_common/pack_ctrl.v" +SOURCE+=" ../util_pack_common/pack_interconnect.v" +SOURCE+=" ../util_pack_common/pack_network.v" +SOURCE+=" ../util_pack_common/pack_shell.v" +SOURCE+=" ../../common/ad_perfect_shuffle.v" + +cd `dirname $0` +source run_tb.sh diff --git a/library/util_pack/tb/upack_tb.v b/library/util_pack/tb/upack_tb.v new file mode 100644 index 000000000..e4cbe4460 --- /dev/null +++ b/library/util_pack/tb/upack_tb.v @@ -0,0 +1,169 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module upack_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + parameter NUM_OF_CHANNELS = 8; + parameter SAMPLES_PER_CHANNEL = 1; + parameter ENABLE_RANDOM = 0; + + `define TIMEOUT 1500000 + `include "tb_base.v" + + localparam NUM_OF_PORTS = SAMPLES_PER_CHANNEL * NUM_OF_CHANNELS; + + reg fifo_rd_en = 1'b1; + wire [NUM_OF_PORTS*8-1:0] fifo_rd_data; + reg [NUM_OF_PORTS*8-1:0] expected_fifo_rd_data = 'h00; + wire fifo_rd_valid; + + reg s_axis_valid = 1'b1; + wire s_axis_ready; + reg [NUM_OF_PORTS*8-1:0] s_axis_data = 'h00; + + reg [NUM_OF_CHANNELS-1:0] enable = 'h1; + reg [NUM_OF_CHANNELS-1:0] next_enable = 'h1; + + integer counter; + + always @(*) begin + if (counter == 15) do_trigger_reset(); + end + + always @(posedge clk) begin + if (trigger_reset == 1'b1) begin + if (enable != {NUM_OF_CHANNELS{1'b1}}) begin + enable <= enable + 1'b1; + end else begin + if (failed == 1'b0) + $display("SUCCESS"); + else + $display("FAILED"); + $finish; + end + end + end + + always @(posedge clk) begin + if (reset == 1'b1) begin + counter <= 'h00; + end else if (s_axis_ready == 1'b1 && s_axis_valid == 1'b1) begin + counter <= counter + 1; + end + end + + integer i; + + always @(posedge clk) begin + for (i = 0; i < NUM_OF_PORTS; i = i + 1) begin + if (reset == 1'b0 && fifo_rd_valid == 1'b1 && enable[i/SAMPLES_PER_CHANNEL] == 1'b1 && + fifo_rd_data[i*8+:8] !== expected_fifo_rd_data[i*8+:8]) begin + failed <= 1'b1; + $display("Failed for enable mask: %x. Expected data %x, got %x", + enable, expected_fifo_rd_data, fifo_rd_data); + i = NUM_OF_PORTS; + end + end + end + + integer j; + integer h; + + always @(posedge clk) begin + if (reset == 1'b1) begin + j = 0; + for (h = 0; h < SAMPLES_PER_CHANNEL; h = h + 1) begin + for (i = 0; i < NUM_OF_CHANNELS; i = i + 1) begin + if (enable[i] == 1'b1) begin + expected_fifo_rd_data[(i*SAMPLES_PER_CHANNEL+h)*8+:8] <= j; + j = j + 1; + end else begin + expected_fifo_rd_data[(i*SAMPLES_PER_CHANNEL+h)*8+:8] <= 'hxx; + end + end + end + end else if (fifo_rd_valid == 1'b1) begin + for (h = 0; h < SAMPLES_PER_CHANNEL; h = h + 1) begin + for (i = 0; i < NUM_OF_CHANNELS; i = i + 1) begin + if (enable[i] == 1'b1) begin + expected_fifo_rd_data[(i*SAMPLES_PER_CHANNEL+h)*8+:8] <= j; + j = j + 1; + end + end + end + end + end + + always @(posedge clk) begin + if (reset == 1'b1) begin + for (i = 0; i < NUM_OF_PORTS; i = i + 1) begin + s_axis_data[i*8+:8] <= i; + end + end else if (s_axis_ready == 1'b1 && s_axis_valid == 1'b1) begin + for (i = 0; i < NUM_OF_PORTS; i = i + 1) begin + s_axis_data[i*8+:8] <= s_axis_data[i*8+:8] + NUM_OF_PORTS; + end + end + end + + always @(posedge clk) begin + fifo_rd_en <= ENABLE_RANDOM ? ($random & 1) : 1'b1; + if (s_axis_valid == 1'b0 || s_axis_ready == 1'b1) begin + s_axis_valid <= ENABLE_RANDOM ? ($random % 20) : 1'b1; + end + end + + util_upack2_impl #( + .NUM_OF_CHANNELS(NUM_OF_CHANNELS), + .SAMPLES_PER_CHANNEL(SAMPLES_PER_CHANNEL), + .SAMPLE_DATA_WIDTH(8) + ) i_unpack ( + .clk(clk), + .reset(reset), + + .enable(enable), + + .fifo_rd_en({NUM_OF_CHANNELS{fifo_rd_en}}), + .fifo_rd_data(fifo_rd_data), + .fifo_rd_valid(fifo_rd_valid), + + .s_axis_valid(s_axis_valid), + .s_axis_ready(s_axis_ready), + .s_axis_data(s_axis_valid ? s_axis_data : {NUM_OF_PORTS{8'hx}}) + ); + +endmodule diff --git a/library/util_pack/util_upack2/Makefile b/library/util_pack/util_upack2/Makefile new file mode 100644 index 000000000..108e317a5 --- /dev/null +++ b/library/util_pack/util_upack2/Makefile @@ -0,0 +1,20 @@ +#################################################################################### +## Copyright 2018(c) Analog Devices, Inc. +## Auto-generated, do not modify! +#################################################################################### + +LIBRARY_NAME := util_upack2 + +GENERIC_DEPS += ../../common/ad_perfect_shuffle.v +GENERIC_DEPS += ../util_pack_common/pack_ctrl.v +GENERIC_DEPS += ../util_pack_common/pack_interconnect.v +GENERIC_DEPS += ../util_pack_common/pack_network.v +GENERIC_DEPS += ../util_pack_common/pack_shell.v +GENERIC_DEPS += util_upack2_impl.v + +XILINX_DEPS += util_upack2.v +XILINX_DEPS += util_upack2_ip.tcl + +ALTERA_DEPS += util_upack2_hw.tcl + +include ../../scripts/library.mk diff --git a/library/util_pack/util_upack2/util_upack2.v b/library/util_pack/util_upack2/util_upack2.v new file mode 100644 index 000000000..66c1e4569 --- /dev/null +++ b/library/util_pack/util_upack2/util_upack2.v @@ -0,0 +1,149 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module util_upack2 #( + parameter NUM_OF_CHANNELS = 4, + parameter SAMPLES_PER_CHANNEL = 1, + parameter SAMPLE_DATA_WIDTH = 16 +) ( + input clk, + input reset, + + input enable_0, + input enable_1, + input enable_2, + input enable_3, + input enable_4, + input enable_5, + input enable_6, + input enable_7, + input enable_8, + input enable_9, + input enable_10, + input enable_11, + input enable_12, + input enable_13, + input enable_14, + input enable_15, + + input fifo_rd_en, + output fifo_rd_valid, + output fifo_rd_underflow, + + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_0, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_1, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_2, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_3, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_4, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_5, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_6, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_7, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_8, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_9, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_10, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_11, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_12, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_13, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_14, + output [SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data_15, + + input s_axis_valid, + output s_axis_ready, + input [2**$clog2(NUM_OF_CHANNELS)*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] s_axis_data +); + +localparam CHANNEL_DATA_WIDTH = SAMPLE_DATA_WIDTH * SAMPLES_PER_CHANNEL; +/* + * Round up to the next power of two and zero out the additional channels + * internally. + */ +localparam REAL_NUM_OF_CHANNELS = NUM_OF_CHANNELS > 8 ? 16 : + NUM_OF_CHANNELS > 4 ? 8 : + NUM_OF_CHANNELS > 2 ? 4 : + NUM_OF_CHANNELS > 1 ? 2 : 1; + +/* FIXME: Find out how to do this in the IP-XACT */ + +wire [15:0] enable_s; +wire [CHANNEL_DATA_WIDTH*REAL_NUM_OF_CHANNELS-1:0] fifo_rd_data; +wire [CHANNEL_DATA_WIDTH*16-1:0] fifo_rd_data_s; + +util_upack2_impl #( + .NUM_OF_CHANNELS(REAL_NUM_OF_CHANNELS), + .SAMPLE_DATA_WIDTH(SAMPLE_DATA_WIDTH), + .SAMPLES_PER_CHANNEL(SAMPLES_PER_CHANNEL) +) i_upack ( + .clk (clk), + .reset (reset), + + .enable (enable_s[REAL_NUM_OF_CHANNELS-1:0]), + + .fifo_rd_en ({REAL_NUM_OF_CHANNELS{fifo_rd_en}}), + .fifo_rd_valid (fifo_rd_valid), + .fifo_rd_underflow (fifo_rd_underflow), + .fifo_rd_data (fifo_rd_data), + + .s_axis_valid (s_axis_valid), + .s_axis_ready (s_axis_ready), + .s_axis_data (s_axis_data) +); + +assign enable_s = { + enable_15,enable_14,enable_13,enable_12,enable_11,enable_10,enable_9,enable_8, + enable_7,enable_6,enable_5,enable_4,enable_3,enable_2,enable_1,enable_0 +}; + +assign fifo_rd_data_s = {{(16-NUM_OF_CHANNELS)*CHANNEL_DATA_WIDTH{1'b0}},fifo_rd_data}; + +assign fifo_rd_data_0 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*0+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_1 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*1+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_2 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*2+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_3 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*3+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_4 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*4+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_5 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*5+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_6 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*6+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_7 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*7+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_8 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*8+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_9 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*9+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_10 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*10+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_11 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*11+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_12 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*12+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_13 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*13+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_14 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*14+:CHANNEL_DATA_WIDTH]; +assign fifo_rd_data_15 = fifo_rd_data_s[CHANNEL_DATA_WIDTH*15+:CHANNEL_DATA_WIDTH]; + +endmodule diff --git a/library/util_pack/util_upack2/util_upack2_hw.tcl b/library/util_pack/util_upack2/util_upack2_hw.tcl new file mode 100644 index 000000000..cd0fadb1f --- /dev/null +++ b/library/util_pack/util_upack2/util_upack2_hw.tcl @@ -0,0 +1,109 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +# +# Each core or library found in this collection may have its own licensing terms. +# The user should keep this in in mind while exploring these cores. +# +# Redistribution and use in source and binary forms, +# with or without modification of this file, are permitted under the terms of either +# (at the option of the user): +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory, or at: +# https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +# +# OR +# +# 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +# https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +# +# *************************************************************************** +# *************************************************************************** + +package require qsys +source ../../scripts/adi_env.tcl +source ../../scripts/adi_ip_alt.tcl + +ad_ip_create util_upack2 {Channel Unpack Utility v2} util_upack_elab +ad_ip_files util_upack2_impl [list \ + $ad_hdl_dir/library/common/ad_perfect_shuffle.v \ + ../util_pack_common/pack_ctrl.v \ + ../util_pack_common/pack_interconnect.v \ + ../util_pack_common/pack_network.v \ + ../util_pack_common/pack_shell.v \ + util_upack2_impl.v ] + +# parameters + +ad_ip_parameter NUM_OF_CHANNELS INTEGER 4 true [list \ + DISPLAY_NAME "Number of Channels" +] + +ad_ip_parameter SAMPLES_PER_CHANNEL INTEGER 1 true [list \ + DISPLAY_NAME "Samples per Channel" +] + +ad_ip_parameter SAMPLE_DATA_WIDTH INTEGER 16 true [list \ + DISPLAY_NAME "Sample Data Width" +] + +ad_ip_parameter INTERFACE_TYPE INTEGER 0 false [list \ + DISPLAY_NAME "Interface Type" \ + ALLOWED_RANGES {"0:AXIS" "1:FIFO"} \ +] + + +# defaults + +proc util_upack_elab {} { + set num_channels [get_parameter_value NUM_OF_CHANNELS] + set samples_per_channel [get_parameter_value SAMPLES_PER_CHANNEL] + set sample_data_width [get_parameter_value SAMPLE_DATA_WIDTH] + set interface_type [get_parameter_value INTERFACE_TYPE] + + set channel_data_width [expr $sample_data_width * $samples_per_channel] + set total_data_width [expr $num_channels * $channel_data_width] + + add_interface clk clock end + add_interface_port clk clk clk Input 1 + add_interface reset reset end + add_interface_port reset reset reset Input 1 + set_interface_property reset associatedClock clk + + # This is a temporary hack and should be removed once all projects have been + # updated to use the AXI streaming interface to connect the the upack + if {$interface_type == 0} { + ad_alt_intf signal s_axis_valid input 1 valid + ad_alt_intf signal s_axis_ready output 1 ready + ad_alt_intf signal s_axis_data input $total_data_width data + } else { + ad_alt_intf signal packed_fifo_rd_en output 1 valid + set_port_property packed_fifo_rd_en fragment_list "s_axis_ready" + ad_alt_intf signal packed_fifo_rd_data input $total_data_width data + set_port_property packed_fifo_rd_data fragment_list \ + [format "s_axis_data(%d:0)" [expr $total_data_width - 1]] + ad_alt_intf signal s_axis_valid input 1 valid + set_port_property s_axis_valid TERMINATION TRUE + set_port_property s_axis_valid TERMINATION_VALUE 1 + } + + ad_alt_intf signal fifo_rd_underflow output 1 unf + + for {set n 0} {$n < $num_channels} {incr n} { + add_interface dac_ch_${n} conduit end + add_interface_port dac_ch_${n} enable_${n} enable Input 1 + set_port_property enable_${n} fragment_list "enable(${n}:${n})" + + add_interface_port dac_ch_${n} fifo_rd_en_${n} valid Input 1 + set_port_property fifo_rd_en_${n} fragment_list "fifo_rd_en(${n})" + add_interface_port dac_ch_${n} fifo_rd_valid_${n} data_valid Output 1 + set_port_property fifo_rd_valid_${n} fragment_list "fifo_rd_valid(0)" + add_interface_port dac_ch_${n} fifo_rd_data_${n} data Output $channel_data_width + set_port_property fifo_rd_data_${n} fragment_list [format "fifo_rd_data(%d:%d)" \ + [expr ($n+1) * $channel_data_width - 1] [expr $n * $channel_data_width]] + set_interface_property dac_ch_${n} associatedClock clk + set_interface_property dac_ch_${n} associatedReset "" + } +} + diff --git a/library/util_pack/util_upack2/util_upack2_impl.v b/library/util_pack/util_upack2/util_upack2_impl.v new file mode 100644 index 000000000..6ab584e4c --- /dev/null +++ b/library/util_pack/util_upack2/util_upack2_impl.v @@ -0,0 +1,146 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module util_upack2_impl #( + parameter NUM_OF_CHANNELS = 4, + parameter SAMPLES_PER_CHANNEL = 1, + parameter SAMPLE_DATA_WIDTH = 16 +) ( + input clk, + input reset, + + input [NUM_OF_CHANNELS-1:0] enable, + + input [NUM_OF_CHANNELS-1:0] fifo_rd_en, + output reg fifo_rd_valid, + output reg fifo_rd_underflow, + output reg [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] fifo_rd_data, + + input s_axis_valid, + output s_axis_ready, + input [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] s_axis_data +); + + /* + * Final output data of the routing network that will be written to + * `fifo_rd_data` after being deinterleaved. + */ + wire [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] out_data; + + /* + * Deinterleaved version of `out_data` + */ + wire [NUM_OF_CHANNELS*SAMPLE_DATA_WIDTH*SAMPLES_PER_CHANNEL-1:0] deinterleaved_data; + + /* + * Internal read signal. + */ + wire data_rd_en; + + /* + * Control signals from/to the pack shell. + */ + wire ce; + wire ready; + wire reset_data; + + /* + * Only the first signal of fifo_rd_en is used. All others are ignored. The + * only reason why fifo_rd_en has multiple entries is to keep the interface + * somewhat backwards compatible to the previous upack. + */ + assign data_rd_en = fifo_rd_en[0]; + + assign ce = s_axis_valid & data_rd_en; + assign s_axis_ready = ready & ce; + + pack_shell #( + .NUM_OF_CHANNELS (NUM_OF_CHANNELS), + .SAMPLES_PER_CHANNEL (SAMPLES_PER_CHANNEL), + .SAMPLE_DATA_WIDTH (SAMPLE_DATA_WIDTH), + .PACK (0) + ) i_pack_shell ( + .clk (clk), + .reset (reset), + + .reset_data (reset_data), + + .enable (enable), + .ce (ce), + .ready (ready), + .in_data (s_axis_data), + .out_data (out_data), + + .out_valid (), + .out_sync () + ); + + /* + * Data at the output of the routing network is interleaved. The upack + * core is supposed to produce deinterleaved data. This just rearrange the + * bits in the data vector and does not consume any FPGA resources. + */ + ad_perfect_shuffle #( + .NUM_GROUPS (SAMPLES_PER_CHANNEL), + .WORDS_PER_GROUP (NUM_OF_CHANNELS), + .WORD_WIDTH (SAMPLE_DATA_WIDTH) + ) i_deinterleave ( + .data_in (out_data), + .data_out (deinterleaved_data) + ); + + always @(posedge clk) begin + /* In case of an underflow the output vector should be zeroed */ + if (reset_data == 1'b1 || + (data_rd_en == 1'b1 && s_axis_valid == 1'b0)) begin + fifo_rd_data <= 'h00; + end else if (data_rd_en == 1'b1) begin + fifo_rd_data <= deinterleaved_data; + end + end + + always @(posedge clk) begin + if (data_rd_en == 1'b1) begin + fifo_rd_valid <= s_axis_valid & ~reset_data; + fifo_rd_underflow <= ~(s_axis_valid & ~reset_data); + end else begin + fifo_rd_valid <= 1'b0; + fifo_rd_underflow <= 1'b0; + end + end + +endmodule diff --git a/library/util_pack/util_upack2/util_upack2_ip.tcl b/library/util_pack/util_upack2/util_upack2_ip.tcl new file mode 100644 index 000000000..5f0eea610 --- /dev/null +++ b/library/util_pack/util_upack2/util_upack2_ip.tcl @@ -0,0 +1,68 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +# +# Each core or library found in this collection may have its own licensing terms. +# The user should keep this in in mind while exploring these cores. +# +# Redistribution and use in source and binary forms, +# with or without modification of this file, are permitted under the terms of either +# (at the option of the user): +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory, or at: +# https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +# +# OR +# +# 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +# https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +# +# *************************************************************************** +# *************************************************************************** + +source ../../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create util_upack2 +adi_ip_files util_upack2 [list \ + "../../common/ad_perfect_shuffle.v" \ + "../util_pack_common/pack_ctrl.v" \ + "../util_pack_common/pack_interconnect.v" \ + "../util_pack_common/pack_network.v" \ + "../util_pack_common/pack_shell.v" \ + "util_upack2_impl.v" \ + "util_upack2.v" ] + +adi_ip_properties_lite util_upack2 + +adi_add_bus "s_axis" "slave" \ + "xilinx.com:interface:axis_rtl:1.0" \ + "xilinx.com:interface:axis:1.0" \ + [list {"s_axis_ready" "TREADY"} \ + {"s_axis_valid" "TVALID"} \ + {"s_axis_data" "TDATA"} \ + ] +adi_add_bus_clock "clk" "s_axis" "reset" + +set cc [ipx::current_core] + +for {set i 1} {$i < 16} {incr i} { + set_property enablement_dependency "spirit:decode(id('MODELPARAM_VALUE.NUM_OF_CHANNELS')) > $i" \ + [ipx::get_ports *_$i -of_objects $cc] +} + +foreach {k v} { \ + "NUM_OF_CHANNELS" "Number of Channels" \ + "SAMPLES_PER_CHANNEL" "Samples per Channel" \ + "SAMPLE_DATA_WIDTH" "Sample Width" \ + } { \ + set p [ipgui::get_guiparamspec -name $k -component $cc] +# ipgui::move_param -component $cc -order $i $p -parent $ + set_property -dict [list \ + DISPLAY_NAME $v \ + ] $p + incr i +} + +ipx::save_core [ipx::current_core]