In this post I will talk about the data types part of the SystemC library.
Here is a list of content if you want to jump to a particular subject:
1. Fixedprecision integer types
1.1 sc_int
1.2 sc_uint
1.3 sc_bigint and sc_biguint
2. Logic and arbitrary width vector types
2.1 sc_logic
2.2 sc_lv<W>
3. FixedPoint Types
3.1 FixedPoint Parameters
3.1.1. World length (WL) and Integer Word Length (IWL)
3.1.2. Quantization Mode (QUAT)
3.1.2.1. Quantization for Signed FixedPoint Numbers
3.1.2.2. Quantization for Unsigned FixedPoint Numbers
3.1.3. Overflow Mode (OVFW) and Number of Saturation Bits (NBITS)
3.1.3.1. Overflow for Signed FixedPoint Numbers
3.1.3.2. Overflow for Unsigned FixedPoint Numbers
3.2 FixedPoint Classes
1. Fixedprecision integer types
In hardware world it is mandatory to use a precise number of bits when representing a number. This is because the HDL code will be synthesized to a physical implementation in silicon where every register bit takes up area and this costs money.
For example, one might declare in Verilog a 10 bit counter like this:
1  reg[9:0] counter 
In the software world there is no requirement for such a fine granularity. In the best case we have usually a 8 bit granularity when it comes to data types widths in bits. For example some of the basic data types that we have natively in C language are:
 char– width: >= 8
 int– width: >= 16
 long– width: >= 32
 etc
SystemC comes with a solution for this problem with four parameterized classes.
Signed  Unsigned  
LENGTH ≤ 64  sc_int<LENGTH>  sc_uint<LENGTH> 
LENGTH > 64  sc_bigint<LENGTH>  sc_biguint<LENGTH> 
Let’s see some usage examples.
1.1. sc_int
First, we can take a look at an example for sc_int class:
1 2 3 4 5 6 7 8 9  //we can initialize the variable by direct assignment sc_int<3> my_a = 1; //we can initialize the variable via its constructor sc_int<4> my_b(2); sc_int<4> result = my_a + my_b; cout << "sc_int: " << my_a << " + " << my_b << " = " << result << endl; 
We can use different styles for initializing our variables. For the code above we will get the following output:
1  sc_int: 1 + 2 = 1 
1.2. sc_uint
In the example for sc_uint class we can easily see the overflow effect as we do not have enough bits in the result to store the correct result of the operation:
1 2 3 4 5 6 7  sc_uint<3> my_a = 3; sc_uint<4> my_b(15); //there is an overflow here as we do not have enough bits to store the correct result sc_uint<4> result = my_a + my_b; cout << "sc_uint: " << my_a << " + " << my_b << " = " << result << endl; 
The output:
1  sc_uint: 3 + 15 = 2 
1.3. sc_bigint and sc_biguint
Of course, the other two classes, sc_bigint and sc_biguint are used in exactly the same manner. You can even combine them:
1 2 3 4 5 6 7 8  sc_biguint<128> my_a = 11; sc_bigint<128> my_b = 3; sc_bigint<128> result = my_a / my_b; //even if the result is 3.666 we are dealing with integers //so the result is truncated down to the closest integer value cout << "sc_biguint & sc_bigint: " << my_a << " / " << my_b << " = " << result << endl; 
As in all integer operations, the result is rounded down to the closest integer:
1  sc_biguint & sc_bigint: 11 / 3 = 3 
You can find all these examples on EDA Playground.
Choosing between native C++ types and these SystemC types must be done with care as SystemC types comes with a slower simulation comparing to native C++ types. Here are some guidelines for you to follow when deciding what types to use:
 use these SystemC types if in the end you will use synthesis on your SystemC code
 use these SystemC types to have the overflow effect out of the box
 use the proper SystemC class based on length and signed/unsigned as in the table from the beginning of this chapter
2. Logic and arbitrary width vector types
In a HDL like Verilog or VHDL, despite the fact that they are used for describing digital logic, a modeled bit of information can have more than just two values: ‘0’ or ‘1’. Most commonly you will see that, for example in Verilog, a register might also take some other values like:
 High Impedance – to model a physical wire left unconnected. This is represented as value ‘z’
 Unknown – to model a physical wire which which has an unknown value due to several reasons – one reason being that is can have two driving sources, or that the wire was never assigned. This is represented as value ‘x’
