# [SOLVED]How do you use variable real numbers?

Status
Not open for further replies.

#### hobbskw

##### Junior Member level 2 Greetings,
I am using a sinewave lookup table to generate an SPWM signal. I am adding a soft-start feature where the modulation index starts at 0, then after after 10 seconds it starts to gradually increase to 0.1 over 20 seconds. The problem is it does not like having a variable real number (except in simulations). My goal is to increment the modulation index by 0.0001 a thousand times, so it would be a very smooth increase. How can I change this to work? I have heard of the floating point and fixed point libraries. Are there any good examples of people using these to make variable real numbers?

Also, if it helps, the sinewaves themselves are integers. So in a sense my goal is really a variable integer, but the problem is I have to scale them down which requires multiplying by a decimal.

Here is the code:

Code:
timescale 1ns / 1ps

module sine_LUT(
input clk,
input rst_n,
output pwm1PT,
output pwm2PT,
output pwm3PT,
output pwm1NT,
output pwm2NT,
output pwm3NT,
output pwm1PB,
output pwm2PB,
output pwm3PB,
output pwm1NB,
output pwm2NB,
output pwm3NB,
output en_rst1H,
output en_pwr1H,
output en_rst1L,
output en_pwr1L,
output en_rst2H,
output en_pwr2H,
output en_rst2L,
output en_pwr2L,
output en_rst3H,
output en_pwr3H,
output en_rst3L,
output en_pwr3L
);

// initialize the sinewave lookup table
reg [12:0] sineLUT[0:47];
localparam res = 47; // res is the highest index number of the lookup table
localparam  D = 1250; // D is the midpoint
real M = 0; // M is the modulation index
always @* begin
0: sineLUT = 1413;
1: sineLUT = 1574;
2: sineLUT = 1728;
3: sineLUT = 1875;
4: sineLUT = 2011;
5: sineLUT = 2134;
6: sineLUT = 2242;
7: sineLUT = 2333;
8: sineLUT = 2405;
9: sineLUT = 2457;
10: sineLUT = 2489;
11: sineLUT = 2500;
12: sineLUT = 2489;
13: sineLUT = 2457;
14: sineLUT = 2405;
15: sineLUT = 2333;
16: sineLUT = 2242;
17: sineLUT = 2134;
18: sineLUT = 2011;
19: sineLUT = 1875;
20: sineLUT = 1728;
21: sineLUT = 1574;
22: sineLUT = 1413;
23: sineLUT = 1250;
24: sineLUT = 1087;
25: sineLUT = 926;
26: sineLUT = 772;
27: sineLUT = 625;
28: sineLUT = 489;
29: sineLUT = 366;
30: sineLUT = 258;
31: sineLUT = 167;
32: sineLUT = 95;
33: sineLUT = 43;
34: sineLUT = 11;
35: sineLUT = 0;
36: sineLUT = 11;
37: sineLUT = 43;
38: sineLUT = 95;
39: sineLUT = 167;
40: sineLUT = 258;
41: sineLUT = 366;
42: sineLUT = 489;
43: sineLUT = 625;
44: sineLUT = 772;
45: sineLUT = 926;
46: sineLUT = 1087;
47: sineLUT = 1250;
endcase;
end

// Wait for lookup table to initialize
integer start = 0;

// when active == 0, the SPWM signals will all be set to 0. This is for implementing safety features (UNFINISHED)
integer active = 1;

// these are used to detect the negative edges of he PWM signals, in order to trigger the deadtime timers
integer T1P = 0;
integer T1N = 0;
integer T2P = 0;
integer T2N = 0;
integer T3P = 0;
integer T3N = 0;

// the Side variable ensures the top and bottom mosfets take turns. One can not turn on twice in a row (UNFINISHED)
integer Side1 = 1;
integer Side2 = 1;
integer Side3 = 1;

// the magnitude of triangle and sinewave is from 0 to 2*D, with the midpoints being equal to D
integer triangle = D;
integer sinewave = D;

// updown tells what direction the triangle wave counter should be going
integer updown = 1;

