Greetings, I'm designing a PWM module,with a 4 bits control. My specs,a 4-bits input control,input clock 50MHz, a single bit output PWM_o, when control changes,the duty cycle of PWM_o changes, like control = 0,PWM_o = 0;Control = 1,PWM_o = 6.25%...increase 6.25% each time(meaning that PWM_o should be wider and wider each time it outputs when Control increase).Desired result should be like marked with red rectangular in the first photo. I've tried so many version of ways to write it,I've noticed the common issue is that my Control changing too fast and I don't know how to delay it,I need to make the Control change after 16 pulses of input Clock,I just can't figure out how to do it... I don't understand how to delay a set of multiple bits of input... Here down below are my attempting,my attempting's output is almost correct,but just the issue with the Control.. Noted: Control is named as `value` in the codes; Attempting 1:

module pwm_c(clk,value,rst,PWM_out,counter,rst); input clk,rst; input [3:0] value; output PWM_out; reg PWM_out; output reg [3:0]counter; always@(posedge clk) begin if(!rst) counter <= 4'd0; else counter <= counter + 4'd1; end always@(counter or value) begin if(value == 4'd0) PWM_out = 1'b0; else if(value == 4'd1) PWM_out = (counter >=4'd1) ? 1'b0:1'b1; else if(value == 4'd2) PWM_out = (counter >=4'd2) ? 1'b0:1'b1; else if(value == 4'd3) PWM_out = (counter >= 4'd3) ? 1'b0:1'b1; else if(value == 4'd4) PWM_out = (counter >= 4'd4) ? 1'b0:1'b1; else if(value == 4'd5) PWM_out = (counter >= 4'd5) ? 1'b0:1'b1; else if(value == 4'd6) PWM_out = (counter >= 4'd6) ? 1'b0:1'b1; else if(value == 4'd7) PWM_out = (counter >= 4'd7) ? 1'b0:1'b1; else if(value == 4'd8) PWM_out = (counter >= 4'd8) ? 1'b0:1'b1; else if(value == 4'd9) PWM_out = (counter >= 4'd9) ? 1'b0:1'b1; else if(value == 4'd10) PWM_out = (counter >= 4'd10) ? 1'b0:1'b1; else if(value == 4'd11) PWM_out = (counter >= 4'd11) ? 1'b0:1'b1; else if(value == 4'd12) PWM_out = (counter >= 4'd12) ? 1'b0:1'b1; else if(value == 4'd13) PWM_out = (counter >= 4'd13) ? 1'b0:1'b1; else if(value == 4'd14) PWM_out = (counter >= 4'd14) ? 1'b0:1'b1; else if(value == 4'd15) PWM_out = (counter >= 4'd15) ? 1'b0:1'b1; else PWM_out = 1'b0; end endmodule |

Attempting 2:

module pwm_c(clk,value,rst,PWM_out,counter); input clk,rst; input wire [3:0] value; output PWM_out; reg PWM_out; output reg [3:0]counter; always@(posedge clk) begin if(!rst) counter <= 4'd0; else counter <= counter + 4'd1; end always@(counter or value) begin if(value == 4'd0) PWM_out = 1'b0; else if(value == 4'd1) PWM_out = counter<2; else if(value == 4'd2) PWM_out = counter<2; else if(value == 4'd3) PWM_out = counter<2; else if(value == 4'd4) PWM_out = counter<2; else if(value == 4'd5) PWM_out = counter<4; else if(value == 4'd6) PWM_out = counter<4; else if(value == 4'd7) PWM_out = counter<4; else if(value == 4'd8) PWM_out = counter<4; else if(value == 4'd9) PWM_out = counter<6; else if(value == 4'd10) PWM_out = counter<6; else if(value == 4'd11) PWM_out = counter<6; else if(value == 4'd12) PWM_out = counter<6; else if(value == 4'd13) PWM_out = counter<15; else if(value == 4'd14) PWM_out = counter<15; else if(value == 4'd15) PWM_out = counter<15; else PWM_out = 1'b0; end endmodule |

Attempting 3:

module pwm_c ( input clk,rst, input [3:0] value, output PWM_out, output reg [3:0]counter ); always@(posedge clk) begin if(!rst) counter <= 4'd0; else counter <= counter + 4'd1; end assign PWM_out = (counter > value) ? 1'b1 : 1'b0; endmodule |

Try to register value when the counter runs over and compare (attemp 3) the registered value with counter.

Hallo wrote: > Try to register value when the counter runs over and compare (attemp 3) But the `value` is an `input`,I don't think that the `input` can be declared as a register.Or perhaps you can enlighten me... although,I still tried to use D-Flip Flops to delay the `input` ,but the result came out wrong...and error. My DFF attempting looks like this:

always@(posedge clk) begin if(!rst) DFF1<=0; DFF2<=0; DFF3<=0; else DFF1<=value; DFF2<=DFF1; DFF3<=DFF2; end assign DFF_out <= DFF3; |

```
So far,using DFF is the only way I could think of to delay the
input...But it came out nothing...
>the registered value with counter.
Do you mean compare the registered value with counter?
```

Smith like:

reg [3:0] value_dly; always_ff@(posedge clk) begin if(!rst) begin value_dly<=4'h0; end else if (counter == 4'hf) begin value_dly <= value; end end assign PWM_out = (counter > value_dly) ? 1'b1 : 1'b0; |

Code not tested, is also not complete solution but should point into right direction...

It's also hard to say what really should happen since value changes more frequently than the counter run over. What should happen when value changes from 0 to 3 and then stay stable for 4*16 clock cycles?

Hallo wrote: > Smith like: >

> reg [3:0] value_dly; > always_ff@(posedge clk) begin > if(!rst) begin > value_dly<=4'h0; > end else if (counter == 4'hf) begin > value_dly <= value; > end > end > > assign PWM_out = (counter > value_dly) ? 1'b1 : 1'b0; > |

> > Code not tested, is also not complete solution but should point into > right direction... I know your idea and I thought about this as well and used a 8bits counter to delay as well,but the problem remain...it won't actually delay the input value,instead it make the counter stop at the value...

always@(posedge clk) begin if(!rst) begin counter<=8'd0; end else if(counter == 8'd15) begin delay<=value; end else begin counter <= counter + 8'd1; end end |