Such multivalue logic is modeled in SystemC by two classes:
 sc_logic – for modeling one bit of information with its four states: ‘0’, ‘1’, ‘x’ and ‘z’
 sc_lv<W> – a parameterized class to model a logic vector
For modeling a purely boolean representation of a bit (two values) there are other two classes:
 sc_bit (deprecated) – for modeling one bit of information with its two states: ‘0’ and ‘1’
 sc_bv
– a parameterized class to model a bit vector
Let’s see some usage examples of these classes.
2.1. sc_logic
There are a lot of ways to initialize a sc_logic class:
 using predefined constants: SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z
 using boolean values: true, false
 using special characters: ‘0’, ‘1’, ‘X’ or ‘Z’
 using sc_logic_value_t type: Log_0, Log_1, Log_X or Log_Z
Here is an example that you can also try it for yourself on EDA Playground:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19  //one can use the values of constants SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z sc_logic val_0 = SC_LOGIC_0; //once can use the boolean values 'true' or 'false' to initialize a sc_logic class sc_logic val_1(true); //one can use the values of the type sc_logic_value_t: Log_0, Log_1, Log_X or Log_Z sc_logic val_x(Log_X); //one can use even the characters '0', '1', 'X' or 'Z' sc_logic val_z('Z'); sc_logic result_a = val_0 & val_1; sc_logic result_b = val_0  val_1; sc_logic result_c = val_x ^ val_z; cout << val_0 << " & " << val_1 << " = " << result_a << endl; cout << val_0 << "  " << val_1 << " = " << result_b << endl; cout << val_x << " ^ " << val_z << " = " << result_c << endl; 
The output is:
1 2 3  0 & 1 = 0 0  1 = 1 X ^ Z = X 
There are many operators overloaded for this class so you should be able to cover all your scenarios.
I extracted from the LRM some truth tables for most common operations:





2.2. sc_lv<W>
sc_lv<W> is a template class representing a finite logic vector – lv in the name of the class stands for “logic vector”. This class inherits from sc_lv_base so you might want to take a look at this one also to see what API is available for you.
Let’s see some examples on how to use this class:
1 2 3 4 5 6 7 8 9  sc_lv<4> a_vector = "1101"; sc_lv<4> b_vector(0b1110); //normal bitwise operations can be performed in logic vectors sc_lv<4> c_vector = a_vector & b_vector; cout << "a_vector: " << a_vector << endl; cout << "b_vector: " << b_vector << endl; cout << "c_vector: " << c_vector << endl; 
sc_lv<W> comes with lots of constructors so you can initialize it in the most intuitive way for you.
SystemC developers took fool advantage of the operator overload so normal bitwise operations can be performed on the logic vectors.
Here is the output of the example from above:
1 2 3  a_vector: 1101 b_vector: 1110 c_vector: 1100 
You can run the example for yourself on EDA Playground.
One other interesting aspect to mention here is that the base class, sc_lv_base, has a lot of useful functions. Here is an example with most of the available functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21  sc_lv<4> a_vector = "1101"; cout << "a_vector: " << a_vector << endl; //Bitwise rotations cout << "a_vector.lrotate(1): " << a_vector.lrotate(1) << endl; cout << "a_vector.rrotate(1): " << a_vector.rrotate(1) << endl; //Bitwise reverse cout << "a_vector.reverse(): " << a_vector.reverse() << endl; //Bit selection cout << "a_vector[3]: " << a_vector[3] << endl; //Part selection cout << "a_vector(3,1): " << a_vector(3,1) << endl; cout << "a_vector.range(3,1): " << a_vector.range(3,1) << endl; //Reduce functions //<OPERATION>_reduce() – where <OPERATION> can be: and, nand, or, nor, xor, xnor cout << "a_vector.and_reduce(): " << a_vector.and_reduce() << endl; 
And the output:
1 2 3 4 5 6 7 8  a_vector: 1101 a_vector.lrotate(1): 1011 a_vector.rrotate(1): 1101 a_vector.reverse(): 1011 a_vector[3]: 1 a_vector(3,1): 101 a_vector.range(3,1): 101 a_vector.and_reduce(): 0 
You can run the example for yourself on EDA Playground.
3. FixedPoint Types
Before you continue reading you must make sure you know how fixedpoint numbers are represented in binary.
You can take a look at this short YouTube video explaining all you need to know about fixedpoint number representation in binary.
IMPORTANT:
In order to have access to fixed point data type classes you must define SC_INCLUDE_FX before you include systemc.h file.
This can be achieved from command line by adding this argument to the compiler: DSC_INCLUDE_FX
3.1 FixedPoint Parameters
The SystemC classes used to model the fixed point types have five parameters:
 Word Length (WL)
 Integer Word Length (IWL)
 Quantization Mode (QUAT)
 Overflow Mode (OVFW)
 Number of Saturation Bits (NBITS)
