hobbskw
Junior Member level 3

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:
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.
Also, please ignore this part:
This is old and was written to implement a more stepping increase of the modulation index.
I should have deleted this bit.
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];
integer addr=0;
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
case (addr)
0: sineLUT[0] = 1413;
1: sineLUT[1] = 1574;
2: sineLUT[2] = 1728;
3: sineLUT[3] = 1875;
4: sineLUT[4] = 2011;
5: sineLUT[5] = 2134;
6: sineLUT[6] = 2242;
7: sineLUT[7] = 2333;
8: sineLUT[8] = 2405;
9: sineLUT[9] = 2457;
10: sineLUT[10] = 2489;
11: sineLUT[11] = 2500;
12: sineLUT[12] = 2489;
13: sineLUT[13] = 2457;
14: sineLUT[14] = 2405;
15: sineLUT[15] = 2333;
16: sineLUT[16] = 2242;
17: sineLUT[17] = 2134;
18: sineLUT[18] = 2011;
19: sineLUT[19] = 1875;
20: sineLUT[20] = 1728;
21: sineLUT[21] = 1574;
22: sineLUT[22] = 1413;
23: sineLUT[23] = 1250;
24: sineLUT[24] = 1087;
25: sineLUT[25] = 926;
26: sineLUT[26] = 772;
27: sineLUT[27] = 625;
28: sineLUT[28] = 489;
29: sineLUT[29] = 366;
30: sineLUT[30] = 258;
31: sineLUT[31] = 167;
32: sineLUT[32] = 95;
33: sineLUT[33] = 43;
34: sineLUT[34] = 11;
35: sineLUT[35] = 0;
36: sineLUT[36] = 11;
37: sineLUT[37] = 43;
38: sineLUT[38] = 95;
39: sineLUT[39] = 167;
40: sineLUT[40] = 258;
41: sineLUT[41] = 366;
42: sineLUT[42] = 489;
43: sineLUT[43] = 625;
44: sineLUT[44] = 772;
45: sineLUT[45] = 926;
46: sineLUT[46] = 1087;
47: sineLUT[47] = 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;
integer addr1 = 0;
integer addr2 = 16;
integer addr3 = 32;
// 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
integer deadtimer1P = 0;
integer deadtimer1N = 0;
integer deadtimer2P = 0;
integer deadtimer2N = 0;
integer deadtimer3P = 0;
integer deadtimer3N = 0;
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
begin // increment addr values
sineCount2 = 0;
if (addr == res)
begin
addr = 0;
//
end
else begin
addr = addr + 1;
end
if (addr1 == res)
begin
addr1 = 0;
end
else begin
addr1 = addr1 + 1;
end
if (addr2 == res)
begin
addr2 = 0;
end
else begin
addr2 = addr2 + 1;
end
if (addr3 == res)
begin
addr3 = 0;
end
else begin
addr3 = addr3 + 1;
end
end
// deadtime timer triggers / negative edge detection
if ((pwm1PT == 0) && (T1P == 0))
begin
T1P = 1;
deadtimer1N = deadtime;
end
if ((pwm1NT == 0) && (T1N == 0))
begin
T1N = 1;
deadtimer1P = deadtime;
end
if ((pwm2PT == 0) && (T2P == 0))
begin
T2P = 1;
deadtimer2N = deadtime;
end
if ((pwm2NT == 0) && (T2N == 0))
begin
T2N = 1;
deadtimer2P = deadtime;
end
if ((pwm3PT == 0) && (T3P == 0))
begin
T3P = 1;
deadtimer3N = deadtime;
end
if ((pwm3NT == 0) && (T3N == 0))
begin
T3N = 1;
deadtimer3P = deadtime;
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
if (deadtimer1P != 0)
begin
deadtimer1P <= deadtimer1P - 1;
end
if (deadtimer2P != 0)
begin
deadtimer2P <= deadtimer2P - 1;
end
if (deadtimer3P != 0)
begin
deadtimer3P <= deadtimer3P - 1;
end
if (deadtimer1N != 0)
begin
deadtimer1N <= deadtimer1N - 1;
end
if (deadtimer2N != 0)
begin
deadtimer2N <= deadtimer2N - 1;
end
if (deadtimer3N != 0)
begin
deadtimer3N <= deadtimer3N - 1;
end
// update the values of the sinewaves from the lookup table
sinewave = sineLUT[addr];
sinewave1 = (M*sineLUT[addr1]/1+D*(1-M))/1;
sinewave2 = (M*sineLUT[addr2]/1+D*(1-M))/1;
sinewave3 = (M*sineLUT[addr3]/1+D*(1-M))/1;
// 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 ---
Also, please ignore this part:
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: