1// 2// Copyright 2020 Ettus Research, a National Instruments Brand 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: rfnoc_siggen_core 7// 8// Description: 9// 10// This module contains the registers and core logic for a single RFNoC 11// Signal Generator module instance. 12// 13 14 15module rfnoc_siggen_core ( 16 input wire clk, 17 input wire rst, 18 19 // CtrlPort Slave 20 input wire s_ctrlport_req_wr, 21 input wire s_ctrlport_req_rd, 22 input wire [19:0] s_ctrlport_req_addr, 23 input wire [31:0] s_ctrlport_req_data, 24 output reg s_ctrlport_resp_ack, 25 output reg [31:0] s_ctrlport_resp_data, 26 27 // Output data stream 28 output wire [31:0] m_tdata, 29 output wire m_tlast, 30 output wire m_tvalid, 31 input wire m_tready, 32 output wire [15:0] m_tlength 33); 34 35 `include "rfnoc_block_siggen_regs.vh" 36 37 38 //--------------------------------------------------------------------------- 39 // Registers 40 //--------------------------------------------------------------------------- 41 42 // Define maximum fixed point value for the gain, equal to about 0.9999 43 localparam MAX_GAIN = {REG_GAIN_LEN-1{1'b1}}; 44 45 reg [ REG_ENABLE_LEN-1:0] reg_enable = 0; 46 reg [ REG_SPP_LEN-1:0] reg_spp = 16; 47 reg [ REG_WAVEFORM_LEN-1:0] reg_waveform = WAVE_CONST; 48 reg [ REG_GAIN_LEN-1:0] reg_gain = MAX_GAIN; 49 reg [ REG_CONSTANT_LEN-1:0] reg_constant = 0; 50 reg [REG_PHASE_INC_LEN-1:0] reg_phase_inc; 51 reg [REG_CARTESIAN_LEN-1:0] reg_cartesian; 52 53 reg reg_phase_inc_stb; 54 reg reg_cartesian_stb; 55 56 always @(posedge clk) begin 57 if (rst) begin 58 reg_enable <= 0; 59 reg_spp <= 16; 60 reg_waveform <= WAVE_CONST; 61 reg_gain <= MAX_GAIN; 62 reg_constant <= 0; 63 reg_phase_inc <= 'bX; 64 reg_cartesian <= 'bX; 65 s_ctrlport_resp_ack <= 1'b0; 66 s_ctrlport_resp_data <= 'bX; 67 reg_phase_inc_stb <= 1'b0; 68 reg_cartesian_stb <= 1'b0; 69 end else begin 70 71 // Default assignments 72 s_ctrlport_resp_ack <= 1'b0; 73 s_ctrlport_resp_data <= 0; 74 reg_phase_inc_stb <= 1'b0; 75 reg_cartesian_stb <= 1'b0; 76 77 // Handle register writes 78 if (s_ctrlport_req_wr) begin 79 s_ctrlport_resp_ack <= 1; 80 case (s_ctrlport_req_addr) 81 REG_ENABLE : reg_enable <= s_ctrlport_req_data[REG_ENABLE_LEN-1:0]; 82 REG_SPP : reg_spp <= s_ctrlport_req_data[REG_SPP_LEN-1:0]; 83 REG_WAVEFORM : reg_waveform <= s_ctrlport_req_data[REG_WAVEFORM_LEN-1:0]; 84 REG_GAIN : reg_gain <= s_ctrlport_req_data[REG_GAIN_LEN-1:0]; 85 REG_CONSTANT : reg_constant <= s_ctrlport_req_data[REG_CONSTANT_LEN-1:0]; 86 REG_PHASE_INC : begin 87 reg_phase_inc <= s_ctrlport_req_data[REG_PHASE_INC_LEN-1:0]; 88 reg_phase_inc_stb <= 1'b1; 89 end 90 REG_CARTESIAN : begin 91 reg_cartesian <= s_ctrlport_req_data[REG_CARTESIAN_LEN-1:0]; 92 reg_cartesian_stb <= 1'b1; 93 end 94 endcase 95 end 96 97 // Handle register reads 98 if (s_ctrlport_req_rd) begin 99 s_ctrlport_resp_ack <= 1; 100 case (s_ctrlport_req_addr) 101 REG_ENABLE : s_ctrlport_resp_data[REG_ENABLE_LEN-1:0] <= reg_enable; 102 REG_SPP : s_ctrlport_resp_data[REG_SPP_LEN-1:0] <= reg_spp; 103 REG_WAVEFORM : s_ctrlport_resp_data[REG_WAVEFORM_LEN-1:0] <= reg_waveform; 104 REG_GAIN : s_ctrlport_resp_data[REG_GAIN_LEN-1:0] <= reg_gain; 105 REG_CONSTANT : s_ctrlport_resp_data[REG_CONSTANT_LEN-1:0] <= reg_constant; 106 REG_PHASE_INC : s_ctrlport_resp_data[REG_PHASE_INC_LEN-1:0] <= reg_phase_inc; 107 REG_CARTESIAN : s_ctrlport_resp_data[REG_CARTESIAN_LEN-1:0] <= reg_cartesian; 108 endcase 109 end 110 end 111 end 112 113 114 //--------------------------------------------------------------------------- 115 // Waveform Generation 116 //--------------------------------------------------------------------------- 117 118 wire [31:0] axis_sine_tdata; 119 wire axis_sine_tvalid; 120 wire axis_sine_tready; 121 wire [31:0] axis_const_tdata; 122 wire axis_const_tvalid; 123 wire axis_const_tready; 124 wire [31:0] axis_noise_tdata; 125 wire axis_noise_tvalid; 126 wire axis_noise_tready; 127 128 //------------------------------------ 129 // Sine waveform generation 130 //------------------------------------ 131 132 // Convert the registers writes to settings bus transactions. Only one 133 // register strobe will assert at a time. 134 wire sine_set_stb = reg_cartesian_stb | reg_phase_inc_stb; 135 wire [31:0] sine_set_data = reg_cartesian_stb ? reg_cartesian : reg_phase_inc; 136 wire [ 7:0] sine_set_addr = reg_cartesian_stb; 137 138 sine_tone #( 139 .WIDTH (32), 140 .SR_PHASE_INC_ADDR (0), 141 .SR_CARTESIAN_ADDR (1) 142 ) sine_tone_i ( 143 .clk (clk), 144 .reset (rst), 145 .clear (1'b0), 146 .enable (1'b1), 147 .set_stb (sine_set_stb), 148 .set_data (sine_set_data), 149 .set_addr (sine_set_addr), 150 .o_tdata (axis_sine_tdata), 151 .o_tlast (), 152 .o_tvalid (axis_sine_tvalid), 153 .o_tready (axis_sine_tready) 154 ); 155 156 //------------------------------------ 157 // Constant waveform generation 158 //------------------------------------ 159 160 assign axis_const_tdata = reg_constant; 161 assign axis_const_tvalid = 1'b1; 162 163 //------------------------------------ 164 // Noise waveform generation 165 //------------------------------------ 166 167 assign axis_noise_tvalid = 1'b1; 168 169 // Random number generator 170 rng rng_i ( 171 .clk (clk), 172 .rst (rst), 173 .out (axis_noise_tdata) 174 ); 175 176 177 //--------------------------------------------------------------------------- 178 // Waveform Selection 179 //--------------------------------------------------------------------------- 180 181 wire [31:0] axis_mux_tdata; 182 wire axis_mux_tvalid; 183 wire axis_mux_tready; 184 185 axi_mux_select #( 186 .WIDTH (32), 187 .SIZE (3), 188 .SWITCH_ON_LAST (0) 189 ) axi_mux_select_i ( 190 .clk (clk), 191 .reset (rst), 192 .clear (1'b0), 193 .select (reg_waveform), 194 .i_tdata ({axis_noise_tdata, axis_sine_tdata, axis_const_tdata}), 195 .i_tlast ({3'd0}), // Length controlled by SPP register 196 .i_tvalid ({axis_noise_tvalid, axis_sine_tvalid, axis_const_tvalid}), 197 .i_tready ({axis_noise_tready, axis_sine_tready, axis_const_tready}), 198 .o_tdata (axis_mux_tdata), 199 .o_tlast (), 200 .o_tvalid (axis_mux_tvalid), 201 .o_tready (axis_mux_tready) 202 ); 203 204 205 //--------------------------------------------------------------------------- 206 // Gain 207 //--------------------------------------------------------------------------- 208 209 wire [63:0] axis_gain_tdata; 210 wire axis_gain_tvalid; 211 wire axis_gain_tready; 212 wire [31:0] axis_round_tdata; 213 wire axis_round_tvalid; 214 wire axis_round_tready; 215 216 mult_rc #( 217 .WIDTH_REAL (16), 218 .WIDTH_CPLX (16), 219 .WIDTH_P (32), 220 .DROP_TOP_P (5), 221 .LATENCY (4) 222 ) mult_rc_i ( 223 .clk (clk), 224 .reset (rst), 225 .real_tdata (reg_gain), 226 .real_tlast (1'b0), 227 .real_tvalid (1'b1), 228 .real_tready (), 229 .cplx_tdata (axis_mux_tdata), 230 .cplx_tlast (1'b0), 231 .cplx_tvalid (axis_mux_tvalid), 232 .cplx_tready (axis_mux_tready), 233 .p_tdata (axis_gain_tdata), 234 .p_tlast (), 235 .p_tvalid (axis_gain_tvalid), 236 .p_tready (axis_gain_tready) 237 ); 238 239 axi_round_and_clip_complex #( 240 .WIDTH_IN (32), 241 .WIDTH_OUT (16), 242 .CLIP_BITS (1) 243 ) axi_round_and_clip_complex_i ( 244 .clk (clk), 245 .reset (rst), 246 .i_tdata (axis_gain_tdata), 247 .i_tlast (1'b0), 248 .i_tvalid (axis_gain_tvalid), 249 .i_tready (axis_gain_tready), 250 .o_tdata (axis_round_tdata), 251 .o_tlast (), 252 .o_tvalid (axis_round_tvalid), 253 .o_tready (axis_round_tready) 254 ); 255 256 257 //--------------------------------------------------------------------------- 258 // Packet Length Control 259 //--------------------------------------------------------------------------- 260 261 wire [REG_SPP_LEN-1:0] m_tlength_samples; 262 263 assign m_tlength = { m_tlength_samples, 2'b0 }; // 4 bytes per sample 264 265 axis_packetize #( 266 .DATA_W (32), 267 .SIZE_W (REG_SPP_LEN), 268 .FLUSH (1) 269 ) axis_packetize_i ( 270 .clk (clk), 271 .rst (rst), 272 .gate (~reg_enable), 273 .size (reg_spp), 274 .i_tdata (axis_round_tdata), 275 .i_tvalid (axis_round_tvalid), 276 .i_tready (axis_round_tready), 277 .o_tdata (m_tdata), 278 .o_tlast (m_tlast), 279 .o_tvalid (m_tvalid), 280 .o_tready (m_tready), 281 .o_tuser (m_tlength_samples) 282 ); 283 284endmodule 285