In the next sections of this chapter I will try to explain how these parameters are used.
3.1.1. Word Length (WL) and Integer Word Length (IWL)
World Length represents how many bits are used to represent the entire number – must be positive.
Integer Word Length represents how many bits, out of Word Length, are used to represent the integer part – it can have any integer value.
There are three scenarios for a fixed point representation based on the relationship between WL and IWL:
Scenario #1: 0 <= IWL <= WL
This is the easiest scenario to understand. A representation of a number where WL is 5 and IWL is 3 is this:
i  i  i  f  f 
i = integer bit, f = fractional bit 
Let’s try to understand the range.
If we have to represent an unsigned number the lowest number, represented in binary, is 000.00 and in decimal is 0.
The biggest number, represented in binary, is 111.11 and in decimal is 7.75
If we have to represent a signed number, two’s complement representation is used, so the lowest number in binary is 100.00 and in decimal is 4.
The biggest number, represented in binary, is 011.11 and in decimal is 3.75
Scenario #2: WL < IWL
In this scenario we have more bits to represent the integer part than there are to represent the entire number. Strange right?
In the actual representation the remaining bits (IWL – WL) are all zero.
A representation of a number where WL is 5 and IWL is 7 is this:
i  i  i  i  i  0  0 
i = integer bit 
Let’s try to understand the range.
If we have to represent an unsigned number the lowest number, represented in binary, is 0000000 and in decimal is 0.
The biggest number, represented in binary, is 1111100 and in decimal is 124
If we have to represent a signed number, two’s complement representation is used, so the lowest number in binary is 1000000 and in decimal is 64.
The biggest number, represented in binary, is 0111100 and in decimal is 60
Scenario #3: IWL < 0 < WL
This is the hardest scenario to understand.
In this scenario we have a negative number of bits to represent the integer part. These bits will actually be a copy of the sign bit, for signed representations and zero for unsigned representations.
A representation of a signed number where WL is 5 and IWL is 2 is this:
s  s  f  f  f  f  f 
s = sign bit, f = fractional bit 
A representation of an unsigned number where WL is 5 and IWL is 2 is this:
0  0  f  f  f  f  f 
f = fractional bit 
Let’s try to understand the range.
If we have to represent an signed number, two’s complement representation is used, so the lowest number, represented in binary, is .1110000 and in decimal is 0.125
The biggest number, represented in binary, is .0001111 and in decimal is 0.1171875
If we have to represent a unsigned number the lowest number in binary is .0000000 and in decimal is 0.
The biggest number, represented in binary, is .0011111 and in decimal is 0.2421875
3.1.2. Quantization Mode (QUAT)
Quantization Mode represents the way to handle the case when the precision of an assigned value exceeds the precision of a fixedpoint variable.
For example, let’s say that we have a fixed point number with WL = 4 and IWL = 2 and it is equal to 0.75 (decimal) and in binary 0011.
If we want to assign it to a fixed point number with WL = 3 and IWL = 2, quantization mode dictates how the rounding shall be performed.
1 2 3 4 5 6  //this number has two fractional bits sc_fixed<4,2> a = 0.75; //this number has only one fractional bit //quantization algorithm dictates what value b variable will have sc_fixed<3, 2> b = a; 
The quantization modes available in SystemC in the enum sc_q_mode and the possible values are listed in the table below.
Quantization mode  Name 
Rounding to plus infinity  SC_RND 
Rounding to zero  SC_RND_ZERO 
Rounding to minus infinity  SC_RND_MIN_INF 
Rounding to infinity  SC_RND_INF 
Convergent rounding  SC_RND_CONV 
Truncation  SC_TRN 
Truncation to zero  SC_TRN_ZERO 
Quantization modes 
3.1.2.1. Quantization for Signed FixedPoint Numbers
Each of the quantization modes available in sc_q_mode has a mathematical formula which is applied in order to do the quantization.
In order to understand those mathematical formulas you need to understand some terminology involved.
Higher precision number  x  x  x  x  x  x  x  x 
Lower precision number  x  x  x  x  x  
Flags  sR  R  R  R  lR  mR  D  D 
Flags at bit level applied for quantization algorithms 
The flags in the table above have the following meaning:
 x – a binary digit (0 or 1)
 sR – a sign bit
 R – the remaining bits
 lR – the least significant remaining bit
 mR – the most significant deleted bit
 D – the deleted bits
