QAM Modulation using Karnaugh-map walks

This article focused on constructing constellation for rectangular QAM modulation using Karnaugh-map walks. Exploit inherent property of Karnaugh-maps to construct Gray coded QAM constellation points.

Karnaugh Map walk 1 for QAM modulation
Figure 1: Karnaugh-Map walks
Figure 2: Karnaugh-Map walks

M-ary Quadrature Amplitude Modulation (M-QAM)

In MQAM modulations, the information bits are encoded as variations in the amplitude and the phase of the signal. The M-QAM modulator transmits a series of information symbols drawn from the set , with each transmitted symbol holding k bits of information (). To restrict the erroneous receiver decisions to single bit errors, the information symbols are Gray coded. The information symbols are then digitally modulated using a rectangular M-QAM technique, whose signal set is given by

Karnaugh Map Walks and Gray Codes:

In any M-QAM constellation, in order to restrict the erroneous symbol decisions to single bit errors, the adjacent symbols in the transmitter constellation should not differ by more than one bit. This is usually achieved by converting the input symbols to Gray coded symbols and then mapping it to the desired QAM constellation. But this intermediate step can be skipped altogether by using a Look-Up-Table (LUT) approach which properly translates the input symbol to appropriate position in the constellation.

This article is part of the following books
Digital Modulations using Matlab : Build Simulation Models from Scratch, ISBN: 978-1521493885
Digital Modulations using Python ISBN: 978-1712321638
All books available in ebook (PDF) and Paperback formats

We will exploit the inherent property of Karnaugh Maps to generate the look-up table of dimension (where ) for the gray coded M-QAM constellation which is rectangular and symmetric (M=4, 16, 64, 256, …). The first step in constructing a QAM constellation is to convert a sequential numbers representing the message symbols to gray coded format. The function to convert decimal numbers to Gray codes is given next.

function [grayCoded]=dec2gray(decInput)
%convert decimal to Gray code representation
%example: x= [0 1 2 3 4 5 6 7] %decimal
%y=dec2gray(x); %returns y = [ 0 1 3 2 6 7 5 4] %Gray coded
[rows,cols]=size(decInput);
grayCoded=zeros(rows,cols);
for i=1:rows
   for j=1:cols
    grayCoded(i,j)=bitxor(bitshift(decInput(i,j),-1),decInput(i,j));
   end
end

If you are familiar with Karnaugh Maps (K-Maps) [1], it is easier for you to identify that the K-Maps are constructed based on Gray Codes. By the nature of the construction of K-Maps, the address of the adjacent cells differ by only one bit. If we supper impose the given M-QAM constellation on the K-Map and walk through the address of each cell in certain pattern, it gives the Gray-coded M-QAM constellation.

As mentioned, a walk through the K-Map will produce a sequence of gray codes. Moreover, if the walk can be looped back to the origin or starting point, it will generate a sequence of cyclic Gray codes. Different walking patterns are possible on K-Maps that generate different sequences of Gray codes. Some of the walks on a \(4 \times 4\) K-Map are shown in Figures 1 and 2. This can be readily extended to any K-Map configuration of higher order.

In walk types 1,3 and 4, the address of the starting point and end point differ by only one bit and the corresponding cells are adjacent to each other. In effect, the walk can be looped to give cyclic Gray codes. But in type 2 walk, the starting cell (0000 ) and the ending cell (1101) are not adjacent to each other and thus the Gray code generated using this pattern of walk is not cyclic. By far, type 1 walk is the simplest. All we have to do is alternate the direction of the walk for every row and read the gray coded address.

The Matlab function constructQAM.m given in the book implements (refer the book Digital Modulations using Matlab for the full Matlab code, python code is available in the book Digital Modulations using Python) the walk type 1 for constructing a MQAM constellation.

Rectangular QAM from PAM constellation

There exist other constellation shapes (like circular, triangular constellations) that are more efficient (in terms of energy required to achieve same the error probability) than the standard rectangular constellation. Rectangular (symmetric or square) constellations are the preferred choice of implementation due to its simplicity in implementing modulation and demodulation.