// sineCount1 and 2 are counters for the fundamental frequency
// There are two: sineCount2 increments when sineCount1 reaches its limit
integer sineCount1 = 0;
integer sineCount2 = 0;

// each sinewave is shifted up by D. Addr1, 2, and 3 effectively phase shift the sinewaves
integer sinewave1 = D;
integer sinewave2 = D;
integer sinewave3 = D;

// Soft start timer
integer SS_counter1 = 0; // pulses (up to 100)
integer SS_counter2 = 0; // microseconds (up to 1000)
integer SS_counter3 = 0; // milliseconds (up to 200)
integer SS_counter4 = 0; // milliseconds (up to 1000)
integer SS_counter5 = 0; // seconds (up to 120)
// Soft start times and modulation indexes
integer SST1 = 5; // seconds for first increment
integer M1 = 0.01;
integer SST2 = 20; // seconds for second increment
integer M2 = 0.15;
integer SST3 = 30; // seconds for third increment
integer M3 = 0.3;
integer SST4 = 35; // seconds for fourth increment
integer M4 = 0.4;

// each mosfets has their own deadtime timer, which count down from the deadtime (100 = 1 microsecond)
integer deadtime = 100/2; // 100/2 = 500 ns

always@(posedge clk) begin
if(sineCount1 == 100)
begin // increment sineCount2
sineCount1 = 0;
sineCount2 = sineCount2 + 1;
end
sineCount1 = sineCount1 + 1;
if(sineCount2 == 333) // trial and error showed 333 gave a 60Hz fundamental frequency
sineCount2 = 0;
begin
//
end
else begin
end
begin
end
else begin
end
begin
end
else begin
end
begin
end
else begin
end
end

// deadtime timer triggers / negative edge detection
if ((pwm1PT == 0) && (T1P == 0))
begin
T1P = 1;
end
if ((pwm1NT == 0) && (T1N == 0))
begin
T1N = 1;
end
if ((pwm2PT == 0) && (T2P == 0))
begin
T2P = 1;
end
if ((pwm2NT == 0) && (T2N == 0))
begin
T2N = 1;
end
if ((pwm3PT == 0) && (T3P == 0))
begin
T3P = 1;
end
if ((pwm3NT == 0) && (T3N == 0))
begin
T3N = 1;
end

// when a PWM signal == 1, its T variable = 0, which allows the above if-statement to trigger when PWM signal == 0 (edge detection)
if (pwm1PT == 1)
begin
T1P = 0;
end
if (pwm1NT == 1)
begin
T1N = 0;
end
if (pwm2PT == 1)
begin
T2P = 0;
end
if (pwm2NT == 1)
begin
T2N = 0;
end
if (pwm3PT == 1)
begin
T3P = 0;
end
if (pwm3NT == 1)
begin
T3N = 0;
end

// decrement the deadtime timers if they are not == 0
begin
end
begin
end
begin
end
begin
end
begin
end
begin
end

// update the values of the sinewaves from the lookup table

// Soft start timer
// SS_counter1 == pulses
// SS_counter2 == microseconds
// SS_counter3 == milliseconds (for increasing M)
// SS_counter4 == milliseconds (for counting seconds)
// SS_counter5 == seconds
if (SS_counter1 < 101) // count 100 pulses
begin
SS_counter1 = SS_counter1 + 1; // increment pulses count
end
else begin
SS_counter1 = 0;
SS_counter2 = SS_counter2+1; // increment microseconds
end
if (SS_counter2 > 1000) // count 1000 microseconds
begin
SS_counter2 = 0;
SS_counter3 = SS_counter3 + 1; // increment milliseconds
SS_counter4 = SS_counter4 + 1; // increment milliseconds
end
if (SS_counter3 > 200) // count 200 milliseconds
begin
SS_counter3 = 0;
if (start && M<0.1) // increase to 0.1 over 20 seconds
begin
M = M + 0.0001;
end
end
if (SS_counter4 > 1000) // count 1000 milliseconds
begin
SS_counter4 = 0;
if (SS_counter5 < 15)
begin
SS_counter5 = SS_counter5 + 1; // increment seconds
end
end
if (SS_counter5 == 10)
begin
start = 1; // begin incrementing the modulation index at 10 seconds
end