I even tried the much more simpler way to express the PWM_out result,but the input value issue still remain...it still changing too fast,it won't wait till 16 pulses of clock before change...

module pwm_c ( input clk; input [3:0]value; output counter,pwm; reg [3:0]counter=0; ); reg pwm; always @(posedge clk) begin counter=counter+1; if(counter<=value/2) pwm=1; else pwm=0; if(counter>=15) counter=0; end endmodule |

Hallo wrote: > It's also hard to say what really should happen since value changes more > frequently than the counter run over. What should happen when value > changes from 0 to 3 and then stay stable for 4*16 clock cycles? No,The first attachment is what I'm trying to show,that the each value should wait for 16 clock cycles before going to the next,like; value = 0 and PWM_out = 0 and equal to 16 clock cycles then value changes to 1,PWM_out= almost 1 clock cycle and equal to 16 clock cycles then value changes to 2,PWM_out = 1 clock cycle...etc... Maybe I'll put it in this way,each `value` is equal to 16 clock cycles. PWM_out only output at counter==15,and value's 16 clock cycle. I've redraw the photo...maybe you'll be much more clearly. But noted,by continue to repeat,I meant that to when value changes to 4 ...PWM_out output equal to 4 clock cycles and value is equal to 16 clock cycles. I don't mean 0-1-2-3 to continue repeat but rather the clock cycles pattern.

:
Edited by User

Your new drawing and my proposal should fit very well If you would like to have every change of value been "processed", even value changes more often than the counter runs over you need an FIFO and push data in if value change and pull data out when the counter runs over.

Hallo wrote: > Your new drawing and my proposal should fit very well > > If you would like to have every change of value been "processed", even > value changes more often than the counter runs over you need an FIFO and > push data in if value change and pull data out when the counter runs > over. If your proposal will do what I wanted, But I only see data in in your proposal,How can I pull it out? I might need more hint,'cause I'm really stuck.

reg [3:0] value_dly; always_ff@(posedge clk) begin if(!rst) begin value_dly<=4'h0; end else if (counter == 4'hf) begin value_dly <= value; end //Here suppose to have a else begin counter <= counter + 4'h1; end , right? end assign PWM_out = (counter > value_dly) ? 1'b1 : 1'b0; |

then why mine doesn't work?

always@(posedge clk) begin if(!rst) begin counter<=8'd0; end else if(counter == 8'd15) begin delay<=value; end else begin counter <= counter + 8'd1; end end |

Okay I think I got it, here with an downward counter:

// Code your design here module pwm_c ( input clk,rst, input [3:0] value, output PWM_out, output reg [3:0]counter ); always@(posedge clk) begin if(!rst) counter <= 4'hf; else counter <= counter - 4'd1; end assign PWM_out = (counter < value) ? 1'b1 : 1'b0; endmodule |

If this is not okay you need to "invert" value:

// Code your design here module pwm_c ( input clk,rst, input [3:0] value, output PWM_out, output reg [3:0]counter ); always@(posedge clk) begin if(!rst) counter <= 4'h0; else counter <= counter + 4'd1; end wire [3:0]value_inv; assign value_inv = 4'hf-value; assign PWM_out = (counter <= value_inv) ? 1'b0 : 1'b1; endmodule |

Hallo wrote: > Added simulation screenshot Not Sure What I did wrong...but my simulation result is way different from yours...and so much wronger than before... I tried added your inverted code...

You change value with every clock cycle. Change of value must be proper specified and I just assumed now that it is only allowed to change when the counter runs over.

Hallo wrote: > You change value with every clock cycle. > Change of value must be proper specified and I just assumed now that it > is only allowed to change when the counter runs over. Ok,I finally understood it,the change of value is what I should set it when I simulate it...and 16 clock cycles is what I should count and then set the value... So...It was never the code's problem... I've got stuck at this for days...THANK YOU SO MUCH.