fpga: lib: Support time and data updates in sim_radio_gen
Original-commit: 684a9879d35269eb80ea79fc69993570c0147189
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user