fpga: rfnoc: Add Log-Power block
Original-commit: cf82b36388880237fe7b690c16dde46afc1a3da3
This commit is contained in:
committed by
Aaron Rossetto
parent
c3f45a92a0
commit
cbe5e99e17
@@ -0,0 +1,255 @@
|
||||
//
|
||||
// Copyright 2020 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rfnoc_block_logpwr
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// This block takes in signed 16-bit complex samples and computes an
|
||||
// estimate of 1024 * log2(i^2+q^2), and puts the result in the upper
|
||||
// 16-bits of each 32-bit output item. The log is estimated using a lookup
|
||||
// table and random noise is added to reduce quantization effects.
|
||||
//
|
||||
// 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).
|
||||
// NUM_PORTS : Number of Log-Power module instances to include.
|
||||
// RANDOM_MODE : Configures the random_mode for the logpwr block.
|
||||
// [0] = Enable random LSBs on each input
|
||||
// [1] = Enable random noise addition
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
|
||||
module rfnoc_block_logpwr #(
|
||||
parameter [9:0] THIS_PORTID = 10'd0,
|
||||
parameter CHDR_W = 64,
|
||||
parameter [5:0] MTU = 10,
|
||||
parameter NUM_PORTS = 1,
|
||||
parameter RANDOM_MODE = 2'b11
|
||||
) (
|
||||
// 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 [NUM_PORTS*CHDR_W-1:0] s_rfnoc_chdr_tdata,
|
||||
input wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tlast,
|
||||
input wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tvalid,
|
||||
output wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tready,
|
||||
// AXIS-CHDR Output Ports (to framework)
|
||||
output wire [NUM_PORTS*CHDR_W-1:0] m_rfnoc_chdr_tdata,
|
||||
output wire [ NUM_PORTS-1:0] m_rfnoc_chdr_tlast,
|
||||
output wire [ NUM_PORTS-1:0] m_rfnoc_chdr_tvalid,
|
||||
input wire [ NUM_PORTS-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
|
||||
);
|
||||
|
||||
`include "../../core/rfnoc_chdr_utils.vh"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Signal Declarations
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Payload Stream to User Logic: in
|
||||
wire [NUM_PORTS*32*1-1:0] m_in_payload_tdata;
|
||||
wire [NUM_PORTS-1:0] m_in_payload_tlast;
|
||||
wire [NUM_PORTS-1:0] m_in_payload_tvalid;
|
||||
wire [NUM_PORTS-1:0] m_in_payload_tready;
|
||||
// Context Stream to User Logic: in
|
||||
wire [NUM_PORTS*CHDR_W-1:0] m_in_context_tdata;
|
||||
wire [NUM_PORTS*4-1:0] m_in_context_tuser;
|
||||
wire [NUM_PORTS-1:0] m_in_context_tlast;
|
||||
wire [NUM_PORTS-1:0] m_in_context_tvalid;
|
||||
reg [NUM_PORTS-1:0] m_in_context_tready;
|
||||
// Payload Stream to User Logic: out
|
||||
wire [NUM_PORTS*16*1-1:0] s_out_payload_tdata;
|
||||
wire [NUM_PORTS-1:0] s_out_payload_tlast;
|
||||
wire [NUM_PORTS-1:0] s_out_payload_tvalid;
|
||||
wire [NUM_PORTS-1:0] s_out_payload_tready;
|
||||
// Context Stream to User Logic: out
|
||||
reg [NUM_PORTS*CHDR_W-1:0] s_out_context_tdata;
|
||||
reg [NUM_PORTS*4-1:0] s_out_context_tuser;
|
||||
reg [NUM_PORTS-1:0] s_out_context_tlast;
|
||||
reg [NUM_PORTS-1:0] s_out_context_tvalid;
|
||||
wire [NUM_PORTS-1:0] s_out_context_tready;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// NoC Shell
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
wire ce_rst;
|
||||
|
||||
noc_shell_logpwr #(
|
||||
.CHDR_W (CHDR_W),
|
||||
.THIS_PORTID (THIS_PORTID),
|
||||
.MTU (MTU),
|
||||
.NUM_PORTS (NUM_PORTS)
|
||||
) noc_shell_logpwr_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 (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_rst (),
|
||||
// Payload Stream to User Logic: in
|
||||
.m_in_payload_tdata (m_in_payload_tdata),
|
||||
.m_in_payload_tkeep (),
|
||||
.m_in_payload_tlast (m_in_payload_tlast),
|
||||
.m_in_payload_tvalid (m_in_payload_tvalid),
|
||||
.m_in_payload_tready (m_in_payload_tready),
|
||||
// Context Stream to User Logic: in
|
||||
.m_in_context_tdata (m_in_context_tdata),
|
||||
.m_in_context_tuser (m_in_context_tuser),
|
||||
.m_in_context_tlast (m_in_context_tlast),
|
||||
.m_in_context_tvalid (m_in_context_tvalid),
|
||||
.m_in_context_tready (m_in_context_tready),
|
||||
// Payload Stream from User Logic: out
|
||||
.s_out_payload_tdata (s_out_payload_tdata),
|
||||
.s_out_payload_tkeep ({NUM_PORTS{1'b1}}),
|
||||
.s_out_payload_tlast (s_out_payload_tlast),
|
||||
.s_out_payload_tvalid (s_out_payload_tvalid),
|
||||
.s_out_payload_tready (s_out_payload_tready),
|
||||
// Context Stream from User Logic: out
|
||||
.s_out_context_tdata (s_out_context_tdata),
|
||||
.s_out_context_tuser (s_out_context_tuser),
|
||||
.s_out_context_tlast (s_out_context_tlast),
|
||||
.s_out_context_tvalid (s_out_context_tvalid),
|
||||
.s_out_context_tready (s_out_context_tready)
|
||||
);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Context Handling
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Output packets have half the payload size of input packets, so we need to
|
||||
// update the header length field as it passes through.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
genvar port;
|
||||
|
||||
for (port = 0; port < NUM_PORTS; port = port+1) begin : gen_context_ports
|
||||
|
||||
always @(*) begin : update_packet_length
|
||||
reg [CHDR_W-1:0] old_tdata;
|
||||
reg [CHDR_W-1:0] new_tdata;
|
||||
|
||||
old_tdata = m_in_context_tdata[CHDR_W*port +: CHDR_W];
|
||||
|
||||
// Check if this context word contains the header
|
||||
if (m_in_context_tuser[4*port +: 4] == CONTEXT_FIELD_HDR ||
|
||||
m_in_context_tuser[4*port +: 4] == CONTEXT_FIELD_HDR_TS
|
||||
) begin : change_header
|
||||
// Update the lower 64-bits (the header word) with the new length
|
||||
reg [15:0] pyld_length;
|
||||
pyld_length = chdr_calc_payload_length(CHDR_W, old_tdata) / 2;
|
||||
new_tdata = old_tdata;
|
||||
new_tdata[63:0] = chdr_update_length(CHDR_W, old_tdata, pyld_length);
|
||||
end else begin : pass_through_header
|
||||
// Not a header word, so pass through unchanged
|
||||
new_tdata = old_tdata;
|
||||
end
|
||||
|
||||
s_out_context_tdata [CHDR_W*port +: CHDR_W] = new_tdata;
|
||||
s_out_context_tuser [ 4*port +: 4] = m_in_context_tuser [4*port +: 4];
|
||||
s_out_context_tlast [ 1*port +: 1] = m_in_context_tlast [1*port +: 1];
|
||||
s_out_context_tvalid [ 1*port +: 1] = m_in_context_tvalid [1*port +: 1];
|
||||
m_in_context_tready [ 1*port +: 1] = s_out_context_tready [1*port +: 1];
|
||||
end // update_packet_length
|
||||
|
||||
end // gen_context_ports
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Log-Power
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
for (port = 0; port < NUM_PORTS; port = port+1) begin : gen_logpwr_ports
|
||||
|
||||
wire [15:0] s_out_payload_tdata_temp;
|
||||
|
||||
axi_logpwr #(
|
||||
.RANDOM_MODE (RANDOM_MODE)
|
||||
) inst_axi_logpwr (
|
||||
.clk (ce_clk),
|
||||
.reset (ce_rst),
|
||||
.i_tdata (m_in_payload_tdata [port*32 +: 32]),
|
||||
.i_tlast (m_in_payload_tlast [port]),
|
||||
.i_tvalid (m_in_payload_tvalid [port]),
|
||||
.i_tready (m_in_payload_tready [port]),
|
||||
.o_tdata (s_out_payload_tdata_temp),
|
||||
.o_tlast (s_out_payload_tlast [port]),
|
||||
.o_tvalid (s_out_payload_tvalid [port]),
|
||||
.o_tready (s_out_payload_tready [port])
|
||||
);
|
||||
|
||||
// Convert the 16-bit unsigned result to a signed 16-bit result. This
|
||||
// makes the output an estimate of 1024 * log2(i^2+q^2) instead of the
|
||||
// 2048 * log2(i^2+q^2) returned by the block.
|
||||
assign s_out_payload_tdata[port*16 +: 16] = {
|
||||
1'b0, s_out_payload_tdata_temp[15:1]
|
||||
};
|
||||
|
||||
end // gen_logpwr_ports
|
||||
|
||||
endmodule // rfnoc_block_logpwr
|
||||
|
||||
|
||||
`default_nettype wire
|
||||
Reference in New Issue
Block a user