Continue to Site

Welcome to

Welcome to our site! is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Proposed FPGA CARD


May 21, 2024
Reaction score
Trophy points
Activity points

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

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.


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 :

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.

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

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 = 2; % relaxation parameter for SOR
    alpha = 1/;
    disp('use custom simulation settings and parameters...')
    par = varargin{1}; % only argument is par structure

% -- initialization

% use runId random seed (enables reproducibility)

% 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 ];

% 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
for t=1ar.trials
    % 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);
                    error('par.detector type not defined.')
            % -- 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_elapsed = time_elapsed + time;
        fprintf('estimated remaining simulation time: %3.0f min.\n',time_elapsed*(par.trials/t-1)/60);
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-'};
for d=1:length(par.detector)
    if d==1
        hold on
hold off
grid on
%xlabel('average SNR per receive antenna [dB]','FontSize',12)
xlabel('SNR [dB]','FontSize',12)
axis([min(par.SNRdB_list) max(par.SNRdB_list) 1e-5 1])
title(['Performance comparison in ' int2str(par.MT)  ' x ' int2str(par.MR) ', n = ' int2str(par.maxiter)]);

%% 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,;

%% 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);
[~,idxhat] = min(abs(xhat*ones(1,length(par.symbols))-ones(par.MT,1)*par.symbols).^2,[],2);
bithat = par.bits(idxhat,;
Last edited by a moderator:
You are not listening to what we are TRYING to tell you:

First of all, you asked what board you should use, and we asked what your hardware requirements are. And your answer was 200 lines of Matlab code.

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

Thirdly,p, you need to use CODE tags, your code is unreadable.
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

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
 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;
 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
 i <= i + 1; -- Increase row counter
 j <= 0; -- Reset column counter
 end if;
 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)
 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:
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!

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to