I'm trying to generate a vhdl code using the HDL code generator in Matlab.
I have a matlab function and its test bench.
This is the matlab function:
function [received_signal_real, received_signal_imag, error_rate] = hdl_compatible_code(n, channel_type)
% Constants
aircraft_altitude = fi(45000,1,32,10); % Altitude of the aircraft in feet
distance_km = fi(350,1,32,10); % Distance between aircraft and base station in kilometers
speed_of_light = fi(3e8,1,32,10); % Speed of light in m/s
n = 100;
% Pathloss model - Free Space Path Loss (FSPL)
fc = fi(1.5e9,1,32,10); % Carrier frequency in Hz (1.5GHz)
lambda = speed_of_light / fc; % Wavelength
path_loss_dB = 20 *log10_approx(fi(4 * pi * distance_km * 1e3 / lambda,1,32,10)); % Path loss in dB
% AWGN
SNR_dB_awgn = fi(10,1,32,10); % Signal to noise ratio in dB for AWGN channel
SNR_awgn = fi(fi(10)^(SNR_dB_awgn / 10),1,32,10); % Convert SNR to linear scale for AWGN channel
tx_power_awgn = fi(1,1,32,10); % Initial guess for transmit power for AWGN channel
noise_power_awgn = tx_power_awgn / SNR_awgn; % Noise power based on SNR for AWGN channel
% Doppler spread
aircraft_speed = fi(660,1,32,10); % Average aircraft speed in meters per second
fd_max = fi(((aircraft_speed * fi(0.51444,1,32,10) * fc) / speed_of_light),1,32,10); % Doppler frequency shift
% Modulation using lookup table
% Precompute constellation points (Scalar approach)
constellation_points = [fi(1,1,16,10), fi(1i,1,16,10),fi(-1,1,16,10), fi(-1i,1,16,10)];
% Modulation
data = lfsr_data(n); % Generate random bits
qpsk_symbols = constellation_points(data + 1); % QPSK modulation: symbol mapping to complex constellation points
% Generate doppler effect using lookup table
two_pi_fd_max = fi(2*pi*fd_max,1,128,10);
t = fi((0:n-1) /n,1,32,10); % Time vector
doppler_shift = cos_lookup(fi((2 * pi * fd_max * t),1,32,10));
% Channel simulation
if channel_type == 0 % AWGN channel
noise_real = sqrt(noise_power_awgn / 2) * lfsr_noise(n); % Generate noise for real part
noise_imag = sqrt(noise_power_awgn / 2) * lfsr_noise(n); % Generate noise for imaginary part
received_signal = (qpsk_symbols .* doppler_shift) + noise_real + fi(1i,1,16,10) * noise_imag; % Received signal in AWGN channel
elseif channel_type == 1 % Rician fading channel
% Rician channel parameters
K =fi( 5,1,32,10); % Rician factor
LOS_power_dB =fi( -10,1,32,10); % Line of sight power in dB
LOS_power_linear = pow2(fi(10,1,32,10),LOS_power_dB/10); % Convert LOS power to linear scale
K_linear = pow2(fi(10,1,32,10),K/10); % Convert Rician factor to linear scale
% Generate fading coefficients
LOS = sqrt(LOS_power_linear / (2 * (1 + 1 / K_linear))) * ones(1, n,'like',fi(0,1,16,10)); % LOS component
scattering = sqrt(LOS_power_linear / (2 * (1 + K_linear))) * (lfsr_noise(n) +fi( 1i,1,16,10) * lfsr_noise(n)); % Scattering component
fading_coefficient = LOS + scattering; % Rician fading coefficients
received_signal = (qpsk_symbols .* fading_coefficient .* doppler_shift); % Apply fading to the transmitted signal
% Add noise to the received signal in Rician channel
noise_real_rician = sqrt(noise_power_awgn / 2) * lfsr_noise(n); % Generate noise for real part
noise_imag_rician = sqrt(noise_power_awgn / 2) * lfsr_noise(n); % Generate noise for imaginary part
received_signal = fi((received_signal + noise_real_rician + fi(1i,1,16,10) * noise_imag_rician),1,49,20); % Add noise
else
error('hdl_compatible_code:UnknownChannelType', 'Unknown channel type');
end
% QPSK demodulation
% Hard decision demodulation
% Decision regions
decision_regions = [fi(-1-1i,1,16,10), fi(-1+1i,1,16,10), fi(1-1i,1,16,10), fi(1+1i,1,16,10)];
% Initialize demodulated symbols
demodulated_symbols = zeros(1, n,'uint8');
for i = 1:n
%Seperate real and imaginary part of received_signal and
%decision_regions
received_real = real(received_signal(i));
received_imag = imag(received_signal(i));
decision_real = real(decision_regions);
decision_imag = imag(decision_regions);
%Compute the absolute difference for real and imaginary parts
%seperately
diff_real = received_real - decision_real;
diff_imag = received_imag - decision_imag;
%Compute the absolute value using Pythagorean theorem
abs_diff = sqrt(diff_real.^2+diff_imag.^2);
%Find the index corresponding to the minimum absoloute difference
[~,~]=min(abs_diff);
end
% Calculate the error rate
errors = sum(bitxor(fi((data),0,8,0), fi((demodulated_symbols),0,8,0))); % Count errors
% Extract real and imaginary parts
received_signal_real = real(received_signal);
received_signal_imag = imag(received_signal);
error_rate = errors / n; % Calculate error rate
end
function noise = lfsr_noise(n)
% Linear feedback shift register (LFSR) for pseudo-random number generation
% Initialize LFSR state
lfsr_state = uint32(1);
noise = zeros(1, n,'like',fi(0,1,16,10));
for i = 1:n
% Generate pseudo-random bit using xor feedback
new_bit = bitxor(bitget(lfsr_state, 1), bitget(lfsr_state, 3));
lfsr_state = bitshift(lfsr_state, -1);
lfsr_state = bitset(lfsr_state, 32, new_bit);
noise(i) = fi(lfsr_state,0,32,0) / fi(intmax('uint32'),1,16,10); % Scale [0,1]
end
end
function data = lfsr_data(n)
% Linear feedback shift register (LFSR) for generating random data
% Initialize LFSR state
lfsr_state = uint32(1);
data = zeros(1, n, 'uint8');
for i = 1:n
% Generate pseudo-random bit using xor feedback
new_bit = bitxor(bitget(lfsr_state, 1), bitget(lfsr_state, 3));
lfsr_state = bitshift(lfsr_state, -1);
lfsr_state = bitset(lfsr_state, 32, new_bit);
data(i) = fi((mod(lfsr_state,4)),0,2,0); % Generate random values in the range [0, 3]
end
end
function cos_value = cos_lookup(angle)
% Precompute cosine values for a range of angles
angles =fi( (0:0.01:2*pi),1,32,10); % Define the range of angles (adjust the step size as needed)
cos_values = fi((cos(angles)),1,16,10); % Compute cosine values
% Interpolate the cosine value for the given angle
cos_value = fi((zeros(size(angle))),1,16,10);
for i = 1:numel(angle)
[~,idx]=min(abs(angles-angle(i)));
cos_value(i)=cos_values(idx);
end
end
function y = log2_approx(x)
%Fixed-point logarithm base 2 approximation
y = fi(0,1,32,10);%Initialize y as fixed-point format
one = fi(1,1,32,10);%Define one in the same fixed-point format
sqrt2 = fi((sqrt(2)),1,32,10);%Define sqrt(2) in the same fixed -point format
for i = 1:32 %Limiting the iterations to 32 to avoid infinite loop
if x > one
x = bitsra(x,1);
y = fi((y + one),1,32,10);
end
end
frac = fi (0.5,1,32,10);
for i = 1:32
if x < one
x = bitsll(x,1);
y =fi( (y - one),1,32,10);
end
end
frac = fi (0.5,1,32,10);
two_pow_neg32 = fi((2^-32),1,32,10);
for i = 1:32
if x >= sqrt2
x = divide(x,sqrt2);
y =fi((y + frac) , 1,32,10);
end
frac = divide(frac,2);
end
end
function y = log10_approx(x)
%Approximate log10 function using a fixed-point approach
y = log2_approx(x)/ log2_approx(fi(10,1,32,10));
end
function result = divide(a,b)
%custom fixed-point division function
result = a/b;
result = fi(result,a.Signed,a.WordLength,a.FractionLength);
end
and this is the test bench
function test_modulation_channel()
%Test 1:AWGN channel
n=100;%Number of sampples
channel_type = 0;%AWGN Channel
hdl_compatible_code(n,channel_type);
assert(true,'hdl_compatible_code should run without errors for AWGN channel');
%Test 2:Rician Fading Channel
n = 100; %Number of samples
channel_type = 1; %Rician channel
hdl_compatible_code(n,channel_type);
assert(true,'hdl_compatible_code should run without errors for Rician channel');
%Test 3:Invalid channel type
n = 100;%Number of samples
channel_type = 2; %Invalid channel type
try
hdl_compatible_code(n,channel_type);
assert(false,'hdl_compatible_code should throw an error for invalid channel type');
catch e
assert(strcmp(e.identifier,'hdl_compatible_code:UnknownChannelType'),'hdl_compatible_code should throw an error with identifier ''hdl_compatible_code:UnknownChannelType''');
end
fprintf('All tests passed!\n');
end
But the workflow advisor is showing 1 error in the HSL conformance report, and in that, it says the function requiring attention is the 'fi' function that I've used. Can anyone fix my code so that it runs on the HDL coder and generates a VHDL code that can be uploaded onto any generic FPGA?
There's a high chance that this is an error within the version of Matlab that I'm using (2020a).