Skip to content

Commit 80ead96

Browse files
committed
[pwm] Correction to heartbeat mode
Heartbeat direction reversal was premature in the event of passing the target duty cycle (non-wrapping case). The heartbeat direction shall only be changed at the end of the 'X'+1 pulse cycles for the current duty cycle. Signed-off-by: Adrian Lees <[email protected]>
1 parent b1faaca commit 80ead96

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

hw/ip/pwm/rtl/pwm_chan.sv

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ module pwm_chan #(
120120
logic [CntDw-1:0] dc_htbt_d;
121121
logic [CntDw-1:0] dc_htbt_q;
122122
logic dc_htbt_end;
123-
// Asserted at the very end of the 'x' pulses cycles for which the heartbeat duty cycle
123+
// Asserted at the very end of the 'x' pulse cycles for which the heartbeat duty cycle
124124
// remains unchanged; this is our signal to update the duty cycle in heartbeat mode.
125125
assign dc_htbt_end = htbt_mode & update & blink_end;
126126

@@ -139,19 +139,24 @@ module pwm_chan #(
139139
assign dc_htbt_max = pos_htbt ? duty_cycle_b_i : duty_cycle_a_i;
140140
assign dc_htbt_min = pos_htbt ? duty_cycle_a_i : duty_cycle_b_i;
141141

142+
logic htbt_too_high;
143+
logic htbt_too_low;
144+
assign htbt_too_high = !htbt_falling & (dc_htbt_q >= dc_htbt_max);
145+
assign htbt_too_low = htbt_falling & (dc_htbt_q <= dc_htbt_min);
146+
147+
// Does the heartbeat need to change direction for the next interval of 'x' pulse cycles?
148+
logic htbt_reverse;
149+
assign htbt_reverse = |{htbt_too_high, htbt_too_low, dc_wrap_q}; // Overflowed/underflowed?
150+
142151
always_ff @(posedge clk_i or negedge rst_ni) begin
143152
if (!rst_ni) begin
144153
htbt_falling <= '0;
145154
end else if (clr_chan_cntr_i) begin
146155
// For proper initialization, set the initial htbt_falling whenever a register is updated,
147156
// as indicated by clr_chan_cntr_i
148157
htbt_falling <= !pos_htbt;
149-
end else if (htbt_mode) begin
150-
if (!htbt_falling && ((dc_htbt_q >= dc_htbt_max) || (dc_wrap && dc_htbt_end))) begin
151-
htbt_falling <= 1'b1; // duty cycle counts down
152-
end else if (htbt_falling && ((dc_htbt_q <= dc_htbt_min) || (dc_wrap && dc_htbt_end))) begin
153-
htbt_falling <= 1'b0; // duty cycle counts up
154-
end
158+
end else if (dc_htbt_end & htbt_reverse) begin // Reversing direction?
159+
htbt_falling <= !htbt_falling;
155160
end
156161
end
157162

@@ -160,7 +165,7 @@ module pwm_chan #(
160165
always_comb begin
161166
if (pattern_repeat) begin
162167
{dc_wrap, dc_htbt_d} = {1'b0, duty_cycle_a_i};
163-
end else if (htbt_falling) begin
168+
end else if (htbt_falling ^ htbt_reverse) begin
164169
{dc_wrap, dc_htbt_d} = {dc_wrap_q, dc_htbt_q} - (CntExtDw)'(blink_param_y_i) - 1'b1;
165170
end else begin
166171
{dc_wrap, dc_htbt_d} = {dc_wrap_q, dc_htbt_q} + (CntExtDw)'(blink_param_y_i) + 1'b1;

0 commit comments

Comments
 (0)