fpga: lib: Support time and data updates in sim_radio_gen

Original-commit: 684a9879d35269eb80ea79fc69993570c0147189
This commit is contained in:
Wade Fife
2022-12-19 08:57:18 -06:00
parent df4953a60d
commit fe014a5a53
@@ -5,100 +5,150 @@
//
// 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.
// 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.
//
// The initial rx_data and radio_time values can be set at run-time using the
// functions provided.
//
// Parameters:
//
// NSPC : Number of samples per clock cycle
// SAMP_W : Length of each radio sample
// NUM_CHANNELS : Number of radio RX ports
// STB_PROB : Probability of STB being asserted on each clock cycle
// INCREMENT : Amount by which to increment radio time each strobe
//
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
parameter int NSPC = 1,
parameter int SAMP_W = 32,
parameter int NUM_CHANNELS = 1,
parameter int STB_PROB = 50,
parameter int INCREMENT = NSPC,
localparam int RADIO_W = SAMP_W*NSPC
) (
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
input logic radio_clk,
input logic radio_rst,
output logic [NUM_CHANNELS-1:0][RADIO_W-1:0] radio_rx_data,
output logic [ NUM_CHANNELS-1:0] radio_rx_stb,
output logic [ 63:0] radio_time
);
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");
typedef bit [ SAMP_W-1:0] sample_t; // Single sample
typedef sample_t [ NSPC-1:0] radio_t; // Radio output word
typedef radio_t [NUM_CHANNELS-1:0] data_t; // Radio output for all channels
typedef bit [ 63:0] timestamp_t; // Radio timestamp
// Generate an initial value all radio channels
function radio_t [NUM_CHANNELS-1:0] radio_init();
radio_t [NUM_CHANNELS-1:0] ret_val;
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
for (int n = 0; n < NUM_CHANNELS; n++) begin
sample_t sample;
// Generate initial value for a single radio channel
function radio_t radio_init(
sample_t first_sample = '0
);
radio_t ret_val;
// 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
for (int samp_i = 0; samp_i < NSPC; samp_i++) begin
ret_val[samp_i] = first_sample + samp_i;
end
return ret_val;
endfunction : radio_init
// Generate an initial value all radio channels
function radio_t [NUM_CHANNELS-1:0] radio_init_all(
bit [SAMP_W-1:0] first_sample = '0
);
data_t ret_val;
sample_t sample;
// Calculate the value of subsequent samples in the channel
for (int ch_i = 0; ch_i < NUM_CHANNELS; ch_i++) begin
sample = sample_t'((2.0 ** SAMP_W) / NUM_CHANNELS * ch_i + first_sample);
ret_val[ch_i] = radio_init(first_sample);
end
return ret_val;
endfunction : radio_init_all
timestamp_t next_time = '0;
bit next_time_ld = 0;
radio_t [NUM_CHANNELS-1:0] next_data = '0;
bit [NUM_CHANNELS-1:0] next_data_ld = '0;
// Change the radio time on the next clock edge
function void set_time(timestamp_t timestamp);
next_time = timestamp;
next_time_ld = 1;
endfunction : set_time
// Change the radio data value for the given channel on the next clock edge
function void set_data(
int channel,
radio_t data);
next_data [channel] = data;
next_data_ld[channel] = 1;
endfunction : set_data
// Change the radio data value for all channels on the next clock edge
function void set_data_all(
data_t data);
next_data = data;
next_data_ld = '1;
endfunction : set_data_all
//---------------------------------------------------------------------------
// Radio Data Generation
// Radio Output Generation
//---------------------------------------------------------------------------
radio_t [NUM_CHANNELS-1:0] data = radio_init();
radio_t [NUM_CHANNELS-1:0] reg_data = radio_init_all();
timestamp_t reg_time = '0;
assign radio_rx_data = data;
// Output X when strobe is low to cause errors when we use the time or data
// during the wrong clock cycle.
assign radio_rx_data = radio_rx_stb ? reg_data : 'X;
assign radio_time = radio_rx_stb ? reg_time : 'X;
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;
if (radio_rst) begin
reg_data <= radio_init();
radio_rx_stb <= '0;
reg_time <= '0;
end else begin
radio_rx_stb <= '0;
if ($urandom_range(99) < STB_PROB) begin
for (int ch_i = 0; ch_i < NUM_CHANNELS; ch_i++) begin
for (int samp_i = 0; samp_i < NSPC; samp_i++) begin
reg_data[ch_i][samp_i] = reg_data[ch_i][samp_i] + NSPC;
end
end
reg_time <= reg_time + INCREMENT;
radio_rx_stb <= '1;
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;
// Override the radio data
if (next_data_ld) begin
for (int ch_i=0; ch_i < NUM_CHANNELS; ch_i++) begin
if (next_data_ld[ch_i]) reg_data[ch_i] <= next_data[ch_i];
end
next_data_ld = 0;
end
// Override the radio time
if (next_time_ld) begin
reg_time <= next_time;
next_time_ld = 0;
end
end
end
end
end : radio_data_count_reg
endmodule : sim_radio_gen
endmodule : sim_radio_gen