60 lines
2.1 KiB
Systemverilog
60 lines
2.1 KiB
Systemverilog
// AN9238 virtual ADC model (1 port)
|
|
|
|
module virtual_adc_model #(
|
|
parameter int unsigned ADC_DATA_WIDTH = 12,
|
|
|
|
// Bipolar input range: +/- VOLTAGE_RANGE
|
|
parameter real VOLTAGE_RANGE = 1.0,
|
|
|
|
// Analog input correction
|
|
parameter real VOLTAGE_GAIN = 0.2,
|
|
parameter real GROUND_BIAS = 0.0,
|
|
|
|
// ADC timing parameters
|
|
parameter time CONVERSION_DELAY = 250ps
|
|
)(
|
|
input logic clk_i,
|
|
input real voltage_i,
|
|
|
|
output logic otr_o,
|
|
output logic [ADC_DATA_WIDTH-1:0] data_o
|
|
);
|
|
|
|
localparam int unsigned ZERO_CODE = (1 << (ADC_DATA_WIDTH - 1));
|
|
localparam real VOLTAGE_STEP = (2 * VOLTAGE_RANGE) / real'((1 << ADC_DATA_WIDTH) - 1);
|
|
|
|
real voltage_corrected;
|
|
|
|
//------------------------------------------------------------
|
|
// Convert analog voltage to ADC code
|
|
//------------------------------------------------------------
|
|
function automatic logic [ADC_DATA_WIDTH-1:0] voltage_to_code( input real voltage );
|
|
if (voltage <= -VOLTAGE_RANGE) return '0;
|
|
if (voltage >= VOLTAGE_RANGE) return {ADC_DATA_WIDTH{1'b1}};
|
|
return $rtoi(voltage / VOLTAGE_STEP + real'((ZERO_CODE)) + 0.5);
|
|
endfunction
|
|
|
|
function automatic logic range_check( input real voltage );
|
|
real v_abs = (voltage < 0.0) ? -voltage : voltage;
|
|
return v_abs >= VOLTAGE_RANGE;
|
|
endfunction
|
|
|
|
//------------------------------------------------------------
|
|
// Initial state
|
|
//------------------------------------------------------------
|
|
initial begin
|
|
data_o = ZERO_CODE; // 0V
|
|
otr_o = 0;
|
|
end
|
|
|
|
//------------------------------------------------------------
|
|
// Update analog output
|
|
//------------------------------------------------------------
|
|
always @(posedge clk_i) begin
|
|
voltage_corrected = (voltage_i - GROUND_BIAS) * VOLTAGE_GAIN;
|
|
data_o <= #(CONVERSION_DELAY) voltage_to_code(voltage_corrected);
|
|
otr_o <= #(CONVERSION_DELAY) range_check(voltage_corrected);
|
|
end
|
|
|
|
endmodule
|