In the mathematical formulas of the quantization algorithms it is used a symbol r – which is the logical OR between all the bits with flag D.
The table below list all the available quantization modes and how is computed the value to be added to the lower precision numer.
Quantization mode  Expression to be added  Details 
SC_RND  mD  Add the most significant deleted bit to the remaining bits. 
SC_RND_ZERO  mD & (sR  r)  If the most significant deleted bit is 1, and either the sign bit or at least one other deleted bit is 1, add 1 to the remaining bits. 
SC_RND_MIN_INF  mD & r  If the most significant deleted bit is 1 and at least one other deleted bit is 1, add 1 to the remaining bits. 
SC_RND_INF  mD & (! sR  r)  If the most significant deleted bit is 1, and either the inverted value of the sign bit or at least one other deleted bit is 1, add 1 to the remaining bits. 
SC_RND_CONV  mD & (lR  r)  If the most significant deleted bit is 1, and either the least significant of the remaining bits or at least one other deleted bit is 1, add 1 to the remaining bits. 
SC_TRN  0  Copy the remaining bits. 
SC_TRN_ZERO  sR & (mD  r)  If the sign bit is 1, and either the most significant deleted bit or at least one other deleted bit is 1, add 1 to the remaining bits. 
Quantization handling for signed fixedpoint numbers 
Let’s see some examples for some of the quantization modes.
Rounding to plus infinity (SC_RND)
For this algorithm, the value to be added to the lower precision number is mD – most significant deleted bit.
1 2 3 4 5 6 7 8 9  //this number has 5 fractional bits sc_fixed<8,3> a = 2.3125; cout << " a in dec: " << a << ", a in bin: "<< a.to_bin() << endl; //this number has 2 fractional bits sc_fixed<5,3, SC_RND> b_sc_rnd = a; cout << "SC_RND  b in dec: " << b_sc_rnd << ", b in bin: "<< b_sc_rnd.to_bin() << endl; 
In this case mD is a[2] = 1 – bit index 2 counting from right to left.
So, b_sc_rnd before adding the value of the quantization algorithm is 0b101.10
Once we add quantization mode value we have b_sc_rnd = 0b101.11
1 2  a in dec: 2.3125, a in bin: 0b101.10110 SC_RND  b in dec: 2.25, b in bin: 0b101.11 
You can run the full example on EDA Playground.
Truncation (SC_TRN)
For this algorithm, the value to be added to the lower precision number is 0 so things are much simpler – this is the default quantization mode.
1 2 3 4 5 6 7 8 9  //this number has 5 fractional bits sc_fixed<8,3> a = 2.3125; cout << " a in dec: " << a << ", a in bin: "<< a.to_bin() << endl; //this number has 2 fractional bits sc_fixed<5,3, SC_TRN> b_sc_rnd = a; cout << "SC_RND  b in dec: " << b_sc_rnd << ", b in bin: "<< b_sc_rnd.to_bin() << endl; 
And the output is:
1 2  a in dec: 2.3125, a in bin: 0b101.10110 SC_TRN  b in dec: 2.5, b in bin: 0b101.10 
You can run the full example on EDA Playground.
3.1.2.1. Quantization for Unsigned FixedPoint Numbers
For unsigned numbers the flags are quite similar with the signed numbers with the only difference that sR no longer exists.
Higher precision number  x  x  x  x  x  x  x  x 
Lower precision number  x  x  x  x  x  
Flags  R  R  R  R  lR  mR  D  D 
Flags at bit level applied for quantization algorithms 
The table below list all the available quantization modes and how is computed the value to be added to the lower precision numer.
Quantization mode  Expression to be added  Details 
SC_RND  mD  Add the most significant deleted bit to the left bits. 
SC_RND_ZERO  0  Copy the remaining bits. 
SC_RND_MIN_INF  0  Copy the remaining bits. 
SC_RND_INF  mD  Add the most significant deleted bit to the left bits. 
SC_RND_CONV  mD & (lR  r)  If the most significant deleted bit is 1, and either the least significant of the remaining bits or at least one other deleted bit is 1, add 1 to the remaining bits. 
SC_TRN  0  Copy the remaining bits. 
SC_TRN_ZERO  0  Copy the remaining bits. 
Quantization handling for unsigned fixedpoint numbers 
3.1.3. Overflow Mode (OVFW) and Number of Saturation Bits (NBITS)
Overflow Mode represents the way to handle the case when the magnitude of an assigned value exceeds the magnitude of a fixedpoint variable.
For example, let’s say that we have a fixed point number with WL = 4 and IWL = 3 and it is equal to 5.5 (decimal) and in binary 0b1011.
If we want to assign it to a fixed point number with WL = 3 and IWL = 2 (maximum integer value is only 3), overflow mode dictates how the assignment shall be performed.
1 2 3 4 5 6  //this number has three integer bits sc_fixed<4,3> a = 5.5; //this number has two integer bits //overflow algorithm dictates what value b variable will have sc_fixed<3, 2> b = a; 
The overflow modes available in SystemC in the enum sc_o_mode and the possible values are listed in the table below.
Overflow Mode  Name 
Saturation  SC_SAT 
Rounding to zero  SC_SAT_ZERO 
Symmetrical saturation  SC_SAT_SYM 
Wraparound  SC_WRAP 
Sign magnitude wraparound  SC_WRAP_SM 
Overflow modes 
3.1.2.1. Overflow for Signed FixedPoint Numbers
Each of the overflow modes available in sc_o_mode has a mathematical formula which is applied in order to do the overflow.
In order to understand those mathematical formulas you need to understand some terminology involved.
Higher precision number  x  x  x  x  x  x  x  x  x  x 
Lower precision number  x  x  x  x  x  x  
Flags  sD  D  D  lD  sR  R(N)  R(lN)  R  R  lR 
Flags at bit level applied for overflow algorithms 
The flags in the table above have the following meaning:
 x – a binary digit (0 or 1)
 sD – a sign bit before overflow handling
 D – deleted bits
 lD – the least significant deleted bit
 sR – the bit on the MSB position of the result number. For the SC_WRAP_SM, 0 and SC_WRAP_SM, 1 modes, a distinction is made between the original value (sRo) and the new value (sRn) of this bit
 N – the saturated bits. Their number is equal to the n_bits argument minus 1
 lN – the least significant saturated bit
 R – the remaining bits
 lR – the least significant remaining bit