Any rectangular QAM constellation is equivalent to superimposing two Amplitude Shift Keying (ASK) signals (also called Pulse Amplitude Modulation – PAM) on quadrature carriers. For example, 16-QAM constellation points can be generated from two 4-PAM signals, similarly the 64-QAM constellation points can be generated from two 8-PAM signals. The generic equation to generate PAM signals of dimension D is

For generating 16-QAM, the dimension D of PAM is set to . Thus for constructing a M-QAM constellation, the PAM dimension is set as . Matlab code for dynamically generating M-QAM constellation points based on Karnaugh map Gray code walk is given below. The resulting ideal constellations for Gray coded 16-QAM and 64-QAM are shown in following figure.

Rate this article : Note: There is a rating embedded within this post, please visit this post to rate it.

For further reading

[1] C. E. Stroud, “Karnaugh Maps (K-map) – Combinational Logic Minimization”, course notes, Auburn University↗

Related topics in this chapter

Digital Modulators and Demodulators - Complex Baseband Equivalent Models
Introduction
Complex baseband representation of modulated signal
Complex baseband representation of channel response
● Modulators for amplitude and phase modulations
 □ Pulse Amplitude Modulation (M-PAM)
 □ Phase Shift Keying Modulation (M-PSK)
 □ Quadrature Amplitude Modulation (M-QAM)
● Demodulators for amplitude and phase modulations
 □ M-PAM detection
 □ M-PSK detection
 □ M-QAM detection
 □ Optimum detector on IQ plane using minimum Euclidean distance
● M-ary FSK modulation and detection
 □ Modulator for M orthogonal signals
 □ M-FSK detection

Books by the author


Wireless Communication Systems in Matlab
Second Edition(PDF)

(172 votes, average: 3.66 out of 5)

Checkout Added to cart

Digital Modulations using Python
(PDF ebook)

(127 votes, average: 3.58 out of 5)

Checkout Added to cart

Digital Modulations using Matlab
(PDF ebook)

(134 votes, average: 3.63 out of 5)

Checkout Added to cart
Hand-picked Best books on Communication Engineering
Best books on Signal Processing

 

QAM modulation: simulate in Matlab & Python

A generic complex baseband simulation technique, to simulate all M-ary QAM modulation techniques is given here. The given simulation code is very generic, and it plots both simulated and theoretical symbol error rates for all M-QAM modulation techniques.

Rectangular QAM from PAM constellation

There exist other constellation shapes (like circular, triangular constellations) that are more efficient (in terms of energy required to achieve same the error probability) than the standard rectangular constellation. Rectangular (symmetric or square) constellations are the preferred choice of implementation due to its simplicity in implementing modulation and demodulation.

In one of the earlier articles, I have discussed the method of constructing constellation for rectangular QAM modulation using Karnaugh-map walks, where the inherent property of Karnaugh-maps is exploited to construct Gray coded QAM symbols.

Any rectangular QAM constellation is equivalent to superimposing two Amplitude Shift Keying (ASK) signals (also called Pulse Amplitude Modulation – PAM) on quadrature carriers. For example, 16-QAM constellation points can be generated from two 4-PAM signals, similarly the 64-QAM constellation points can be generated from two 8-PAM signals.

Figure 1: Signal space constellations for 16-QAM and 64-QAM

The generic equation to generate PAM signals of dimension D is

For generating 16-QAM, the dimension D of PAM is set to . Thus for constructing a M-QAM constellation, the PAM dimension is set as . Matlab code for dynamically generating M-QAM constellation points based on Karnaugh map Gray code walk is given below. The resulting ideal constellations for Gray coded 16-QAM and 64-QAM are shown in Figure 1.

Matlab code

Full Matlab code available in the book Digital Modulations using Matlab – build simulation models from scratch

function [s,ref]=mqam_modulator(M,d)
%Function to MQAM modulate the vector of data symbols - d
%[s,ref]=mqam_modulator(M,d) modulates the symbols defined by the vector d
% using MQAM modulation, where M specifies order of M-QAM modulation and
% vector d contains symbols whose values range 1:M. The output s is modulated
% output and ref represents reference constellation that can be used in demod
if(((M˜=1) && ˜mod(floor(log2(M)),2))==0), %M not a even power of 2
  error('Only Square MQAM supported. M must be even power of 2');
end
  ref=constructQAM(M); %construct reference constellation
  s=ref(d); %map information symbols to modulated symbols
end

