pdm.v 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * pdm.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Pulse Density Modulation core (1st order with dither)
  7. *
  8. * Copyright (C) 2019 Sylvain Munaut <tnt@246tNt.com>
  9. * All rights reserved.
  10. *
  11. * BSD 3-clause, see LICENSE.bsd
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * * Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * * Neither the name of the <organization> nor the
  21. * names of its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  26. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  27. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  28. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  29. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  30. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  31. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. `default_nettype none
  36. module pdm #(
  37. parameter integer WIDTH = 8,
  38. parameter PHY = "GENERIC",
  39. parameter DITHER = "NO"
  40. )(
  41. input wire [WIDTH-1:0] in,
  42. output wire pdm,
  43. input wire oe,
  44. input wire clk,
  45. input wire rst
  46. );
  47. // Signals
  48. wire [WIDTH:0] in_i;
  49. reg [WIDTH:0] acc;
  50. reg dither;
  51. wire pdm_i;
  52. // Delta Sigma
  53. assign in_i = { acc[WIDTH], in };
  54. always @(posedge clk)
  55. begin
  56. if (rst)
  57. acc <= 0;
  58. else
  59. acc <= acc + in_i + dither;
  60. end
  61. assign pdm_i = acc[WIDTH];
  62. // Dither generator
  63. generate
  64. if (DITHER == "YES") begin
  65. wire [7:0] lfsr_out;
  66. pdm_lfsr #(
  67. .WIDTH(8),
  68. .POLY(8'h71)
  69. ) lfsr_I (
  70. .out(lfsr_out),
  71. .clk(clk),
  72. .rst(rst)
  73. );
  74. always @(posedge clk)
  75. dither <= lfsr_out[0] ^ lfsr_out[3];
  76. end else begin
  77. always @(posedge clk)
  78. dither <= 1'b0;
  79. end
  80. endgenerate
  81. // PHY (Basically just IO register)
  82. generate
  83. if (PHY == "GENERIC") begin
  84. reg pdm_r;
  85. always @(posedge clk)
  86. pdm_r <= oe ? pdm_i : 1'bz;
  87. assign pdm = pdm_r;
  88. end else if (PHY == "ICE40") begin
  89. SB_IO #(
  90. .PIN_TYPE(6'b110100),
  91. .PULLUP(1'b0),
  92. .NEG_TRIGGER(1'b0),
  93. .IO_STANDARD("SB_LVCMOS")
  94. ) io_reg_I (
  95. .PACKAGE_PIN(pdm),
  96. .LATCH_INPUT_VALUE(1'b0),
  97. .CLOCK_ENABLE(1'b1),
  98. .INPUT_CLK(1'b0),
  99. .OUTPUT_CLK(clk),
  100. .OUTPUT_ENABLE(oe),
  101. .D_OUT_0(pdm_i),
  102. .D_OUT_1(1'b0),
  103. .D_IN_0(),
  104. .D_IN_1()
  105. );
  106. end
  107. endgenerate
  108. endmodule // pdm
  109. module pdm_lfsr #(
  110. parameter integer WIDTH = 8,
  111. parameter POLY = 8'h71
  112. )(
  113. output reg [WIDTH-1:0] out,
  114. input wire clk,
  115. input wire rst
  116. );
  117. // Signals
  118. wire fb;
  119. // Linear Feedback
  120. assign fb = ^(out & POLY);
  121. // Register
  122. always @(posedge clk)
  123. if (rst)
  124. out <= { {(WIDTH-1){1'b0}}, 1'b1 };
  125. else
  126. out <= { fb, out[WIDTH-1:1] };
  127. endmodule // pdm_lfsr