123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- /*
- * 3signal.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2025 Krzysztof Skrzynecki, Jakub Duchniewicz <j.duchniewicz@gmail.com>
- * SPDX-License-Identifier: TODO:
- */
- `default_nettype none
- module continous_pwm_gen#(
- parameter WIDTH = 16
- ) (
- input wire nrst, clk,
- input [WIDTH-1:0] period,
- input [WIDTH-1:0] delay,
- output wire [0:0] last_tick,
- output wire [0:0] mid_tick,
- output reg [0:0] pwm_out
- );
- reg [WIDTH-1:0] counter;
- wire [WIDTH-1:0] next_cnt=counter+1;
- wire [WIDTH-1:0] last_avail_cnt=period-1;
- // Counter logic
- always_ff @(posedge clk or negedge nrst) begin
- if (!nrst) begin
- counter <= 0;
- pwm_out <= 0;
- end else begin
- if(counter >= last_avail_cnt) begin
- counter <= 0;
- end else begin
- counter <= next_cnt;
- end
- if ((next_cnt<delay) || (counter>=last_avail_cnt)) begin
- pwm_out <= 0;
- end else begin
- pwm_out <= 1;
- end
- end
- end
- assign last_tick = (next_cnt>=period);
- assign mid_tick = ((next_cnt)==(period>>1));
- endmodule
- module single_shot_gen#(
- parameter WIDTH = 16
- )(
- input wire nrst, clk,
- input wire trigger,
- input [WIDTH-1:0] delay,
- input [WIDTH-1:0] duty,
- output reg [0:0] pwm_out
- );
- reg [WIDTH-1:0] counter;
- reg [0:0] is_counting;
- wire [WIDTH-1:0] next_cnt=counter+1;
- wire [WIDTH-1:0] period=delay+duty;
- //wire [WIDTH-1:0] last_avail_cnt=period-1;
- always_ff @(posedge clk or negedge nrst) begin
- if (!nrst) begin
- counter <= 0;
- is_counting <= 0;
- end else begin
- if (is_counting) begin
- if(counter+1 >= period) begin
- counter <= 0;
- is_counting <= 0;
- pwm_out <= 0;
- end else begin
- counter <= next_cnt;
- if (next_cnt>=delay) begin
- pwm_out <= 1;
- end else begin
- pwm_out <= 0;
- end
- end
- end else begin
- if (trigger) begin
- is_counting <= 1;
- if ((delay==0) && (duty!=0)) begin
- pwm_out <= 1;
- end
- end
- end
- end
- end
- endmodule
- module phase_delay#(
- parameter WIDTH = 16,
- parameter FORWARD_DATA_WIDTH = 16
- )(
- input wire nrst, clk,
- input wire in_trig,
- input [WIDTH-1:0] delay,
- input [FORWARD_DATA_WIDTH-1:0] in_data_fwd,
- output wire out_trig,
- output reg [FORWARD_DATA_WIDTH-1:0] out_data_fwd
- );
- reg [WIDTH-1:0] counter;
- reg [0:0] is_counting;
- reg [WIDTH-1:0] delay_latched;
- always_ff @(posedge clk or negedge nrst) begin
- if (!nrst) begin
- counter <= 0;
- is_counting <=0;
- delay_latched <=0;
- end else begin
- if (is_counting) begin
- if ((counter+1) >= delay_latched) begin
- counter <= 0;
- is_counting <= 0;
- end else begin
- counter <= counter+1;
- end
- end else begin
- if (in_trig) begin
- is_counting <= 1;
- out_data_fwd <= in_data_fwd;
- delay_latched <= delay;
- end
- end
- end
- end
- assign out_trig=((counter+1)>=delay) && is_counting;
- endmodule
- module pulse_train_gen#(
- parameter WIDTH = 16,
- parameter PULSE_COUNTER_WIDTH = 16
- )(
- input wire nrst, clk,
- input wire trigger,
- input [PULSE_COUNTER_WIDTH-1:0] npuls,
- input [WIDTH-1:0] period,
- input [WIDTH-1:0] duty,
- output reg [0:0] pwm_out
- );
- reg [WIDTH-1:0] counter;
- reg [0:0] is_counting;
- reg [PULSE_COUNTER_WIDTH-1:0] remaining_pulses;
- reg [WIDTH-1:0] period_local;
- reg [WIDTH-1:0] duty_local;
- wire [WIDTH-1:0] next_cnt = counter+1;
- always_ff @(posedge clk or negedge nrst) begin
- if (!nrst) begin
- counter <= 0;
- is_counting <= 0;
- pwm_out <=0;
- end else begin
- if (is_counting) begin
- if(next_cnt >= period) begin
- counter <= 0;
- if (remaining_pulses > 0) begin
- remaining_pulses <= remaining_pulses-1;
- pwm_out <= 1;
- end else begin
- pwm_out <= 0;
- is_counting <= 0;
- end
- end else begin
- counter <= next_cnt;
- if (next_cnt>=duty) begin
- pwm_out <= 0;
- end else begin
- pwm_out <= 1;
- end
- end
- end else begin
- if (trigger) begin
- if ((period>0) && (duty!=0) && (npuls>0)) begin
- pwm_out <= 1;
- remaining_pulses <= npuls-1;
- is_counting <= 1;
- counter <= 0;
- period_local <= period;
- duty_local <= duty;
- end
- end
- end
- end
- end
- endmodule
- typedef enum logic [1:0] {
- ODD_TRAIN_FORCE_OFF,
- ODD_TRAIN_ENA_CONTROL,
- ODD_TRAIN_FORCE_ON
- } odd_train_flag_t;
- module three_signal#(
- parameter FAST_PWM_WIDTH=8,
- parameter PULSE_COUNTER_WIDTH=8,
- parameter SLOW_PWM_WIDTH=14
- )(
- input wire nrst, clk,
- input [SLOW_PWM_WIDTH-1:0] period1,
- input [SLOW_PWM_WIDTH-1:0] delay1,
- input [SLOW_PWM_WIDTH-1:0] duty2,
- input [SLOW_PWM_WIDTH-1:0] delay2,
- input [FAST_PWM_WIDTH-1:0] period3,
- input [FAST_PWM_WIDTH-1:0] duty3,
- input [SLOW_PWM_WIDTH-1:0] delay3,//delay is wrt slow pwm, thus longer bit length
- input [PULSE_COUNTER_WIDTH-1:0] npuls3,
- input /*odd_train_flag_t*/ wire [1:0] odd_train_flag,
- input wire ena_odd_out3,
- output reg Out1,
- output reg Out2,
- output reg Out3
- );
- wire trigger_next_cycle;
- wire trigger_even_cycle;
- wire trigger_odd_cycle;
- wire [SLOW_PWM_WIDTH-1:0] delay3_part1;
- wire [SLOW_PWM_WIDTH-1:0] delay3_part234;
- assign delay3_part234 = delay3>>2;
- assign delay3_part1 = (delay3<4) ? 0 : (delay3 - (delay3_part234*3));
- continous_pwm_gen #(.WIDTH(SLOW_PWM_WIDTH)) pwm1(
- .nrst(nrst),
- .clk(clk),
- .period(period1),
- .delay(delay1),
- .last_tick(trigger_next_cycle),
- .mid_tick(trigger_even_cycle),
- .pwm_out(Out1)
- );
- single_shot_gen #(.WIDTH(SLOW_PWM_WIDTH)) pwm2(
- .nrst(nrst),
- .clk(clk),
- .trigger(trigger_next_cycle),
- .delay(delay2),
- .duty(duty2),
- .pwm_out(Out2)
- );
- wire trigger_delay_1_to_2;
- wire trigger_delay_2_to_3;
- wire trigger_delay_3_to_4;
- wire trigger_delay_4_to_pulse_train;
- localparam FORWARD_DATA_WIDTH = SLOW_PWM_WIDTH + PULSE_COUNTER_WIDTH + FAST_PWM_WIDTH + FAST_PWM_WIDTH;
- localparam DELAY_BITS_POS = PULSE_COUNTER_WIDTH + FAST_PWM_WIDTH + FAST_PWM_WIDTH;
- wire [FORWARD_DATA_WIDTH-1:0] data_1_to_2;
- wire [FORWARD_DATA_WIDTH-1:0] data_2_to_3;
- wire [FORWARD_DATA_WIDTH-1:0] data_3_to_4;
- wire [FORWARD_DATA_WIDTH-1:0] data_4_to_gen;
- assign trigger_odd_cycle =
- (odd_train_flag == ODD_TRAIN_ENA_CONTROL) ? trigger_next_cycle && ena_odd_out3 :
- (odd_train_flag == ODD_TRAIN_FORCE_ON) ? trigger_next_cycle :
- 0;
- wire [FAST_PWM_WIDTH-1:0] period3_gen;
- wire [FAST_PWM_WIDTH-1:0] duty3_gen;
- wire [PULSE_COUNTER_WIDTH-1:0] npuls3_gen;
- assign duty3_gen = data_4_to_gen[FAST_PWM_WIDTH-1:0];
- assign period3_gen = data_4_to_gen[FAST_PWM_WIDTH+FAST_PWM_WIDTH-1:FAST_PWM_WIDTH];
- assign npuls3_gen = data_4_to_gen[FAST_PWM_WIDTH+FAST_PWM_WIDTH+PULSE_COUNTER_WIDTH-1:FAST_PWM_WIDTH+FAST_PWM_WIDTH];
- phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_1of4(
- .nrst(nrst),
- .clk(clk),
- .in_trig(trigger_odd_cycle | trigger_even_cycle),
- .delay(delay3_part1),
- .in_data_fwd({delay3_part234, npuls3, period3, duty3}),
- .out_trig(trigger_delay_1_to_2),
- .out_data_fwd(data_1_to_2)
- );
- phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_2of4(
- .nrst(nrst),
- .clk(clk),
- .in_trig(trigger_delay_1_to_2),
- .delay(data_1_to_2[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
- .in_data_fwd(data_1_to_2),
- .out_trig(trigger_delay_2_to_3),
- .out_data_fwd(data_2_to_3)
- );
- phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_3of4(
- .nrst(nrst),
- .clk(clk),
- .in_trig(trigger_delay_2_to_3),
- .delay(data_2_to_3[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
- .in_data_fwd(data_2_to_3),
- .out_trig(trigger_delay_3_to_4),
- .out_data_fwd(data_3_to_4)
- );
- phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_4of4(
- .nrst(nrst),
- .clk(clk),
- .in_trig(trigger_delay_3_to_4),
- .delay(data_3_to_4[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
- .in_data_fwd(data_3_to_4),
- .out_trig(trigger_delay_4_to_pulse_train),
- .out_data_fwd(data_4_to_gen)
- );
- pulse_train_gen #(.WIDTH(FAST_PWM_WIDTH),.PULSE_COUNTER_WIDTH(PULSE_COUNTER_WIDTH)) pwm3(
- .nrst(nrst),
- .clk(clk),
- .trigger(trigger_delay_4_to_pulse_train),
- .npuls(npuls3_gen),
- .period(period3_gen),
- .duty(duty3_gen),
- .pwm_out(Out3)
- );
- endmodule
|