337 lines
13 KiB
Verilog
337 lines
13 KiB
Verilog
//
|
|
// Copyright 2020 Ettus Research, a National Instruments Brand
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
//
|
|
// Module: rfnoc_block_addsub
|
|
//
|
|
// Description:
|
|
//
|
|
// This block takes in two streams and adds and subtracts them, creating two
|
|
// output streams with the sum and difference of the input streams. It
|
|
// assumes the input and output packets are all the same length and use sc16
|
|
// samples.
|
|
//
|
|
// This block also demonstrates how to use Verilog, VHDL and/or
|
|
// high-level-synthesis (HLS) in a design. You can set the USE_IMPL parameter
|
|
// to control which implementation is used.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// THIS_PORTID : Control crossbar port to which this block is connected
|
|
// CHDR_W : AXIS-CHDR data bus width
|
|
// MTU : Maximum transmission unit (i.e., maximum packet size in CHDR
|
|
// words is 2**MTU).
|
|
// USE_IMPL : Indicates which implementation to use. This is a string that
|
|
// can be set to "Verilog", "VHDL", or "HLS".
|
|
//
|
|
`default_nettype none
|
|
|
|
|
|
module rfnoc_block_addsub #(
|
|
parameter [9:0] THIS_PORTID = 10'd0,
|
|
parameter CHDR_W = 64,
|
|
parameter [5:0] MTU = 10,
|
|
parameter USE_IMPL = "Verilog"
|
|
) (
|
|
// RFNoC Framework Clocks and Resets
|
|
input wire rfnoc_chdr_clk,
|
|
input wire rfnoc_ctrl_clk,
|
|
input wire ce_clk,
|
|
// RFNoC Backend Interface
|
|
input wire [ 511:0] rfnoc_core_config,
|
|
output wire [ 511:0] rfnoc_core_status,
|
|
// AXIS-CHDR Input Ports (from framework)
|
|
input wire [2*CHDR_W-1:0] s_rfnoc_chdr_tdata,
|
|
input wire [ 2-1:0] s_rfnoc_chdr_tlast,
|
|
input wire [ 2-1:0] s_rfnoc_chdr_tvalid,
|
|
output wire [ 2-1:0] s_rfnoc_chdr_tready,
|
|
// AXIS-CHDR Output Ports (to framework)
|
|
output wire [2*CHDR_W-1:0] m_rfnoc_chdr_tdata,
|
|
output wire [ 2-1:0] m_rfnoc_chdr_tlast,
|
|
output wire [ 2-1:0] m_rfnoc_chdr_tvalid,
|
|
input wire [ 2-1:0] m_rfnoc_chdr_tready,
|
|
// AXIS-Ctrl Input Port (from framework)
|
|
input wire [ 31:0] s_rfnoc_ctrl_tdata,
|
|
input wire s_rfnoc_ctrl_tlast,
|
|
input wire s_rfnoc_ctrl_tvalid,
|
|
output wire s_rfnoc_ctrl_tready,
|
|
// AXIS-Ctrl Output Port (to framework)
|
|
output wire [ 31:0] m_rfnoc_ctrl_tdata,
|
|
output wire m_rfnoc_ctrl_tlast,
|
|
output wire m_rfnoc_ctrl_tvalid,
|
|
input wire m_rfnoc_ctrl_tready
|
|
);
|
|
|
|
// This block currently only supports 64-bit CHDR
|
|
if (CHDR_W != 64) begin
|
|
CHDR_W_must_be_64_for_the_addsub_block();
|
|
end
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Signal Declarations
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Clocks and Resets
|
|
wire axis_data_clk;
|
|
wire axis_data_rst;
|
|
// Payload Stream to User Logic: in_a
|
|
wire [32*1-1:0] m_in_a_payload_tdata;
|
|
wire m_in_a_payload_tlast;
|
|
wire m_in_a_payload_tvalid;
|
|
wire m_in_a_payload_tready;
|
|
// Context Stream to User Logic: in_a
|
|
wire [CHDR_W-1:0] m_in_a_context_tdata;
|
|
wire [3:0] m_in_a_context_tuser;
|
|
wire m_in_a_context_tlast;
|
|
wire m_in_a_context_tvalid;
|
|
wire m_in_a_context_tready;
|
|
// Payload Stream to User Logic: in_b
|
|
wire [32*1-1:0] m_in_b_payload_tdata;
|
|
wire m_in_b_payload_tlast;
|
|
wire m_in_b_payload_tvalid;
|
|
wire m_in_b_payload_tready;
|
|
// Context Stream to User Logic: in_b
|
|
wire m_in_b_context_tready;
|
|
// Payload Stream from User Logic: add
|
|
wire [32*1-1:0] s_add_payload_tdata;
|
|
wire s_add_payload_tlast;
|
|
wire s_add_payload_tvalid;
|
|
wire s_add_payload_tready;
|
|
// Context Stream from User Logic: add
|
|
wire [CHDR_W-1:0] s_add_context_tdata;
|
|
wire [3:0] s_add_context_tuser;
|
|
wire s_add_context_tlast;
|
|
wire s_add_context_tvalid;
|
|
wire s_add_context_tready;
|
|
// Payload Stream from User Logic: sub
|
|
wire [32*1-1:0] s_sub_payload_tdata;
|
|
wire s_sub_payload_tlast;
|
|
wire s_sub_payload_tvalid;
|
|
wire s_sub_payload_tready;
|
|
// Context Stream from User Logic: sub
|
|
wire [CHDR_W-1:0] s_sub_context_tdata;
|
|
wire [3:0] s_sub_context_tuser;
|
|
wire s_sub_context_tlast;
|
|
wire s_sub_context_tvalid;
|
|
wire s_sub_context_tready;
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// NoC Shell
|
|
//---------------------------------------------------------------------------
|
|
|
|
noc_shell_addsub #(
|
|
.CHDR_W (CHDR_W),
|
|
.THIS_PORTID (THIS_PORTID),
|
|
.MTU (MTU),
|
|
.USE_IMPL (USE_IMPL)
|
|
) noc_shell_addsub_i (
|
|
//---------------------
|
|
// Framework Interface
|
|
//---------------------
|
|
|
|
// Clock Inputs
|
|
.rfnoc_chdr_clk (rfnoc_chdr_clk),
|
|
.rfnoc_ctrl_clk (rfnoc_ctrl_clk),
|
|
.ce_clk (ce_clk),
|
|
// Reset Outputs
|
|
.rfnoc_chdr_rst (),
|
|
.rfnoc_ctrl_rst (),
|
|
.ce_rst (),
|
|
// RFNoC Backend Interface
|
|
.rfnoc_core_config (rfnoc_core_config),
|
|
.rfnoc_core_status (rfnoc_core_status),
|
|
// CHDR Input Ports (from framework)
|
|
.s_rfnoc_chdr_tdata (s_rfnoc_chdr_tdata),
|
|
.s_rfnoc_chdr_tlast (s_rfnoc_chdr_tlast),
|
|
.s_rfnoc_chdr_tvalid (s_rfnoc_chdr_tvalid),
|
|
.s_rfnoc_chdr_tready (s_rfnoc_chdr_tready),
|
|
// CHDR Output Ports (to framework)
|
|
.m_rfnoc_chdr_tdata (m_rfnoc_chdr_tdata),
|
|
.m_rfnoc_chdr_tlast (m_rfnoc_chdr_tlast),
|
|
.m_rfnoc_chdr_tvalid (m_rfnoc_chdr_tvalid),
|
|
.m_rfnoc_chdr_tready (m_rfnoc_chdr_tready),
|
|
// AXIS-Ctrl Input Port (from framework)
|
|
.s_rfnoc_ctrl_tdata (s_rfnoc_ctrl_tdata),
|
|
.s_rfnoc_ctrl_tlast (s_rfnoc_ctrl_tlast),
|
|
.s_rfnoc_ctrl_tvalid (s_rfnoc_ctrl_tvalid),
|
|
.s_rfnoc_ctrl_tready (s_rfnoc_ctrl_tready),
|
|
// AXIS-Ctrl Output Port (to framework)
|
|
.m_rfnoc_ctrl_tdata (m_rfnoc_ctrl_tdata),
|
|
.m_rfnoc_ctrl_tlast (m_rfnoc_ctrl_tlast),
|
|
.m_rfnoc_ctrl_tvalid (m_rfnoc_ctrl_tvalid),
|
|
.m_rfnoc_ctrl_tready (m_rfnoc_ctrl_tready),
|
|
|
|
//---------------------
|
|
// Client Interface
|
|
//---------------------
|
|
|
|
// AXI-Stream Payload Context Clock and Reset
|
|
.axis_data_clk (axis_data_clk),
|
|
.axis_data_rst (axis_data_rst),
|
|
// Payload Stream to User Logic: in_a
|
|
.m_in_a_payload_tdata (m_in_a_payload_tdata),
|
|
.m_in_a_payload_tkeep (),
|
|
.m_in_a_payload_tlast (m_in_a_payload_tlast),
|
|
.m_in_a_payload_tvalid (m_in_a_payload_tvalid),
|
|
.m_in_a_payload_tready (m_in_a_payload_tready),
|
|
// Context Stream to User Logic: in_a
|
|
.m_in_a_context_tdata (m_in_a_context_tdata),
|
|
.m_in_a_context_tuser (m_in_a_context_tuser),
|
|
.m_in_a_context_tlast (m_in_a_context_tlast),
|
|
.m_in_a_context_tvalid (m_in_a_context_tvalid),
|
|
.m_in_a_context_tready (m_in_a_context_tready),
|
|
// Payload Stream to User Logic: in_b
|
|
.m_in_b_payload_tdata (m_in_b_payload_tdata),
|
|
.m_in_b_payload_tkeep (),
|
|
.m_in_b_payload_tlast (m_in_b_payload_tlast),
|
|
.m_in_b_payload_tvalid (m_in_b_payload_tvalid),
|
|
.m_in_b_payload_tready (m_in_b_payload_tready),
|
|
// Context Stream to User Logic: in_b
|
|
.m_in_b_context_tdata (),
|
|
.m_in_b_context_tuser (),
|
|
.m_in_b_context_tlast (),
|
|
.m_in_b_context_tvalid (),
|
|
.m_in_b_context_tready (m_in_b_context_tready),
|
|
// Payload Stream from User Logic: add
|
|
.s_add_payload_tdata (s_add_payload_tdata),
|
|
.s_add_payload_tkeep (1'b1),
|
|
.s_add_payload_tlast (s_add_payload_tlast),
|
|
.s_add_payload_tvalid (s_add_payload_tvalid),
|
|
.s_add_payload_tready (s_add_payload_tready),
|
|
// Context Stream from User Logic: add
|
|
.s_add_context_tdata (s_add_context_tdata),
|
|
.s_add_context_tuser (s_add_context_tuser),
|
|
.s_add_context_tlast (s_add_context_tlast),
|
|
.s_add_context_tvalid (s_add_context_tvalid),
|
|
.s_add_context_tready (s_add_context_tready),
|
|
// Payload Stream from User Logic: diff
|
|
.s_sub_payload_tdata (s_sub_payload_tdata),
|
|
.s_sub_payload_tkeep (1'b1),
|
|
.s_sub_payload_tlast (s_sub_payload_tlast),
|
|
.s_sub_payload_tvalid (s_sub_payload_tvalid),
|
|
.s_sub_payload_tready (s_sub_payload_tready),
|
|
// Context Stream from User Logic: diff
|
|
.s_sub_context_tdata (s_sub_context_tdata),
|
|
.s_sub_context_tuser (s_sub_context_tuser),
|
|
.s_sub_context_tlast (s_sub_context_tlast),
|
|
.s_sub_context_tvalid (s_sub_context_tvalid),
|
|
.s_sub_context_tready (s_sub_context_tready)
|
|
);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Context Handling
|
|
//---------------------------------------------------------------------------
|
|
|
|
// We use the A input to control the packet size and other attributes of the
|
|
// output packets. So we duplicate the A context and discard the B context.
|
|
assign m_in_b_context_tready = 1;
|
|
|
|
axis_split #(
|
|
.DATA_W (1 + 4 + CHDR_W), // TLAST + TUSER + TDATA
|
|
.NUM_PORTS (2)
|
|
) axis_split_i (
|
|
.clk (axis_data_clk),
|
|
.rst (axis_data_rst),
|
|
.s_axis_tdata ({m_in_a_context_tlast,
|
|
m_in_a_context_tuser,
|
|
m_in_a_context_tdata}),
|
|
.s_axis_tvalid (m_in_a_context_tvalid),
|
|
.s_axis_tready (m_in_a_context_tready),
|
|
.m_axis_tdata ({s_sub_context_tlast,
|
|
s_sub_context_tuser,
|
|
s_sub_context_tdata,
|
|
s_add_context_tlast,
|
|
s_add_context_tuser,
|
|
s_add_context_tdata}),
|
|
.m_axis_tvalid ({s_sub_context_tvalid, s_add_context_tvalid}),
|
|
.m_axis_tready ({s_sub_context_tready, s_add_context_tready})
|
|
);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Add/Subtract logic
|
|
//---------------------------------------------------------------------------
|
|
|
|
generate
|
|
if (USE_IMPL == "HLS") begin : gen_hls
|
|
// Use the module generated through Vivado High-Level Synthesis (see
|
|
// addsub_hls.cpp).
|
|
addsub_hls addsub_hls_i (
|
|
.ap_clk (axis_data_clk),
|
|
.ap_rst_n (~axis_data_rst),
|
|
.a_TDATA (m_in_a_payload_tdata),
|
|
.a_TVALID (m_in_a_payload_tvalid),
|
|
.a_TREADY (m_in_a_payload_tready),
|
|
.a_TLAST (m_in_a_payload_tlast),
|
|
.b_TDATA (m_in_b_payload_tdata),
|
|
.b_TVALID (m_in_b_payload_tvalid),
|
|
.b_TREADY (m_in_b_payload_tready),
|
|
.b_TLAST (m_in_b_payload_tlast),
|
|
.add_TDATA (s_add_payload_tdata),
|
|
.add_TVALID (s_add_payload_tvalid),
|
|
.add_TREADY (s_add_payload_tready),
|
|
.add_TLAST (s_add_payload_tlast),
|
|
.sub_TDATA (s_sub_payload_tdata),
|
|
.sub_TVALID (s_sub_payload_tvalid),
|
|
.sub_TREADY (s_sub_payload_tready),
|
|
.sub_TLAST (s_sub_payload_tlast)
|
|
);
|
|
end else if (USE_IMPL == "VHDL") begin : gen_vhdl
|
|
// Use the VHDL implementation
|
|
addsub_vhdl #(
|
|
.width_g (16)
|
|
) addsub_vhdl_i (
|
|
.clk_i (axis_data_clk),
|
|
.rst_i (axis_data_rst),
|
|
.i0_tdata (m_in_a_payload_tdata),
|
|
.i0_tlast (m_in_a_payload_tlast),
|
|
.i0_tvalid (m_in_a_payload_tvalid),
|
|
.i0_tready (m_in_a_payload_tready),
|
|
.i1_tdata (m_in_b_payload_tdata),
|
|
.i1_tlast (m_in_b_payload_tlast),
|
|
.i1_tvalid (m_in_b_payload_tvalid),
|
|
.i1_tready (m_in_b_payload_tready),
|
|
.sum_tdata (s_add_payload_tdata),
|
|
.sum_tlast (s_add_payload_tlast),
|
|
.sum_tvalid (s_add_payload_tvalid),
|
|
.sum_tready (s_add_payload_tready),
|
|
.diff_tdata (s_sub_payload_tdata),
|
|
.diff_tlast (s_sub_payload_tlast),
|
|
.diff_tvalid (s_sub_payload_tvalid),
|
|
.diff_tready (s_sub_payload_tready)
|
|
);
|
|
end else begin : gen_verilog
|
|
// Use Verilog implementation
|
|
addsub #(
|
|
.WIDTH (16)
|
|
) inst_addsub (
|
|
.clk (axis_data_clk),
|
|
.reset (axis_data_rst),
|
|
.i0_tdata (m_in_a_payload_tdata),
|
|
.i0_tlast (m_in_a_payload_tlast),
|
|
.i0_tvalid (m_in_a_payload_tvalid),
|
|
.i0_tready (m_in_a_payload_tready),
|
|
.i1_tdata (m_in_b_payload_tdata),
|
|
.i1_tlast (m_in_b_payload_tlast),
|
|
.i1_tvalid (m_in_b_payload_tvalid),
|
|
.i1_tready (m_in_b_payload_tready),
|
|
.sum_tdata (s_add_payload_tdata),
|
|
.sum_tlast (s_add_payload_tlast),
|
|
.sum_tvalid (s_add_payload_tvalid),
|
|
.sum_tready (s_add_payload_tready),
|
|
.diff_tdata (s_sub_payload_tdata),
|
|
.diff_tlast (s_sub_payload_tlast),
|
|
.diff_tvalid (s_sub_payload_tvalid),
|
|
.diff_tready (s_sub_payload_tready)
|
|
);
|
|
end
|
|
endgenerate
|
|
|
|
endmodule // rfnoc_block_addsub
|
|
|
|
`default_nettype wire
|