Continue to Site

# Proposed FPGA CARD

#### salahberra39

##### Newbie
Dear

I hope you are doing very well.

I am a PhD student in signal detection massive MIMO system, I would like to implement my algorithm in FPGA with code VHDL.

please advise me which card I can use and any one can help me from the beginning, i know VHDL.

and which, is a good book for VHDL matrix math.

thank you

How much memory do you need? What speed? What are your inputs? What are your outputs? How complex are your calculations?

You've given us zero information.

Ok.

I would start with Matlab code. Because my code was designed in Matlab.

specific FPGA implementation of this design is given for 16-QAM , with 16-bit quantization, N = 12,K = 8.

we have =

channel H size N*K
transmitter x=K*1
noise n= N*1.
Y=N*1

Y=xH+n

the MMSE estimate is hatx= (H^HH + sigma^2I_N )−1H^H y.

The inputs are H, x, n, and Y calculated, then we MMSE detector.

you can follow this channel :

@salahberra39
You have told us only about the computation. This part comes later, when you are designing the system with VHDL. And yes Matlab HDL Coder can also generate the design for you.

But to make a choice on the FPGA development board, you need to tell us how the data required for computation is fed-in to the FPGA and how the computed data is fed-out. In other terms, you need to tell us about the systems that will interface the FPGA.

hI

I told you that I am new to this VHDL design, I just took the course for simple cases. If you can see the paper that I sent you I want to implement this paper.

we need multiple matrix matrix, matrix-vector all of them complex numbers.

this is code Matlab, I would like to implement.

MODERATOR ACTION : Added code tags

Code:
function Detectors(varargin)
% -- set up default/custom parameters

if isempty(varargin)

disp('using default simulation settings and parameters...')

par.simName = 'ERR_128x16_64QAM'; % simulation name (used for saving results)
par.runId = 0; % simulation ID (used to reproduce results)
par.MR = 128; % receive antennas
par.MT = 16; % transmit antennas (set not larger than MR!)
par.mod = '64QAM'; % modulation type: 'BPSK','QPSK','16QAM','64QAM'
par.trials = 1e3; % number of Monte-Carlo trials (transmissions)
par.SNRdB_list = 0:2:20; % list of SNR [dB] values to be simulated
par.detector = {'MMSE', 'SOR', }
par.maxiter = 3; % max number of iterations n = 1 to any integer
par.omega = 2; % relaxation parameter for SOR
alpha = 1/par.omega;

else

disp('use custom simulation settings and parameters...')
par = varargin{1}; % only argument is par structure

end

% -- initialization

% use runId random seed (enables reproducibility)
rng('default');

% set up Gray-mapped constellation alphabet (according to IEEE 802.11)
switch (par.mod)
case 'BPSK',
par.symbols = [ -1 1 ];
case 'QPSK',
par.symbols = [ -1-1i,-1+1i, ...
+1-1i,+1+1i ];
case '16QAM',
par.symbols = [ -3-3i,-3-1i,-3+3i,-3+1i, ...
-1-3i,-1-1i,-1+3i,-1+1i, ...
+3-3i,+3-1i,+3+3i,+3+1i, ...
+1-3i,+1-1i,+1+3i,+1+1i ];
case '64QAM',
par.symbols = [ -7-7i,-7-5i,-7-1i,-7-3i,-7+7i,-7+5i,-7+1i,-7+3i, ...
-5-7i,-5-5i,-5-1i,-5-3i,-5+7i,-5+5i,-5+1i,-5+3i, ...
-1-7i,-1-5i,-1-1i,-1-3i,-1+7i,-1+5i,-1+1i,-1+3i, ...
-3-7i,-3-5i,-3-1i,-3-3i,-3+7i,-3+5i,-3+1i,-3+3i, ...
+7-7i,+7-5i,+7-1i,+7-3i,+7+7i,+7+5i,+7+1i,+7+3i, ...
+5-7i,+5-5i,+5-1i,+5-3i,+5+7i,+5+5i,+5+1i,+5+3i, ...
+1-7i,+1-5i,+1-1i,+1-3i,+1+7i,+1+5i,+1+1i,+1+3i, ...
+3-7i,+3-5i,+3-1i,+3-3i,+3+7i,+3+5i,+3+1i,+3+3i ];

end

% extract average symbol energy
par.Es = mean(abs(par.symbols).^2);

% precompute bit labels
par.Q = log2(length(par.symbols)); % number of bits per symbol
par.bits = de2bi(0:length(par.symbols)-1,par.Q,'left-msb');

% track simulation time
time_elapsed = 0;

% -- start simulation

% initialize result arrays (detector x SNR)
res.VER = zeros(length(par.detector),length(par.SNRdB_list)); % vector error rate
res.SER = zeros(length(par.detector),length(par.SNRdB_list)); % symbol error rate
res.BER = zeros(length(par.detector),length(par.SNRdB_list)); % bit error rate