The table below list all the available overflow modes and how the result is computed.
Overflow mode  sR  N, lN  R, lR  Details 
SC_SAT  sD  !sD  The result number gets the sign bit of the original number. The remaining bits shall get the inverse value of the sign bit.  
SC_SAT_ZERO  0  0  All bits shall be set to zero.  
SC_SAT_SYM  sD  !sD  The result number shall get the sign bit of the original number. The remaining bits shall get the inverse value of the sign bit, except the least significant remaining bit, which shall be set to one.  
SC_WRAP, n_bits = 0  sR  x  All bits except for the deleted bits shall be copied to the result.  
SC_WRAP, n_bits = 1  sD  x  The result number shall get the sign bit of the original number. The remaining bits shall be copied from the original number.  
SC_WRAP, n_bits > 1  sD  !sD  x  The result number shall get the sign bit of the original number. The saturated bits shall get the inverse value of the sign bit of the original number. The remaining bits shall be copied from the original number. 
SC_WRAP_SM, n_bits = 0  lD  x ^ sRo ^ sRn  The sign bit of the result number shall get the value of the least significant deleted bit. The remaining bits shall be XORed with the original and the new value of the sign bit of the result.  
SC_WRAP_SM, n_bits = 1  sD  x ^ sRo ^ sRn  The result number shall get the sign bit of the original number. The remaining bits shall be XORed with the original and the new value of the sign bit of the result.  
SC_WRAP_SM, n_bits > 1  sD  !sD  x ^ lNo ^ !sD  The result number shall get the sign bit of the original number. The saturated bits shall get the inverse value of the sign bit of the original number. The remaining bits shall be XORed with the original value of the least significant saturated bit and the inverse value of the original sign bit. 
Overflow handling for signed fixedpoint numbers  
Let’s see an example.
Saturation (SC_SAT)
1 2 3 4 5 6 7 8 9  //this number has 4 integer bits sc_fixed<6,4> a = 7; cout << " a in dec: " << a << ", a in bin: "<< a.to_bin() << endl; //this number has 2 integer bits sc_fixed<4,2, SC_RND, SC_SAT> b_sc_sat = a; cout << "SC_SAT  b in dec: " << b_sc_sat << ", b in bin: "<< b_sc_sat.to_bin() << endl; 
In this case sR = sD so it is a[5] = 1.
R = !sD so it is 0.
1 2  a in dec: 7, a in bin: 0b1001.00 SC_SAT  b in dec: 2, b in bin: 0b10.00 
You can run the full example on EDA Playground.
3.1.2.2. Overflow for Unsigned FixedPoint Numbers
For unsigned numbers the flags are quite similar with the signed numbers with the only difference that sD, sR and lR no longer exists
Higher precision number  x  x  x  x  x  x  x  x  x  x 
Lower precision number  x  x  x  x  x  x  
Flags  D  D  D  lD  R(N)  R  R  R  R  R 
Flags at bit level applied for overflow algorithms 
The table below list all the available overflow modes and how the result is computed.
Overflow mode  N  R  Details 
SC_SAT  1 (overflow) 0 (underflow)  The remaining bits shall be set to 1 (overflow) or 0 (underflow).  
SC_SAT_ZERO  0  The remaining bits shall be set to 0.  
SC_SAT_SYM  1 (overflow) 0 (underflow)  The remaining bits shall be set to 1 (overflow) or 0 (underflow).  
SC_WRAP, n_bits = 0  x  All bits except for the deleted bits shall be copied to the result number.  
SC_WRAP, n_bits > 0  1  x  The saturated bits of the result number shall be set to 1. The remaining bits shall be copied to the result. 
SC_WRAP_SM  Not defined for unsigned numbers.  
Overflow handling for unsigned fixedpoint numbers  
3.2 FixedPoint Classes
Now that we have a clear understanding on how these fixedpoint numbers are represented we can take a look at the classes used for modeling fixedpoint numbers:
Let’s look over the differences between these classes.
The ones with “fast” are called limitedprecision fixedpoint types. They are faster than the other ones due to the fact that internal implementation takes use of the double primitive. These types can not be bigger than 53 bits.
The ones with “u” are unsigned.
The ones with “fixed” (past tense) are template classes and you can set all the parameters via variable declaration.
The other ones, with “fix” are regular C++ classes for which you can set the parameters via their constructors or via parameters context.
Let’s see an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  //first argument is WL and second argument is IWL sc_fixed<5,3> a_fixed = 1.75; cout << "a_fixed: " << a_fixed << endl; //for "fix" class you can specify via its constructor WL and IWL sc_fix a_fix(5, 3); a_fix = 1.75; cout << "a_fix: " << a_fix << endl; //however for "fix" classes the parameters can be set via a context sc_fxtype_params params(5,4); sc_fxtype_context context(params); //because we do not specify in b_fix constructor anything //the parameters are taken from the latest created context sc_fix b_fix; b_fix = 1.75; //b_fix is 1.5 because we configured the context with WL = 5 and IWL = 4 //leaving only one bit for fractional value cout << "b_fix: " << b_fix << endl; //even if we set the context earlier we can use the constructor to //hard code the arguments sc_fix c_fix(5,3); c_fix = 1.75; cout << "c_fix: " << c_fix << endl; 
This produce the following output:
1 2 3 4  a_fixed: 1.75 a_fix: 1.75 b_fix: 1.5 c_fix: 1.75 
Pay attention to the comments in the example as I tried to explain there how WL and IWL are attributed to each variable.
You can run the example on your own on EDAPlayground.
Next Lesson: Learning SystemC: #002 Module – sc_module
Previous Lesson: Learning SystemC: #000 Learning Materials and Initial Setup
reversed description for signed and unsigned fixed point representation for scenario 3. Also wrong sign for scenario 3: IWL< 0 < WL
You are right. thank you for the feedback! I did the changes in the article.
Under Section 3.1.2.1. Quantization for Signed FixedPoint Numbers, I think you meant mD and not mR.