Generating sawtooth waveform

I am trying to generate a sawtooth waveform between 0 and 1 which would have a frequency upto 200 kHz. I run this piece of code within a Matlab function block - it works fine up to 10 kHz, but higher than that frequency it doesn't give the desired waveform.

For example, at F = 40 kHz, I get the right shape but it's peak is not at 1 anymore. At 50 kHz, I do not get a clean sawtooth wave anymore where all the triangles are between 0 and 1, it jumps up and gets shifted up a little every now and then (please see pic.2).

Can someone tell me where I'm going wrong in my function?

function y = fcn(clk)

T = 1/40e3;

if(mod(clk,T)==0)
y = 0;

else
y = (clk-floor(clk/T)*T)/T;
end


• Maybe you need a tighter timestep? Commented Dec 1, 2022 at 18:56
• @aconcernedcitizen No that doesn't do it - I get why it's not working : because the mod(clk,T) gives a 0 when it's not supposed to I think if I use smaller time steps? I'm not sure how to fix it
– SM32
Commented Dec 1, 2022 at 18:59
• I don't understand: when you say "that doesn't do it" you mean you tried imposing a tighter timestep and it failed (if yes, how?). But later on you say "I think if I use smaller time steps?" which means you haven't tried imposing them in the first place, so why do you say it doesn't work? Also, if you have the mod() function then you don't need the x-floor(x) since that's how it's implemented (or something like that). Just use the function mod(), directly. Commented Dec 1, 2022 at 19:02
• @aconcernedcitizen No that doesn't do it - I did try using a smaller time step for higher frequencies, it still gives irregular sawtooth waves as in the pic above. I don't know how to fix this problem and the other where it isn't going up to 1, it falls to 0 before that.
– SM32
Commented Dec 1, 2022 at 19:05
• Have you tried mod(), directly? Commented Dec 1, 2022 at 19:05

y = (clk-floor(clk/T)*T)/T;


This code is probably creating a rounding error every once in a while and causing the floor not to work. Change the function to something that doesn't have a rounding error.

In fact its probably this part of the function that doesn't work.

floor(clk/T)


create a block with just that in it and see what the output looks like.

You might also be able to dispense of the floor and if then statment and just do this:

y = mod(clk,T)


and then scale it vertically if needed.