Python code

Full Matlab code available in the book Digital Modulations using Python

class QAMModem(Modem):
    # Derived class: QAMModem
    
    def __init__(self,M):
        
        if (M==1) or (np.mod(np.log2(M),2)!=0): # M not a even power of 2
            raise ValueError('Only square MQAM supported. M must be even power of 2')
        
        n = np.arange(0,M) # Sequential address from 0 to M-1 (1xM dimension)
        a = np.asarray([xˆ(x>>1) for x in n]) #convert linear addresses to Gray code
        D = np.sqrt(M).astype(int) #Dimension of K-Map - N x N matrix
        a = np.reshape(a,(D,D)) # NxN gray coded matrix
        oddRows=np.arange(start = 1, stop = D ,step=2) # identify alternate rows
        
        nGray=np.reshape(a,(M)) # reshape to 1xM - Gray code walk on KMap
        #Construction of ideal M-QAM constellation from sqrt(M)-PAM
        (x,y)=np.divmod(nGray,D) #element-wise quotient and remainder
        Ax=2*x+1-D # PAM Amplitudes 2d+1-D - real axis
        Ay=2*y+1-D # PAM Amplitudes 2d+1-D - imag axis
        constellation = Ax+1j*Ay
        Modem.__init__(self, M, constellation, name='QAM') #set the modem attributes

This article is part of the following books
Digital Modulations using Matlab : Build Simulation Models from Scratch, ISBN: 978-1521493885
Digital Modulations using Python ISBN: 978-1712321638
All books available in ebook (PDF) and Paperback formats

M-QAM demodulation (coherent detection)

Generally the two main categories of detection techniques, commonly applied for detecting the digitally modulated data are coherent detection and non-coherent detection.

In the vector simulation model for the coherent detection, the transmitter and receiver agree on the same
reference constellation for modulating and demodulating the information. The modulators generate the reference constellation for the selected modulation type. The same reference constellation should be used if coherent detection is selected as the method of demodulating the received data vector.

On the other hand, in the non-coherent detection, the receiver is oblivious to the reference constellation used at the transmitter. The receiver uses methods like envelope detection to demodulate the data.

The IQ detection technique is an example of coherent detection. In the IQ detection technique, the first step is to compute the pair-wise Euclidean distance between the given two vectors – reference array and the received symbols corrupted with noise. Each symbol in the received symbol vector (represented on a p-dimensional plane) should be compared with every symbol in the reference array. Next, the symbols, from the reference array, that provide the minimum Euclidean distance are returned.

Let x=(x1,x2,…,xp) and y=(y1,y2,…,yp) be two points in p-dimensional space. The Euclidean distance between them is given by

The pair-wise Euclidean distance between two sets of vectors, say x and y, on a p-dimensional space, can be computed using the vectorized code. The vectorized code returns the ideal signaling points from matrix y that provides the minimum Euclidean distance. Since the vectorized implementation is devoid of nested for-loops, the program executes significantly faster for larger input matrices. The given code is very generic in the sense that it can be easily reused to implement optimum coherent receivers for any N-dimensional digital modulation technique (Please refer the books Digital Modulations using Matlab and Digital Modulations using Python for complete simulation code) .

Matlab code

Full Matlab code available in the book Digital Modulations using Matlab

function [dCap]= mqam_detector(M,r)
%Function to detect MQAM modulated symbols
%[dCap]= mqam_detector(M,r) detects the received MQAM signal points
%points - 'r'. M is the modulation level of MQAM
   if(((M˜=1) && ˜mod(floor(log2(M)),2))==0), %M not a even power of 2
      error('Only Square MQAM supported. M must be even power of 2');
   end
   ref=constructQAM(M); %reference constellation for MQAM
   [˜,dCap]= iqOptDetector(r,ref); %IQ detection
end

Python code

Full Matlab code available in the book Digital Modulations using Python

Performance simulation results

The simulation results for error rate performance of M-QAM modulations over AWGN channel and Rician flat-fading channel is given in the following figures.

Figure 2: Error rate performance of M-QAM modulations in AWGN channel

Rate this article: Note: There is a rating embedded within this post, please visit this post to rate it.

Reference

[1] John G. Proakis, “Digital Communciations”, McGraw-Hill; 5th edition.↗

Related Topics

Digital Modulators and Demodulators - Complex Baseband Equivalent Models
Introduction
Complex baseband representation of modulated signal
Complex baseband representation of channel response
● Modulators for amplitude and phase modulations
 □ Pulse Amplitude Modulation (M-PAM)
 □ Phase Shift Keying Modulation (M-PSK)
 □ Quadrature Amplitude Modulation (M-QAM)
● Demodulators for amplitude and phase modulations
 □ M-PAM detection
 □ M-PSK detection
 □ M-QAM detection
 □ Optimum detector on IQ plane using minimum Euclidean distance
● M-ary FSK modulation and detection
 □ Modulator for M orthogonal signals
 □ M-FSK detection

Books by the author


Wireless Communication Systems in Matlab
Second Edition(PDF)

Note: There is a rating embedded within this post, please visit this post to rate it.
Checkout Added to cart

Digital Modulations using Python
(PDF ebook)

Note: There is a rating embedded within this post, please visit this post to rate it.
Checkout Added to cart

Digital Modulations using Matlab
(PDF ebook)

Note: There is a rating embedded within this post, please visit this post to rate it.
Checkout Added to cart
Hand-picked Best books on Communication Engineering
Best books on Signal Processing

Natural Binary Codes and Gray Codes

Note: There is a rating embedded within this post, please visit this post to rate it.
In a given communication system, we always want to send data that represent real world data representing some physical quantity (be it speech, temperature, etc..,) .The real world physical quantity exist in analog domain and it becomes imperative to convert it to digital domain if we want to send it via a digital communication system. The above process of converting from analog to digital domain is done by an Analog to Digital Converter (ADC). A typical ADC contains the following components/blocks: 1) Sampler 2) Quantizer and 3) Encoder.

The Sampler converts the analog signal (manifestation of real world physical quantities) to sequence of discrete samples that are uniformly spaced in time. For more details on sampling process refer previous sections – 1) Sampling Theorem – Baseband Sampling and 2)Sampling Theorem – bandpass or under sampling .

The sampled signals from the sampling process are discrete in time but their amplitude is still continuous. In order to have a full representation of a signal in digital form, the signal has to be discrete in amplitude too. The amplitude of the sampled signal can take on values from infinite number of possible amplitude levels. This infinite number of possible amplitude has to be mapped to manageable amplitude levels by mapping different ranges of amplitude levels to a set a amplitude levels. This requires the next two blocks in ADC namely the quantizer and the encoder.

The quantizer discretizes the continuous amplitude of the sampled signal to discrete levels of amplitude. Several types of quantizers – uniform, non-uniform (A-law quantizer, law quantizer), differential quantizer, etc exist to fulfill the purpose.

The quantized signal has to be represented in some numeric form to get a digital representation. The encoder, the next block in the ADC, maps the discrete amplitude levels of the quantized samples to codewords. Codewords are just some form of numeric representation that the encoder assigns to each discretized amplitude level. Some of the convenient methods for one-to-one mapping of amplitude levels to codewords include: 1) Natural Binary Coding and 2) Gray coding. In natural binary mapping the discrete amplitude levels are coded in binary format.

Natural Binary Coding:

Consider that the sampler has discretized the samples in time and the quantizer maps discretized ranges of voltages to discrete amplitude levels. The first column in the following tables gives the encoder output in binary. The second column gives possible interpretations. Four commonly known interpretations exists namely – unsigned, signed magnitude, 1’s complement and 2’s complement form. The encoder just spits out the binary pattern and it is up to the designer to decide how to interpret the binary pattern in order to represent quantization values. The interpretation influences the quantizer ranges that will be mapped to specific values. Quantizer design and encoder’s output interpretation always goes hand in hand.

Out of the four common interpretations listed above, unsigned integer representation can represent positive values only. The other three representations can accommodate both positive and negative values.

In signed magnitude representation, also called Folded Binary Code / Foldover Binary Code, the Most Significant Bit (MSB) of the binary pattern represents the sign of the number (positive/negative) and the rest of the bits represent the magnitude. In 1’s complement representation, the negative values are just the 1’s complement of positive values. To convert a binary representation to 1’s complement, one just has to flip all the bits (1’s to 0’s and 0’s to 1’s). To convert to 2’s complement form, convert the binary pattern to 1’s complement and then add ‘1’ to the resulting sum.

