tdraudio: implement ΔΣ-DAC and volume control
This commit is contained in:
parent
d5888861d3
commit
a73fad5786
1 changed files with 53 additions and 10 deletions
|
|
@ -10,23 +10,30 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
input wire wr_en,
|
input wire wr_en,
|
||||||
|
|
||||||
output wire pdm_out,
|
output wire pdm_out,
|
||||||
output wire gain_en,
|
output wire gain_sel,
|
||||||
output wire shutdown_n
|
output wire shutdown_n
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam CLOCK_DIV_WIDTH = 22;
|
localparam CLOCK_DIV_WIDTH = 22;
|
||||||
|
localparam AMP_WIDTH = 16;
|
||||||
|
|
||||||
localparam TDRAU_REG_CTL = 0; /* control register */
|
localparam TDRAU_REG_CTL = 0; /* control register */
|
||||||
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
||||||
|
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
|
||||||
|
|
||||||
reg audio_out;
|
wire audio_out;
|
||||||
reg channel_enable;
|
reg channel_enable;
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
||||||
|
reg amp_phase;
|
||||||
|
reg [AMP_WIDTH-1:0] amp_start;
|
||||||
|
reg [AMP_WIDTH-1:0] amp_out;
|
||||||
|
|
||||||
|
reg [AMP_WIDTH:0] deltasigma_acc;
|
||||||
|
|
||||||
assign pdm_out = audio_out;
|
assign pdm_out = audio_out;
|
||||||
assign rd_data = {{DATA_WIDTH-8-CLOCK_DIV_WIDTH{1'b0}}, div_count, {7{1'b0}}, channel_enable};
|
assign rd_data = {{DATA_WIDTH-8-CLOCK_DIV_WIDTH{1'b0}}, div_count, {7{1'b0}}, channel_enable};
|
||||||
assign gain_en = 0;
|
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
||||||
assign shutdown_n = channel_enable;
|
assign shutdown_n = channel_enable;
|
||||||
|
|
||||||
/* channel enable flag */
|
/* channel enable flag */
|
||||||
|
|
@ -43,10 +50,21 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
begin
|
begin
|
||||||
if(reset)
|
if(reset)
|
||||||
clock_div <= 0;
|
clock_div <= 0;
|
||||||
else if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
else
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
||||||
clock_div <= wr_data;
|
clock_div <= wr_data;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/* amplitude register */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
amp_start <= 0;
|
||||||
|
else
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_AMP))
|
||||||
|
amp_start <= wr_data;
|
||||||
|
end
|
||||||
|
|
||||||
/* divider counter */
|
/* divider counter */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -59,16 +77,41 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
||||||
div_count <= 0; // set counter to zero whenever the clock divider is set
|
div_count <= 1; // start cycle in next clock tick
|
||||||
end
|
end
|
||||||
|
|
||||||
/* 1-bit audio output */
|
/* amplitude out */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
if (reset)
|
if (reset)
|
||||||
audio_out <= 0;
|
begin
|
||||||
else
|
amp_out <= 0;
|
||||||
if (channel_enable && (div_count == 0))
|
amp_phase <= 1;
|
||||||
audio_out <= ~audio_out;
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
if (channel_enable && (div_count == 0)) // invert amplitude on clock tick
|
||||||
|
begin
|
||||||
|
amp_out <= amp_phase ? amp_start : ~amp_start;
|
||||||
|
amp_phase <= ~amp_phase;
|
||||||
|
end
|
||||||
|
|
||||||
|
// reset phase bit when enabling the channel
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_CTL) && wr_data[0])
|
||||||
|
// when channel is enabled, phase will be flipped on next tick
|
||||||
|
// because div_count will become zero
|
||||||
|
amp_phase <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* delta-sigma DAC */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
deltasigma_acc <= 0;
|
||||||
|
else
|
||||||
|
if (channel_enable)
|
||||||
|
deltasigma_acc <= deltasigma_acc[AMP_WIDTH-1:0] + amp_out;
|
||||||
|
end
|
||||||
|
|
||||||
|
/* 1-bit audio output */
|
||||||
|
assign audio_out = deltasigma_acc[AMP_WIDTH];
|
||||||
endmodule
|
endmodule
|
||||||
Loading…
Add table
Add a link
Reference in a new issue