diff --git a/tridoracpu/tridoracpu.srcs/tdraudio.v b/tridoracpu/tridoracpu.srcs/tdraudio.v index dbd0dc3..ac87abf 100644 --- a/tridoracpu/tridoracpu.srcs/tdraudio.v +++ b/tridoracpu/tridoracpu.srcs/tdraudio.v @@ -10,23 +10,30 @@ module tdraudio #(DATA_WIDTH=32) ( input wire wr_en, output wire pdm_out, - output wire gain_en, + output wire gain_sel, output wire shutdown_n ); localparam CLOCK_DIV_WIDTH = 22; + localparam AMP_WIDTH = 16; localparam TDRAU_REG_CTL = 0; /* control 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 [CLOCK_DIV_WIDTH-1:0] clock_div; 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 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; /* channel enable flag */ @@ -43,10 +50,21 @@ module tdraudio #(DATA_WIDTH=32) ( begin if(reset) 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; 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 */ always @(posedge clk) begin @@ -59,16 +77,41 @@ module tdraudio #(DATA_WIDTH=32) ( end else 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 - /* 1-bit audio output */ + /* amplitude out */ always @(posedge clk) begin if (reset) - audio_out <= 0; + begin + amp_out <= 0; + amp_phase <= 1; + end else - if (channel_enable && (div_count == 0)) - audio_out <= ~audio_out; + 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 -endmodule + + /* 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 \ No newline at end of file