% generate random bit stream (antenna x bit x trial)
bits = randi([0 1],par.MT,par.Q,par.trials);

% trials loop
tic
for t=1ar.trials
t
% generate transmit symbol
idx = bi2de(bits,:,t),'left-msb')+1;
s1 = par.symbols(idx).';

% generate iid Gaussian channel matrix & noise vector
n = sqrt(0.5)*(randn(par.MR,1)+1i*randn(par.MR,1));
H = sqrt(0.5)*(randn(par.MR,par.MT)+1i*randn(par.MR,par.MT));

% transmit over noiseless channel (will be used later)
x = H*s1;

% SNR loop
for k=1:length(par.SNRdB_list)

% compute noise variance (average SNR per receive antenna is: SNR=MT*Es/N0)
N0 = par.MT*par.Es*10^(-par.SNRdB_list(k)/10);
% transmit data over noisy channel
y = x+sqrt(N0)*n;

for d=1:length(par.detector)

switch (par.detector{d}) % select algorithms
case 'MMSE', %  MMSE detector
[idxhat,bithat] = MMSE(par,H,y,N0);
case 'SOR' % SOR
[idxhat,bithat] = SOR(par,H,y,N0,alpha);
otherwise,
error('par.detector type not defined.')
end

% -- compute error metrics
err = (idx~=idxhat);
res.VER(d,k) = res.VER(d,k) + any(err);
res.SER(d,k) = res.SER(d,k) + sum(err)/par.MT;
res.BER(d,k) = res.BER(d,k) + sum(sum(bits,:,t)~=bithat))/(par.MT*par.Q);

end % algorithm loop

end % SNR loop

% keep track of simulation time
if toc>10
time=toc;
time_elapsed = time_elapsed + time;
fprintf('estimated remaining simulation time: %3.0f min.\n',time_elapsed*(par.trials/t-1)/60);
tic
end

end % trials loop

% normalize results
res.VER = res.VER/par.trials;
res.SER = res.SER/par.trials;
res.BER = res.BER/par.trials;
res.time_elapsed = time_elapsed

% -- save final results (par and res structure)

% -- show results (generates fairly nice Matlab plot)

