pwm.v 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * pwm.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
  7. * All rights reserved.
  8. *
  9. * BSD 3-clause, see LICENSE.bsd
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * * Neither the name of the <organization> nor the
  19. * names of its contributors may be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  26. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. `default_nettype none
  34. module pwm #(
  35. parameter integer WIDTH = 10,
  36. parameter PHY = "GENERIC"
  37. )(
  38. // PWM out
  39. output wire pwm,
  40. // Config
  41. input wire [WIDTH-1:0] cfg_val,
  42. input wire cfg_oe,
  43. // Clock / Reset
  44. input wire clk,
  45. input wire rst
  46. );
  47. // Signals
  48. wire [WIDTH:0] cnt_cycle_rst;
  49. reg [WIDTH:0] cnt_cycle;
  50. reg [WIDTH:0] cnt_on;
  51. wire pwm_i;
  52. // Cycle counter (counts 2^WIDTH - 1 cycles)
  53. assign cnt_cycle_rst = { { (WIDTH-1){1'b0} }, 2'b10 };
  54. always @(posedge clk or posedge rst)
  55. if (rst)
  56. cnt_cycle <= cnt_cycle_rst;
  57. else
  58. cnt_cycle <= cnt_cycle[WIDTH] ? cnt_cycle_rst : (cnt_cycle + 1);
  59. // ON counter (counts cycles with output high)
  60. always @(posedge clk or posedge rst)
  61. if (rst)
  62. cnt_on <= 0;
  63. else
  64. cnt_on <= cnt_cycle[WIDTH] ? { 1'b1, cfg_val } : (cnt_on - 1);
  65. assign pwm_i = cnt_on[WIDTH];
  66. // PHY (Basically just IO register)
  67. generate
  68. if (PHY == "NONE") begin
  69. // No PHY (and no OE support)
  70. assign pwm = pwm_i;
  71. end else if (PHY == "GENERIC") begin
  72. // Generic IO register, let tool figure it out
  73. reg pwm_d_r;
  74. reg pwm_oe_r;
  75. always @(posedge clk)
  76. begin
  77. pwm_d_r <= pwm_i;
  78. pwm_oe_r <= cfg_oe;
  79. end
  80. assign pwm = pwm_oe_r ? pwm_d_r : 1'bz;
  81. end else if (PHY == "ICE40") begin
  82. // iCE40 specific IOB
  83. SB_IO #(
  84. .PIN_TYPE(6'b110100),
  85. .PULLUP(1'b0),
  86. .NEG_TRIGGER(1'b0),
  87. .IO_STANDARD("SB_LVCMOS")
  88. ) io_reg_I (
  89. .PACKAGE_PIN(pwm),
  90. .LATCH_INPUT_VALUE(1'b0),
  91. .CLOCK_ENABLE(1'b1),
  92. .INPUT_CLK(1'b0),
  93. .OUTPUT_CLK(clk),
  94. .OUTPUT_ENABLE(cfg_oe),
  95. .D_OUT_0(pwm_i),
  96. .D_OUT_1(1'b0),
  97. .D_IN_0(),
  98. .D_IN_1()
  99. );
  100. end
  101. endgenerate
  102. endmodule // pwm