axi_pwm_gen: Fix offset mechanism
Fix offset for pwms with different periods. The previous version was using an offset scheme based on pwm counter_0. By using a separate offset counter the user will not be constrained by pwm_0 period in regards with the offset of other pulses. In this version offset 0 is used to delay pwm 0 in regards to the offset counter. The offset counter will start after the load_config signal is asserted and all active pwm counters finish the previous cycle or by a software reset. The software reset should also be used when using external_sync.main
parent
a3e049ae03
commit
81320b6469
|
@ -39,7 +39,7 @@ module axi_pwm_gen #(
|
|||
parameter ID = 0,
|
||||
parameter ASYNC_CLK_EN = 1,
|
||||
parameter N_PWMS = 1,
|
||||
parameter PWM_0_EXT_SYNC = 0,
|
||||
parameter PWM_EXT_SYNC = 0,
|
||||
parameter EXT_ASYNC_SYNC = 0,
|
||||
parameter PULSE_0_WIDTH = 7,
|
||||
parameter PULSE_1_WIDTH = 7,
|
||||
|
@ -49,6 +49,7 @@ module axi_pwm_gen #(
|
|||
parameter PULSE_1_PERIOD = 10,
|
||||
parameter PULSE_2_PERIOD = 10,
|
||||
parameter PULSE_3_PERIOD = 10,
|
||||
parameter PULSE_0_OFFSET = 0,
|
||||
parameter PULSE_1_OFFSET = 0,
|
||||
parameter PULSE_2_OFFSET = 0,
|
||||
parameter PULSE_3_OFFSET = 0)(
|
||||
|
@ -93,14 +94,13 @@ module axi_pwm_gen #(
|
|||
|
||||
// internal registers
|
||||
|
||||
reg sync_0;
|
||||
reg sync_1;
|
||||
reg sync_2;
|
||||
reg sync_3;
|
||||
reg sync_active_0;
|
||||
reg sync_active_1;
|
||||
reg sync_active_2;
|
||||
reg sync_active_3;
|
||||
reg sync_0 = 1'b0;
|
||||
reg sync_1 = 1'b0;
|
||||
reg sync_2 = 1'b0;
|
||||
reg sync_3 = 1'b0;
|
||||
reg [31:0] offset_cnt = 32'd0;
|
||||
reg offset_alignment = 1'b0;
|
||||
reg pause_cnt_d = 1'b0;
|
||||
|
||||
// internal signals
|
||||
|
||||
|
@ -118,10 +118,12 @@ module axi_pwm_gen #(
|
|||
wire [127:0] pwm_width_s;
|
||||
wire [127:0] pwm_period_s;
|
||||
wire [127:0] pwm_offset_s;
|
||||
wire [ 31:0] pwm_counter[0:N_PWMS-1];
|
||||
wire [ 31:0] pwm_counter[0:3];
|
||||
wire load_config_s;
|
||||
wire pwm_gen_resetn;
|
||||
wire ext_sync_s;
|
||||
wire pause_cnt;
|
||||
wire offset_alignment_ready;
|
||||
|
||||
assign up_clk = s_axi_aclk;
|
||||
assign up_rstn = s_axi_aresetn;
|
||||
|
@ -140,6 +142,7 @@ module axi_pwm_gen #(
|
|||
.PULSE_1_PERIOD (PULSE_1_PERIOD),
|
||||
.PULSE_2_PERIOD (PULSE_2_PERIOD),
|
||||
.PULSE_3_PERIOD (PULSE_3_PERIOD),
|
||||
.PULSE_0_OFFSET (PULSE_0_OFFSET),
|
||||
.PULSE_1_OFFSET (PULSE_1_OFFSET),
|
||||
.PULSE_2_OFFSET (PULSE_2_OFFSET),
|
||||
.PULSE_3_OFFSET (PULSE_3_OFFSET))
|
||||
|
@ -162,6 +165,59 @@ module axi_pwm_gen #(
|
|||
.up_rdata (up_rdata_s),
|
||||
.up_rack (up_rack_s));
|
||||
|
||||
// external sync
|
||||
|
||||
generate
|
||||
|
||||
reg ext_sync_m0 = 1'b1;
|
||||
reg ext_sync_m1 = 1'b1;
|
||||
|
||||
if (EXT_ASYNC_SYNC) begin
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
ext_sync_m0 <= 1'b1;
|
||||
ext_sync_m1 <= 1'b1;
|
||||
end else begin
|
||||
ext_sync_m0 <= (PWM_EXT_SYNC == 1) ? ext_sync : 0;
|
||||
ext_sync_m1 <= ext_sync_m0;
|
||||
end
|
||||
end
|
||||
assign ext_sync_s = ext_sync_m1;
|
||||
end else begin
|
||||
assign ext_sync_s = (PWM_EXT_SYNC == 1) ? ext_sync : 0;
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
// offset counter
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (offset_alignment) begin
|
||||
offset_cnt <= 32'd0;
|
||||
end else begin
|
||||
offset_cnt <= offset_cnt + 1'b1;
|
||||
end
|
||||
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
pause_cnt_d <= 1'b0;
|
||||
offset_alignment <= 1'b0;
|
||||
end else begin
|
||||
pause_cnt_d <= pause_cnt_d;
|
||||
|
||||
// when using external sync an offset alignment can be done only
|
||||
// after all pwm counters are paused(load_config)/reseated
|
||||
offset_alignment <= (load_config_s == 1'b1) ? 1'b1 :
|
||||
offset_alignment &
|
||||
(ext_sync_s ? 1'b1 : !offset_alignment_ready);
|
||||
end
|
||||
end
|
||||
|
||||
assign pause_cnt = ((pwm_counter[0] == 32'd1 ||
|
||||
pwm_counter[1] == 32'd1 ||
|
||||
pwm_counter[2] == 32'd1 ||
|
||||
pwm_counter[3] == 32'd1) ? 1'b1 : 1'b0);
|
||||
assign offset_alignment_ready = !pause_cnt_d & pause_cnt;
|
||||
|
||||
axi_pwm_gen_1 #(
|
||||
.PULSE_WIDTH (PULSE_0_WIDTH),
|
||||
.PULSE_PERIOD (PULSE_0_PERIOD))
|
||||
|
@ -177,38 +233,14 @@ module axi_pwm_gen #(
|
|||
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
sync_active_0 <= 1'b1;
|
||||
sync_0 <= 1'b1;
|
||||
end else begin
|
||||
sync_active_0 <= PWM_0_EXT_SYNC;
|
||||
if (sync_active_0) begin
|
||||
sync_0 <= ext_sync_s;
|
||||
end else begin
|
||||
sync_0 <= 1'b0;
|
||||
end
|
||||
sync_0 <= (offset_cnt == pwm_offset_s[31:0]) ? 1'b0 : 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
|
||||
reg ext_sync_m0 = 1'b1;
|
||||
reg ext_sync_m1 = 1'b1;
|
||||
|
||||
if (EXT_ASYNC_SYNC) begin
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
ext_sync_m0 <= 1'b1;
|
||||
ext_sync_m1 <= 1'b1;
|
||||
end else begin
|
||||
ext_sync_m0 <= ext_sync;
|
||||
ext_sync_m1 <= ext_sync_m0;
|
||||
end
|
||||
end
|
||||
assign ext_sync_s = ext_sync_m1;
|
||||
end else begin
|
||||
assign ext_sync_s = ext_sync;
|
||||
end
|
||||
|
||||
if (N_PWMS >= 2) begin
|
||||
axi_pwm_gen_1 #(
|
||||
.PULSE_WIDTH (PULSE_1_WIDTH),
|
||||
|
@ -225,19 +257,14 @@ module axi_pwm_gen #(
|
|||
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
sync_active_1 <= 1'b1;
|
||||
sync_1 <= 1'b1;
|
||||
end else begin
|
||||
sync_active_1 <= |pwm_offset_s[63:32];
|
||||
if (sync_active_1) begin
|
||||
sync_1 <= (pwm_counter[0] == pwm_offset_s[63:32]) ? 1'b0 : 1'b1;
|
||||
end else begin
|
||||
sync_1 <= 1'b0;
|
||||
end
|
||||
sync_1 <= (offset_cnt == pwm_offset_s[63:32]) ? 1'b0 : 1'b1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
assign pwm_1 = 1'b0;
|
||||
assign pwm_counter[1] = 32'd1;
|
||||
end
|
||||
|
||||
if (N_PWMS >= 3) begin
|
||||
|
@ -256,19 +283,14 @@ module axi_pwm_gen #(
|
|||
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
sync_active_2 <= 1'b1;
|
||||
sync_2 <= 1'b1;
|
||||
end else begin
|
||||
sync_active_2 <= |pwm_offset_s[95:64];
|
||||
if (sync_active_2) begin
|
||||
sync_2 <= (pwm_counter[0] == pwm_offset_s[95:64]) ? 1'b0 : 1'b1;
|
||||
end else begin
|
||||
sync_2 <= 1'b0;
|
||||
end
|
||||
sync_2 <= (offset_cnt == pwm_offset_s[95:64]) ? 1'b0 : 1'b1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
assign pwm_2 = 1'b0;
|
||||
assign pwm_counter[2] = 32'd1;
|
||||
end
|
||||
|
||||
if (N_PWMS >= 4) begin
|
||||
|
@ -287,19 +309,14 @@ module axi_pwm_gen #(
|
|||
|
||||
always @(posedge clk) begin
|
||||
if (pwm_gen_resetn == 1'b0) begin
|
||||
sync_active_3 <= 1'b1;
|
||||
sync_3 <= 1'b1;
|
||||
end else begin
|
||||
sync_active_3 <= |pwm_offset_s[127:96];
|
||||
if (sync_active_3) begin
|
||||
sync_3 <= (pwm_counter[0] == pwm_offset_s[127:96]) ? 1'b0 : 1'b1;
|
||||
end else begin
|
||||
sync_3 <= 1'b0;
|
||||
end
|
||||
sync_3 <= (offset_cnt == pwm_offset_s[127:96]) ? 1'b0 : 1'b1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
assign pwm_3 = 1'b0;
|
||||
assign pwm_counter[3] = 32'd1;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ set_property -dict [list \
|
|||
|
||||
ipgui::add_param -name "EXT_ASYNC_SYNC" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "External sync signal for pwm_0 is asynchronous" \
|
||||
"display_name" "External sync signal is asynchronous" \
|
||||
"tooltip" "NOTE: If active the ext_sync will be delayed 2 clock cycles." \
|
||||
"widget" "checkBox" \
|
||||
] [ipgui::get_guiparamspec -name "EXT_ASYNC_SYNC" -component $cc]
|
||||
|
@ -78,8 +78,22 @@ set_property -dict [list \
|
|||
"display_name" "Number of pwms" \
|
||||
] [ipgui::get_guiparamspec -name "N_PWMS" -component $cc]
|
||||
|
||||
ipgui::add_param -name "PWM_EXT_SYNC" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "External sync" \
|
||||
"tooltip" "NOTE: If active the whole pwm gen module will be waiting for the ext_sync to be set low. A load config or reset must be used before deaserting the ext_sync" \
|
||||
"widget" "checkBox" \
|
||||
] [ipgui::get_guiparamspec -name "PWM_EXT_SYNC" -component $cc]
|
||||
|
||||
ipgui::add_param -name "EXT_ASYNC_SYNC" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "External sync signal is asynchronous" \
|
||||
"tooltip" "NOTE: If active the ext_sync will be delayed 2 clock cycles." \
|
||||
"widget" "checkBox" \
|
||||
] [ipgui::get_guiparamspec -name "EXT_ASYNC_SYNC" -component $cc]
|
||||
|
||||
# Maximum 4 pwms
|
||||
for {set i 1} {$i < 4} {incr i} {
|
||||
for {set i 0} {$i < 4} {incr i} {
|
||||
ipgui::add_param -name "PULSE_${i}_WIDTH" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "PULSE $i width" \
|
||||
|
@ -106,14 +120,6 @@ for {set i 1} {$i < 4} {incr i} {
|
|||
] \
|
||||
[ipx::get_user_parameters PULSE_${i}_PERIOD -of_objects $cc]
|
||||
|
||||
if { $i == 1 } {
|
||||
ipgui::add_param -name "PWM_0_EXT_SYNC" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "Main pwm(1) sync" \
|
||||
"tooltip" "NOTE: If active the whole pwm gen module will be waiting for the ext_sync to be set high." \
|
||||
"widget" "checkBox" \
|
||||
] [ipgui::get_guiparamspec -name "PWM_0_EXT_SYNC" -component $cc]
|
||||
} else {
|
||||
ipgui::add_param -name "PULSE_${i}_OFFSET" -component $cc -parent $page0
|
||||
set_property -dict [list \
|
||||
"display_name" "PULSE ${i} offset" \
|
||||
|
@ -127,7 +133,6 @@ for {set i 1} {$i < 4} {incr i} {
|
|||
] \
|
||||
[ipx::get_user_parameters PULSE_${i}_OFFSET -of_objects $cc]
|
||||
}
|
||||
}
|
||||
|
||||
for {set i 1} {$i < 4} {incr i} {
|
||||
adi_set_ports_dependency "pwm_$i" \
|
||||
|
@ -135,7 +140,7 @@ for {set i 1} {$i < 4} {incr i} {
|
|||
}
|
||||
|
||||
adi_set_ports_dependency "ext_sync" \
|
||||
"(spirit:decode(id('MODELPARAM_VALUE.PWM_0_EXT_SYNC')) == 1)"
|
||||
"(spirit:decode(id('MODELPARAM_VALUE.PWM_EXT_SYNC')) == 1)"
|
||||
|
||||
set_property driver_value 0 [ipx::get_ports -filter "direction==in" -of_objects $cc]
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ module axi_pwm_gen_regmap #(
|
|||
parameter PULSE_2_PERIOD = 10,
|
||||
parameter PULSE_3_PERIOD = 10,
|
||||
parameter PULSE_0_EXT_SYNC = 0,
|
||||
parameter PULSE_0_OFFSET = 0,
|
||||
parameter PULSE_1_OFFSET = 0,
|
||||
parameter PULSE_2_OFFSET = 0,
|
||||
parameter PULSE_3_OFFSET = 0)(
|
||||
|
@ -92,7 +93,7 @@ module axi_pwm_gen_regmap #(
|
|||
reg [31:0] up_pwm_period_1 = PULSE_1_PERIOD;
|
||||
reg [31:0] up_pwm_period_2 = PULSE_2_PERIOD;
|
||||
reg [31:0] up_pwm_period_3 = PULSE_3_PERIOD;
|
||||
reg [31:0] up_pwm_offset_0 = 32'd0;
|
||||
reg [31:0] up_pwm_offset_0 = PULSE_0_OFFSET;
|
||||
reg [31:0] up_pwm_offset_1 = PULSE_1_OFFSET;
|
||||
reg [31:0] up_pwm_offset_2 = PULSE_2_OFFSET;
|
||||
reg [31:0] up_pwm_offset_3 = PULSE_3_OFFSET;
|
||||
|
@ -111,7 +112,7 @@ module axi_pwm_gen_regmap #(
|
|||
up_pwm_period_1 <= PULSE_1_PERIOD;
|
||||
up_pwm_period_2 <= PULSE_2_PERIOD;
|
||||
up_pwm_period_3 <= PULSE_3_PERIOD;
|
||||
up_pwm_offset_0 <= 32'd0;
|
||||
up_pwm_offset_0 <= PULSE_0_OFFSET;
|
||||
up_pwm_offset_1 <= PULSE_1_OFFSET;
|
||||
up_pwm_offset_2 <= PULSE_2_OFFSET;
|
||||
up_pwm_offset_3 <= PULSE_3_OFFSET;
|
||||
|
|
Loading…
Reference in New Issue