// generation of the triangle wave
if (triangle == 2*D)
begin
updown <= -1;
end
if (triangle == 1)
begin
updown <= 1;
end
triangle <= triangle + updown;

end

// generation of SPWM signals
assign pwm1PT = ((start && deadtimer1P == 0)&&(sinewave1 > triangle))?1:0;
assign pwm2PT = ((start && deadtimer2P == 0)&&(sinewave2 > triangle))?1:0;
assign pwm3PT = ((start && deadtimer3P == 0)&&(sinewave3 > triangle))?1:0;
assign pwm1NT = ((start && deadtimer1N == 0)&&(sinewave1 < triangle))?1:0;
assign pwm2NT = ((start && deadtimer2N == 0)&&(sinewave2 < triangle))?1:0;
assign pwm3NT = ((start && deadtimer3N == 0)&&(sinewave3 < triangle))?1:0;
// each gate driver requires both the upper and lower gate signals to prevent short-circuits
assign pwm1PB = pwm1NT;
assign pwm2PB = pwm2NT;
assign pwm3PB = pwm3NT;
assign pwm1NB = pwm1PT;
assign pwm2NB = pwm2PT;
assign pwm3NB = pwm3PT;
// enable bits
assign en_rst1H = 1;
assign en_pwr1H = 1;
assign en_rst1L = 1;
assign en_pwr1L = 1;
assign en_rst2H = 1;
assign en_pwr2H = 1;
assign en_rst2L = 1;
assign en_pwr2L = 1;
assign en_rst3H = 1;
assign en_pwr3H = 1;
assign en_rst3L = 1;
assign en_pwr3L = 1;

endmodule

Here is the error it is producing: Line 283 is this: I divide by 1 because that seems to round/change the output of the equation to an integer, which is what sinewave1/2/3 are, thus getting rid of an earlier error from setting an integer to a real.
--- Updated ---

Code:
// Soft start times and modulation indexes
integer SST1 = 5; // seconds for first increment
integer M1 = 0.01;
integer SST2 = 20; // seconds for second increment
integer M2 = 0.15;
integer SST3 = 30; // seconds for third increment
integer M3 = 0.3;
integer SST4 = 35; // seconds for fourth increment
integer M4 = 0.4;`

This is old and was written to implement a more stepping increase of the modulation index.
I should have deleted this bit.

Last edited:

#### KlausST

##### Super Moderator
Staff member Hi,

I guess there are many thousands of good SPWM tutorials/example/code/videos...
Almost any manufacturer for inverter semiconductors provides application notes.
A lot of threads here in the forum and in the internet..

We don´t know MCU/PLD/PSoC, language, compiler ... so thus we can´t give detailed infromations.

I personally see no need for fixed point nor floating point variables here, because the PWM module will only accept integer values.

You say "softstart" but I as far as I understand you just increase frequency ... I guess it´s a better strategy to increase amplitude.

"Dividing" is the most complicated of the 4 basic operations. I avoid it - if possible.. and if not hardware divider available.
"making integer" for a fixed point value means just "shift" or "truncate".
In a PLD it´s nothing.. just using the signals you need.

My recommendation:
* then show what you want to do. Draw a sketch.
* then focus on one problem. Solve it. Test it.
* Then go to the next problem

Klaus

#### hobbskw

##### Junior Member level 2 After some messing around with the code I found a solution. Unfortunately there are timing errors with my implementation, but it removed the error I was struggling with. My solution was to change the values inside of the lookup table by dividing each by 1000. So I hard-coded those decimal values. I mean, I just typed a decimal point in each value of the lookup table, like I changed "0: sineLUT = 1413;" to "0: sineLUT = 1.413;". Then I increase M from 1 to 1000, so it is an integer now. I hope this is helpful to someone else who having this issue.

Status
Not open for further replies.