3signal.v 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * 3signal.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2025 Krzysztof Skrzynecki, Jakub Duchniewicz <j.duchniewicz@gmail.com>
  7. * SPDX-License-Identifier: TODO:
  8. */
  9. `default_nettype none
  10. module continous_pwm_gen#(
  11. parameter WIDTH = 16
  12. ) (
  13. input wire nrst, clk,
  14. input [WIDTH-1:0] period,
  15. input [WIDTH-1:0] delay,
  16. output wire [0:0] last_tick,
  17. output wire [0:0] mid_tick,
  18. output reg [0:0] pwm_out
  19. );
  20. reg [WIDTH-1:0] counter;
  21. wire [WIDTH-1:0] next_cnt=counter+1;
  22. wire [WIDTH-1:0] last_avail_cnt=period-1;
  23. // Counter logic
  24. always_ff @(posedge clk or negedge nrst) begin
  25. if (!nrst) begin
  26. counter <= 0;
  27. pwm_out <= 0;
  28. end else begin
  29. if(counter >= last_avail_cnt) begin
  30. counter <= 0;
  31. end else begin
  32. counter <= next_cnt;
  33. end
  34. if ((next_cnt<delay) || (counter>=last_avail_cnt)) begin
  35. pwm_out <= 0;
  36. end else begin
  37. pwm_out <= 1;
  38. end
  39. end
  40. end
  41. assign last_tick = (next_cnt>=period);
  42. assign mid_tick = ((next_cnt)==(period>>1));
  43. endmodule
  44. module single_shot_gen#(
  45. parameter WIDTH = 16
  46. )(
  47. input wire nrst, clk,
  48. input wire trigger,
  49. input [WIDTH-1:0] delay,
  50. input [WIDTH-1:0] duty,
  51. output reg [0:0] pwm_out
  52. );
  53. reg [WIDTH-1:0] counter;
  54. reg [0:0] is_counting;
  55. wire [WIDTH-1:0] next_cnt=counter+1;
  56. wire [WIDTH-1:0] period=delay+duty;
  57. //wire [WIDTH-1:0] last_avail_cnt=period-1;
  58. always_ff @(posedge clk or negedge nrst) begin
  59. if (!nrst) begin
  60. counter <= 0;
  61. is_counting <= 0;
  62. end else begin
  63. if (is_counting) begin
  64. if(counter+1 >= period) begin
  65. counter <= 0;
  66. is_counting <= 0;
  67. pwm_out <= 0;
  68. end else begin
  69. counter <= next_cnt;
  70. if (next_cnt>=delay) begin
  71. pwm_out <= 1;
  72. end else begin
  73. pwm_out <= 0;
  74. end
  75. end
  76. end else begin
  77. if (trigger) begin
  78. is_counting <= 1;
  79. if ((delay==0) && (duty!=0)) begin
  80. pwm_out <= 1;
  81. end
  82. end
  83. end
  84. end
  85. end
  86. endmodule
  87. module phase_delay#(
  88. parameter WIDTH = 16,
  89. parameter FORWARD_DATA_WIDTH = 16
  90. )(
  91. input wire nrst, clk,
  92. input wire in_trig,
  93. input [WIDTH-1:0] delay,
  94. input [FORWARD_DATA_WIDTH-1:0] in_data_fwd,
  95. output wire out_trig,
  96. output reg [FORWARD_DATA_WIDTH-1:0] out_data_fwd
  97. );
  98. reg [WIDTH-1:0] counter;
  99. reg [0:0] is_counting;
  100. reg [WIDTH-1:0] delay_latched;
  101. always_ff @(posedge clk or negedge nrst) begin
  102. if (!nrst) begin
  103. counter <= 0;
  104. is_counting <=0;
  105. delay_latched <=0;
  106. end else begin
  107. if (is_counting) begin
  108. if ((counter+1) >= delay_latched) begin
  109. counter <= 0;
  110. is_counting <= 0;
  111. end else begin
  112. counter <= counter+1;
  113. end
  114. end else begin
  115. if (in_trig) begin
  116. is_counting <= 1;
  117. out_data_fwd <= in_data_fwd;
  118. delay_latched <= delay;
  119. end
  120. end
  121. end
  122. end
  123. assign out_trig=((counter+1)>=delay) && is_counting;
  124. endmodule
  125. module pulse_train_gen#(
  126. parameter WIDTH = 16,
  127. parameter PULSE_COUNTER_WIDTH = 16
  128. )(
  129. input wire nrst, clk,
  130. input wire trigger,
  131. input [PULSE_COUNTER_WIDTH-1:0] npuls,
  132. input [WIDTH-1:0] period,
  133. input [WIDTH-1:0] duty,
  134. output reg [0:0] pwm_out
  135. );
  136. reg [WIDTH-1:0] counter;
  137. reg [0:0] is_counting;
  138. reg [PULSE_COUNTER_WIDTH-1:0] remaining_pulses;
  139. reg [WIDTH-1:0] period_local;
  140. reg [WIDTH-1:0] duty_local;
  141. wire [WIDTH-1:0] next_cnt = counter+1;
  142. always_ff @(posedge clk or negedge nrst) begin
  143. if (!nrst) begin
  144. counter <= 0;
  145. is_counting <= 0;
  146. pwm_out <=0;
  147. end else begin
  148. if (is_counting) begin
  149. if(next_cnt >= period) begin
  150. counter <= 0;
  151. if (remaining_pulses > 0) begin
  152. remaining_pulses <= remaining_pulses-1;
  153. pwm_out <= 1;
  154. end else begin
  155. pwm_out <= 0;
  156. is_counting <= 0;
  157. end
  158. end else begin
  159. counter <= next_cnt;
  160. if (next_cnt>=duty) begin
  161. pwm_out <= 0;
  162. end else begin
  163. pwm_out <= 1;
  164. end
  165. end
  166. end else begin
  167. if (trigger) begin
  168. if ((period>0) && (duty!=0) && (npuls>0)) begin
  169. pwm_out <= 1;
  170. remaining_pulses <= npuls-1;
  171. is_counting <= 1;
  172. counter <= 0;
  173. period_local <= period;
  174. duty_local <= duty;
  175. end
  176. end
  177. end
  178. end
  179. end
  180. endmodule
  181. typedef enum logic [1:0] {
  182. ODD_TRAIN_FORCE_OFF,
  183. ODD_TRAIN_ENA_CONTROL,
  184. ODD_TRAIN_FORCE_ON
  185. } odd_train_flag_t;
  186. module three_signal#(
  187. parameter FAST_PWM_WIDTH=8,
  188. parameter PULSE_COUNTER_WIDTH=8,
  189. parameter SLOW_PWM_WIDTH=14
  190. )(
  191. input wire nrst, clk,
  192. input [SLOW_PWM_WIDTH-1:0] period1,
  193. input [SLOW_PWM_WIDTH-1:0] delay1,
  194. input [SLOW_PWM_WIDTH-1:0] duty2,
  195. input [SLOW_PWM_WIDTH-1:0] delay2,
  196. input [FAST_PWM_WIDTH-1:0] period3,
  197. input [FAST_PWM_WIDTH-1:0] duty3,
  198. input [SLOW_PWM_WIDTH-1:0] delay3,//delay is wrt slow pwm, thus longer bit length
  199. input [PULSE_COUNTER_WIDTH-1:0] npuls3,
  200. input /*odd_train_flag_t*/ wire [1:0] odd_train_flag,
  201. input wire ena_odd_out3,
  202. output reg Out1,
  203. output reg Out2,
  204. output reg Out3
  205. );
  206. wire trigger_next_cycle;
  207. wire trigger_even_cycle;
  208. wire trigger_odd_cycle;
  209. wire [SLOW_PWM_WIDTH-1:0] delay3_part1;
  210. wire [SLOW_PWM_WIDTH-1:0] delay3_part234;
  211. assign delay3_part234 = delay3>>2;
  212. assign delay3_part1 = (delay3<4) ? 0 : (delay3 - (delay3_part234*3));
  213. continous_pwm_gen #(.WIDTH(SLOW_PWM_WIDTH)) pwm1(
  214. .nrst(nrst),
  215. .clk(clk),
  216. .period(period1),
  217. .delay(delay1),
  218. .last_tick(trigger_next_cycle),
  219. .mid_tick(trigger_even_cycle),
  220. .pwm_out(Out1)
  221. );
  222. single_shot_gen #(.WIDTH(SLOW_PWM_WIDTH)) pwm2(
  223. .nrst(nrst),
  224. .clk(clk),
  225. .trigger(trigger_next_cycle),
  226. .delay(delay2),
  227. .duty(duty2),
  228. .pwm_out(Out2)
  229. );
  230. wire trigger_delay_1_to_2;
  231. wire trigger_delay_2_to_3;
  232. wire trigger_delay_3_to_4;
  233. wire trigger_delay_4_to_pulse_train;
  234. localparam FORWARD_DATA_WIDTH = SLOW_PWM_WIDTH + PULSE_COUNTER_WIDTH + FAST_PWM_WIDTH + FAST_PWM_WIDTH;
  235. localparam DELAY_BITS_POS = PULSE_COUNTER_WIDTH + FAST_PWM_WIDTH + FAST_PWM_WIDTH;
  236. wire [FORWARD_DATA_WIDTH-1:0] data_1_to_2;
  237. wire [FORWARD_DATA_WIDTH-1:0] data_2_to_3;
  238. wire [FORWARD_DATA_WIDTH-1:0] data_3_to_4;
  239. wire [FORWARD_DATA_WIDTH-1:0] data_4_to_gen;
  240. assign trigger_odd_cycle =
  241. (odd_train_flag == ODD_TRAIN_ENA_CONTROL) ? trigger_next_cycle && ena_odd_out3 :
  242. (odd_train_flag == ODD_TRAIN_FORCE_ON) ? trigger_next_cycle :
  243. 0;
  244. wire [FAST_PWM_WIDTH-1:0] period3_gen;
  245. wire [FAST_PWM_WIDTH-1:0] duty3_gen;
  246. wire [PULSE_COUNTER_WIDTH-1:0] npuls3_gen;
  247. assign duty3_gen = data_4_to_gen[FAST_PWM_WIDTH-1:0];
  248. assign period3_gen = data_4_to_gen[FAST_PWM_WIDTH+FAST_PWM_WIDTH-1:FAST_PWM_WIDTH];
  249. assign npuls3_gen = data_4_to_gen[FAST_PWM_WIDTH+FAST_PWM_WIDTH+PULSE_COUNTER_WIDTH-1:FAST_PWM_WIDTH+FAST_PWM_WIDTH];
  250. phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_1of4(
  251. .nrst(nrst),
  252. .clk(clk),
  253. .in_trig(trigger_odd_cycle | trigger_even_cycle),
  254. .delay(delay3_part1),
  255. .in_data_fwd({delay3_part234, npuls3, period3, duty3}),
  256. .out_trig(trigger_delay_1_to_2),
  257. .out_data_fwd(data_1_to_2)
  258. );
  259. phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_2of4(
  260. .nrst(nrst),
  261. .clk(clk),
  262. .in_trig(trigger_delay_1_to_2),
  263. .delay(data_1_to_2[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
  264. .in_data_fwd(data_1_to_2),
  265. .out_trig(trigger_delay_2_to_3),
  266. .out_data_fwd(data_2_to_3)
  267. );
  268. phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_3of4(
  269. .nrst(nrst),
  270. .clk(clk),
  271. .in_trig(trigger_delay_2_to_3),
  272. .delay(data_2_to_3[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
  273. .in_data_fwd(data_2_to_3),
  274. .out_trig(trigger_delay_3_to_4),
  275. .out_data_fwd(data_3_to_4)
  276. );
  277. phase_delay #(.WIDTH(SLOW_PWM_WIDTH),.FORWARD_DATA_WIDTH(FORWARD_DATA_WIDTH)) pd_4of4(
  278. .nrst(nrst),
  279. .clk(clk),
  280. .in_trig(trigger_delay_3_to_4),
  281. .delay(data_3_to_4[DELAY_BITS_POS+SLOW_PWM_WIDTH-1:DELAY_BITS_POS]),
  282. .in_data_fwd(data_3_to_4),
  283. .out_trig(trigger_delay_4_to_pulse_train),
  284. .out_data_fwd(data_4_to_gen)
  285. );
  286. pulse_train_gen #(.WIDTH(FAST_PWM_WIDTH),.PULSE_COUNTER_WIDTH(PULSE_COUNTER_WIDTH)) pwm3(
  287. .nrst(nrst),
  288. .clk(clk),
  289. .trigger(trigger_delay_4_to_pulse_train),
  290. .npuls(npuls3_gen),
  291. .period(period3_gen),
  292. .duty(duty3_gen),
  293. .pwm_out(Out3)
  294. );
  295. endmodule