marker_style = {'mo-','ks-','kv-.','rp:','r*-','c>--','cx:','b-.','bo--', 'yd-', 'yh-.', 'g>-.', 'gp-'};
figure(1)
for d=1:length(par.detector)
if d==1
semilogy(par.SNRdB_list,res.BER(d,,marker_style{d},'LineWidth',2)
hold on
else
semilogy(par.SNRdB_list,res.BER(d,,marker_style{d},'LineWidth',2)
end
end
hold off
grid on
%xlabel('average SNR per receive antenna [dB]','FontSize',12)
xlabel('SNR [dB]','FontSize',12)
ylabel('BER','FontSize',12)
axis([min(par.SNRdB_list) max(par.SNRdB_list) 1e-5 1])
legend(par.detector,'FontSize',12)
set(gca,'FontSize',12)
title(['Performance comparison in ' int2str(par.MT)  ' x ' int2str(par.MR) ', n = ' int2str(par.maxiter)]);

end
%% MMSE detector (MMSE)
function [idxhat,bithat] = MMSE(par,H,y,N0)
W = (H'*H+(N0/par.Es)*eye(par.MT))\(H');
xhat = W*y;
G = real(diag(W*H));
[~,idxhat] = min(abs(xhat*ones(1,length(par.symbols))-G*par.symbols).^2,[],2);
bithat = par.bits(idxhat,;
end

%% SOR
% omega is the relaxation parameter 0<w<2
function [idxhat,bithat] = SOR(par,H,y,N0,alpha)
A = H'*H+(N0/par.Es)*eye(par.MT);
MF = H'*y;

D = diag(diag(A)); %D
E = -triu(A,1);    %L=-(tril(HH)-D);
F = -tril(A,-1);   %U=-(triu(HH)-D);
xhat = diag(inv(D));% inv(D)*MF;
for i = 0ar.maxiter %par.alg.maxiter
xhat = inv(D-alpha*E)*(alpha*MF+((1-alpha)*D + alpha*F)*xhat);
end
[~,idxhat] = min(abs(xhat*ones(1,length(par.symbols))-ones(par.MT,1)*par.symbols).^2,[],2);
bithat = par.bits(idxhat,;
end

Last edited by a moderator:

You are not listening to what we are TRYING to tell you:

Nobody (at least not me) is going to wade through all your Matlab code.

Ok this code that I start for gram matrix H^H H. i HAVE complex matrix, i need to test this one

MODERATOR ACTION : Added code tags

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ComplexMatrixProduct is
generic (
MATRIX_SIZE : positive := 16;
DATA_WIDTH : positive := 8
);
port (
clk : in std_logic;
reset : in std_logic;
start : in std_logic;
h_matrix : in std_logic_vector((MATRIX_SIZE * DATA_WIDTH * 2) - 1 downto 0);
result : out std_logic_vector((DATA_WIDTH * 2 * MATRIX_SIZE * MATRIX_SIZE) - 1 downto 0);
done : out std_logic
);
end entity;

architecture Behavioral of ComplexMatrixProduct is
type ComplexNumber is record
real : integer range -(2**(DATA_WIDTH-1)) to (2**(DATA_WIDTH-1))-1;
imag : integer range -(2**(DATA_WIDTH-1)) to (2**(DATA_WIDTH-1))-1;
end record;

type ComplexMatrix is array (natural range <>) of ComplexNumber;

signal h_matrix_int : ComplexMatrix(0 to MATRIX_SIZE-1, 0 to MATRIX_SIZE-1);
signal result_int : ComplexMatrix(0 to MATRIX_SIZE-1, 0 to MATRIX_SIZE-1);
signal i : natural range 0 to MATRIX_SIZE;
signal j : natural range 0 to MATRIX_SIZE;
signal k : natural range 0 to MATRIX_SIZE;
signal mult_done : boolean;
signal state : natural range 0 to 3; -- Added a state machine

-- Conversion from std_logic_vector to ComplexMatrix
process(h_matrix)
begin
for i in 0 to MATRIX_SIZE-1 loop
for j in 0 to MATRIX_SIZE-1 loop
h_matrix_int(i, j).real <= to_integer(signed(h_matrix((i*DATA_WIDTH*2)+(DATA_WIDTH-1) downto (i*DATA_WIDTH*2))));
h_matrix_int(i, j).imag <= to_integer(signed(h_matrix((i*DATA_WIDTH*2)+(DATA_WIDTH*2)-1 downto (i*DATA_WIDTH*2)+DATA_WIDTH)));
end loop;
end loop;
end process;

-- Matrix product calculation
matrix_product: process(clk, reset, start)
variable sum_real, sum_imag : integer;
begin
if reset = '1' then
i <= 0;
j <= 0;
mult_done <= false;
state <= 0;
elsif rising_edge(clk) then
if start = '1' then
case state is
when 0 => -- Start state, initialize the counters
i <= 0;
j <= 0;
state <= 1;
when 1 => -- Computing state, perform matrix multiplication
sum_real := 0;
sum_imag := 0;
for k in 0 to MATRIX_SIZE-1 loop
sum_real := sum_real + (h_matrix_int(i, k).real * h_matrix_int(k, j).real - h_matrix_int(i, k).imag * h_matrix_int(k, j).imag);
sum_imag := sum_imag + (h_matrix_int(i, k).real * h_matrix_int(k, j).imag + h_matrix_int(i, k).imag * h_matrix_int(k, j).real);
end loop;
result_int(i, j).real <= sum_real;
result_int(i, j).imag <= sum_imag;
if j = MATRIX_SIZE-1 then
if i = MATRIX_SIZE-1 then
state <= 2; -- Done with computation, move to Done state
else
i <= i + 1; -- Increase row counter
j <= 0; -- Reset column counter
end if;
else
j <= j + 1; -- Increase column counter
end if;
when 2 => -- Done state
mult_done <= true;
if start = '0' then
state <= 3; -- Move to Idle state
end if;
when others => -- Idle state, wait for start signal
mult_done <= false;
if start = '1' then
state <= 0; -- Move to Start state
end if;
end case;
end if;
end if;
end process;

-- Conversion from ComplexMatrix to std_logic_vector
convert_result: process(result_int)
begin
for i in 0 to MATRIX_SIZE-1 loop
for j in 0 to MATRIX_SIZE-1 loop
result((i*DATA_WIDTH*2* MATRIX_SIZE)+(j*DATA_WIDTH*2)+(DATA_WIDTH-1) downto (i*DATA_WIDTH*2* MATRIX_SIZE)+(j*DATA_WIDTH*2)) <= std_logic_vector(to_signed(result_int(i, j).real, DATA_WIDTH));
result((i*DATA_WIDTH*2* MATRIX_SIZE)+(j*DATA_WIDTH*2)+(DATA_WIDTH*2)-1 downto (i*DATA_WIDTH*2* MATRIX_SIZE)+(j*DATA_WIDTH*2)+DATA_WIDTH) <= std_logic_vector(to_signed(result_int(i, j).imag, DATA_WIDTH));
end loop;
end loop;
end process;

-- Done signal
done <= '1' when mult_done = true else '0';

end architecture;

Last edited by a moderator:

@salahberra39
1. Have have digressed from your original question.
2. You are now trying to shift the discussion to the VHDL implementation. Technically you need to start a new thread for this.

Please understand that it is not possible for us to read papers for you and suggest solutions!

And yes, please do not expect us to bheave as compilers for your code. You have the tools, you run you code, you return here with the problems you face with adequate description (if you say you are a newbie to VHDL, you need to hone your VHDL skills first). That is how this forum works!