summaryrefslogtreecommitdiffstats
path: root/sound.v
blob: 692df59891d731e4e33a2c2ddb996d6d8f801b86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * sound.v
 *
 * Circuit to generate PDM sound using an Altera Nios board with an
 * AleaRep Lancelot sound add-on.
 *
 * This module should be fed with a 100 MHz clock from the PLL.
 * 
 * This is a second-order delta-sigma DAC, assuming an external
 * low pass filter.
 */

//
// The number of extra bits of precision (XBITS) necessary isn't very
// clear.  I ran the contents of a full CD through a simulator of the
// algorithm, and came up with at least one transition which required
// 6 extra bits.
//
`define MSB	(BITS-1)
`define XBITS   6		// Additional bits of precision
`define DBITS	(`MSB+`XBITS)

module sound(
	     reset_n,
	     clk,
	     data,
	     audio,
	     audio_clk,
	     );

   parameter BITS = 16;

   input          reset_n;
   input	  clk;
   input [`MSB:0] data;
   output	  audio;
   output         audio_clk;

   reg [`MSB:0] 	data_latch;
   wire [`DBITS:0] 	xdata;	// Expanded data

   wire [`DBITS:0] 	delta2_add;
   wire [`DBITS:0] 	delta_add;

   wire [`DBITS:0] 	sigma2_add;
   wire [`DBITS:0] 	sigma_add;

   reg [`DBITS:0] 	sigma2_latch;
   reg [`DBITS:0] 	sigma_latch;

   wire [`DBITS:0] 	delta;

   reg [11:0] 		pulse_ctr = 0;
   
   // Note: the input is expected *signed*.  For unsigned input, invert
   // bit `MSB.  This is a change from previous code.
   assign	xdata[`DBITS:BITS] = {`XBITS{data_latch[`MSB]}};
   assign	xdata[`MSB:0] = data_latch;

   assign	delta2_add = xdata + delta;
   assign	sigma2_add = delta2_add + sigma2_latch;
   
   assign 	delta_add = sigma2_add + delta;
   assign 	sigma_add = delta_add + sigma_latch;

   // delta is -32768 if sigma_latch is negative, otherwise 32768
   assign 	delta[`DBITS:BITS] = {`XBITS{sigma_latch[`DBITS]}};
   assign	delta[`MSB] = 1'b1;
   assign 	delta[`MSB-1:0] = 0;

   always @(negedge reset_n or posedge clk)
     if (~reset_n)
       begin
	  pulse_ctr <= 0;
	  sigma_latch <= 0;
	  sigma2_latch <= 0;
       end
        else
       begin
	  if ( pulse_ctr == 0 )
	    begin
	       // 2268 is the oversampling ratio (100 MHz/44100 Hz)
	       pulse_ctr <= 2268-1;
	       data_latch <= data;
	    end
	  else
	    begin
	       pulse_ctr <= pulse_ctr-1;
	    end

	  sigma_latch  <= sigma_add;
	  sigma2_latch <= sigma2_add;
       end

   assign audio     = sigma_latch[`DBITS];
   assign audio_clk = pulse_ctr[11];
   
endmodule // sound