// AN9767 model (1 port) module virtual_dac_model #( parameter int unsigned DAC_DATA_WIDTH = 14, // Bipolar output range: +/- VOLTAGE_RANGE parameter real VOLTAGE_RANGE = 5.0, // Analog output correction parameter real VOLTAGE_GAIN = 1.0, parameter real GROUND_BIAS = 0.0, // DAC timing parameters parameter time TRANSMISSION_DELAY = 150ps, parameter time CONVERSION_DELAY = 150ps )( input logic clk_i, input logic wrt_i, input logic [DAC_DATA_WIDTH-1:0] data_i, output real voltage_o ); localparam int unsigned ZERO_CODE = (1 << (DAC_DATA_WIDTH - 1)); localparam real VOLTAGE_STEP = VOLTAGE_RANGE / real'(ZERO_CODE); logic [DAC_DATA_WIDTH-1:0] dac_code; //------------------------------------------------------------ // Convert DAC code to analog voltage //------------------------------------------------------------ function automatic real code_to_voltage( input logic [DAC_DATA_WIDTH-1:0] code); return (int'(code) - int'(ZERO_CODE)) * VOLTAGE_STEP; endfunction //------------------------------------------------------------ // Initial state //------------------------------------------------------------ initial begin dac_code = '0; voltage_o = code_to_voltage('0) * VOLTAGE_GAIN + GROUND_BIAS; end //------------------------------------------------------------ // Latch new DAC code //------------------------------------------------------------ always @(posedge wrt_i) begin #(TRANSMISSION_DELAY); dac_code = data_i; end //------------------------------------------------------------ // Update analog output //------------------------------------------------------------ always @(posedge clk_i) begin #(CONVERSION_DELAY); voltage_o = code_to_voltage(dac_code) * VOLTAGE_GAIN + GROUND_BIAS; end endmodule