// // Copyright 2022 Ettus Research, A National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // // Module: sim_radio_gen // // Description: Generate radio data for simulation purposes. The strobe pattern // is random, which is not like a normal radio but covers every possibility. // The data pattern is an incrementing sequence of samples, with each channel // starting at a different value to differentiate them. Strobe and time are // common between channels. // module sim_radio_gen #( parameter int NSPC = 1, // Number of samples per clock cycle parameter int SAMP_W = 32, // Length of each radio sample parameter int NUM_CHANNELS = 1, // Number of radio RX ports parameter int STB_PROB = 50, // Probability of STB being asserted on each clock cycle parameter int INCREMENT = 2, // Amount by which to increment parameter int PPS_PERIOD = 50 // Period of the PPS output ) ( input bit radio_clk, input bit radio_rst, output bit [NUM_CHANNELS*SAMP_W*NSPC-1:0] radio_rx_data, output bit [ NUM_CHANNELS-1:0] radio_rx_stb, output bit [ 63:0] radio_time, output bit radio_pps ); localparam int RADIO_W = SAMP_W*NSPC; typedef bit [RADIO_W-1:0] radio_t; // Radio output word typedef bit [SAMP_W-1:0] sample_t; // Single sample initial assert (PPS_PERIOD % INCREMENT == 0) else $fatal(1, "PPS_PERIOD must be a multiple of INCREMENT"); // Generate an initial value all radio channels function radio_t [NUM_CHANNELS-1:0] radio_init(); radio_t [NUM_CHANNELS-1:0] ret_val; for (int n = 0; n < NUM_CHANNELS; n++) begin sample_t sample; // Calculate the value of first sample in this radio channel sample = sample_t'((2.0 ** SAMP_W) / NUM_CHANNELS * n); // Calculate the value of subsequent samples in the channel for (int s = 0; s < NSPC; s++) begin ret_val[n][s*SAMP_W +: SAMP_W] = sample + s; end end return ret_val; endfunction : radio_init //--------------------------------------------------------------------------- // Radio Data Generation //--------------------------------------------------------------------------- radio_t [NUM_CHANNELS-1:0] data = radio_init(); assign radio_rx_data = data; always @(posedge radio_clk) begin : radio_data_count_reg if (radio_rst) begin data <= radio_init(); radio_rx_stb <= '0; end else begin radio_rx_stb <= '0; if ($urandom_range(99) < STB_PROB) begin for (int n = 0; n < NUM_CHANNELS; n++) begin for (int s = 0; s < NSPC; s++) begin data[n][s*SAMP_W +: SAMP_W] <= data[n][s*SAMP_W +: SAMP_W] + NSPC; end end radio_rx_stb <= '1; end end end : radio_data_count_reg //--------------------------------------------------------------------------- // Radio Time //--------------------------------------------------------------------------- always @(posedge radio_clk) begin if (radio_rst) begin radio_time <= 64'b0; radio_pps <= 1'b0; end else begin radio_pps <= 1'b0; if (radio_rx_stb[0]) begin radio_time <= radio_time + INCREMENT; if (radio_time % PPS_PERIOD == 0 && radio_time != 0) begin radio_pps <= 1'b1; end end end end endmodule : sim_radio_gen