The designer can conveniently choose any of the above mentioned forms to interpret the binary output of the encoder. For example, if the designer interprets it as 1’s complement or signed magnitude representation, then he would end-up in having two different representations for the value ‘0’. All the further calculations in DSP has to done by keeping this fact in mind and this poses greater threat to the reliability of design. To avoid this ambiguity, 2’s complement is always the choice of interpretation. Additionally two’s complement interpretation results in faster and simpler hardware. Also it can be noted that given the same number of bits (3 bits) to represent the binary output of the encoder, the two’s complement encoding can represent voltage ranges from -4.5V to +3.5V without any ambiguity. But in the case of signed magnitude and one’s complement encoding the range of representable voltage ranges shrinks to -3.5V to +3.5V but they also result in ambiguity in representing 0V.

Gray Coding:

Gray Coding is another form of representation that is used ubiquitously in all applications. In Gray coding, the adjacent representations (symbols) differ by only one bit. Gray coding, when combined with Forward Error Correction codes capable of corrective single bit errors, it can aid in correction of erroneous reception of bits that spills into adjacent symbols. Digital modulation techniques like M-PSK and M-QAM use Gray coding representation to represent the symbols that are modulated.

Converting from Natural Binary to Gray:

To convert a binary representation (X3 X2 X1 X0) to Gray code (Y3 Y2 Y1 Y0), following method can be used.

$$\begin{matrix}Y_3 = X_3 \;\;\;\;\;\;\;\;\;\\
Y_2 = X_3 \bigoplus X_2 \\
Y_1 = X_2 \bigoplus X_1\\
Y_0 = X_1 \bigoplus X_0 \\ \end{matrix} $$

That is, the MSB (Y3) is same for both binary and Gray codes. The next bit (Y2) is the XOR of previous bit (X3) and the present bit (X2) of the binary code and so on. Following example illustrates this concept using a 6-bit code.

Converting from Gray to Natural Binary:

To convert a Gray code representation (Y3 Y2 Y1 Y0) to binary code (X3 X2 X1 X0), following method can be used.

$$ \begin{matrix}
X_3 = Y_3 \;\;\;\;\;\;\;\;\;\\
X_2 = Y_2 \bigoplus X_3 \\
X_1 = Y_1 \bigoplus X_2\\
X_0 = Y_0 \bigoplus X_1 \\
\end{matrix} $$

That is, the MSB (X3) of binary code is same as that of gray code. The next bit (X2) is the XOR of previous result (X3) and the present bit (Y2) of the gray code and so on. Following example illustrates this concept using 6-bit code.

The following table illustrates the conversion for a three bit system.

Matlab Code:

Matlab Code to convert decimal values directly to Gray

function [grayCoded]=dec2gray(decimalInput)
    [rows,cols]=size(decimalInput);
    grayCoded=zeros(rows,cols);
    for i=1:rows
        for j=1:cols
            grayCoded(i,j)=bitxor(bitshift(decimalInput(i,j),-1),decimalInput(i,j));
        end
    end
end

Matlab Code to convert Gray to decimal values

function [decimal]=gray2dec(grayInput)
    grayInput=uint8(grayInput); %Force datatype to uint8
    [rows,cols]=size(grayInput);
    decimal=zeros(rows,cols);
    for i=1:rows
        for j=1:cols
            temp = bitxor(grayInput(i,j),bitshift(grayInput(i,j),-8));
            temp = bitxor(temp,bitshift(temp,-4));
            temp = bitxor(temp,bitshift(temp,-2));
            temp = bitxor(temp,bitshift(temp,-1));
            decimal(i,j) = temp;
        end
    end
end

Sample Run:

>> decimalInput=[0 1 2 3 4 5 6 7]
decimalInput = 0 1 2 3 4 5 6 7
>> graycoded=dec2gray(decimalInput)
graycoded = 0 1 3 2 6 7 5 4
>> graycoded=gray2dec(graycoded)
graycoded = 0 1 2 3 4 5 6 7

See also:

[1] Oversampling, ADC – DAC Conversion,pulse shaping and Matched Filter
[2] Bandpass Sampling
[3]Baseband or Intermediate Sampling