104 lines
3.4 KiB
Systemverilog
104 lines
3.4 KiB
Systemverilog
//
|
|
// 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 |